Compare commits

...
13 Commits
Author SHA1 Message Date
Marc Klingen 4aba13ec35 chore: release v2.4.0
CI/CD / lint (push) Waiting to run
CI/CD / test-docker-build (push) Waiting to run
CI/CD / tests (18) (push) Waiting to run
CI/CD / tests (20) (push) Waiting to run
CI/CD / e2e-tests (push) Waiting to run
CI/CD / all-ci-passed (push) Blocked by required conditions
CI/CD / push-docker-image (push) Blocked by required conditions
release.yml / release (push) Waiting to run
2024-02-12 17:52:28 +01:00
Marc Klingen 0f5d5cd9a0 fix(ui): invalidation of traces after delete 2024-02-12 17:46:58 +01:00
Marc KlingenandGitHub 78df145e20 fix(ui): invalidation of traces when deleting a single trace (#1134) 2024-02-12 12:00:57 +00:00
Max DeichmannandGitHub b35618f1c9 refactor: add betterstack env variable to env.prod.example (#1132) 2024-02-12 10:17:51 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a139ada85e chore(deps): bump the sentry group with 3 updates (#1110)
Bumps the sentry group with 3 updates: [@sentry/nextjs](https://github.com/getsentry/sentry-javascript), [@sentry/profiling-node](https://github.com/getsentry/sentry-javascript) and [@sentry/types](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/nextjs` from 7.99.0 to 7.100.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.100.1/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.99.0...7.100.1)

Updates `@sentry/profiling-node` from 1.3.5 to 7.100.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.100.1/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/commits/7.100.1)

Updates `@sentry/types` from 7.99.0 to 7.100.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.100.1/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.99.0...7.100.1)

---
updated-dependencies:
- dependency-name: "@sentry/nextjs"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/profiling-node"
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: sentry
- dependency-name: "@sentry/types"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 00:07:57 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
cdfb0c6b7c chore(deps): bump posthog-js from 1.104.4 to 1.105.7 (#1131)
Bumps [posthog-js](https://github.com/PostHog/posthog-js) from 1.104.4 to 1.105.7.
- [Release notes](https://github.com/PostHog/posthog-js/releases)
- [Changelog](https://github.com/PostHog/posthog-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js/compare/v1.104.4...1.105.7)

---
updated-dependencies:
- dependency-name: posthog-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 01:02:10 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c0bbf39b29 chore(deps-dev): bump the patches group with 3 updates (#1130)
Bumps the patches group with 3 updates: [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom), [postcss](https://github.com/postcss/postcss) and [tsx](https://github.com/privatenumber/tsx).


Updates `@types/react-dom` from 18.2.18 to 18.2.19
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `postcss` from 8.4.34 to 8.4.35
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.34...8.4.35)

Updates `tsx` from 4.7.0 to 4.7.1
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/develop/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.7.0...v4.7.1)

---
updated-dependencies:
- dependency-name: "@types/react-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: tsx
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-11 23:44:28 +00:00
Marc Klingen a6900ad3c4 fix(ui): use lightner colors in observation tree 2024-02-12 00:31:00 +01:00
21940a0464 feat(ui): improve trace view: collapse/expand observation tree + color coding of observation types (#916)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-11 23:47:46 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fe642f8e9e chore(deps-dev): bump @typescript-eslint/eslint-plugin from 6.20.0 to 6.21.0 (#1112)
chore(deps-dev): bump @typescript-eslint/eslint-plugin

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.20.0 to 6.21.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.21.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-11 22:05:53 +00:00
c803b0d9c2 feat(ui): delete prompts and prompt versions + deduplication of prompt variables (#1116)
* fix and feat: update Var renaming and add functionality to delete prompt and versions

* pass ci by removing unused components

* ux improvements

---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-11 22:00:31 +00:00
Marc KlingenandGitHub e7086cf044 fix(ci): temporarily fix modelmatch test by waiting 5 sec (#1129)
* fix(ci): temporarily fix modelmatch test by waiting 5 sec

* fix
2024-02-11 21:56:19 +00:00
Marc KlingenandGitHub 9d49bbe987 chore(ui): responsive layout (#1126) 2024-02-10 03:29:38 +00:00
20 changed files with 640 additions and 366 deletions
+3
View File
@@ -81,6 +81,9 @@ SALT="salt"
# NEXT_SENTRY_PROJECT=
# SENTRY_AUTH_TOKEN=
# Betterstack
# LANGFUSE_TEAM_BETTERSTACK_TOKEN=
# Demo project that users can use to try the platform
# NEXT_PUBLIC_DEMO_PROJECT_ID=
+5 -1
View File
@@ -48,4 +48,8 @@ yarn-error.log*
/generated/typescript-server
# openapi spec that is copied during build
/public/openapi*.yml
/public/openapi*.yml
# vscode
.devcontainer
+144 -246
View File
@@ -1,12 +1,12 @@
{
"name": "langfuse-core",
"version": "2.3.0",
"version": "2.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "langfuse-core",
"version": "2.3.0",
"version": "2.4.0",
"hasInstallScript": true,
"dependencies": {
"@anthropic-ai/tokenizer": "^0.0.4",
@@ -39,8 +39,8 @@
"@radix-ui/react-tooltip": "^1.0.7",
"@react-email/components": "^0.0.14",
"@react-email/render": "^0.0.12",
"@sentry/nextjs": "^7.99.0",
"@sentry/profiling-node": "^1.3.5",
"@sentry/nextjs": "^7.100.1",
"@sentry/profiling-node": "^7.100.1",
"@sentry/types": "^7.88.0",
"@t3-oss/env-nextjs": "^0.8.0",
"@tailwindcss/forms": "^0.5.7",
@@ -68,7 +68,7 @@
"next-auth": "^4.24.5",
"next-query-params": "^5.0.0",
"nodemailer": "^6.9.9",
"posthog-js": "^1.104.4",
"posthog-js": "^1.105.7",
"posthog-node": "^3.6.2",
"react": "18.2.0",
"react-day-picker": "^8.10.0",
@@ -100,9 +100,9 @@
"@types/node": "20.10.5",
"@types/nodemailer": "^6.4.14",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.18",
"@types/react-dom": "^18.2.19",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"autoprefixer": "^10.4.17",
"dotenv-cli": "^7.3.0",
@@ -110,7 +110,7 @@
"eslint-config-next": "^14.1.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8.4.34",
"postcss": "^8.4.35",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"prisma": "^5.9.1",
@@ -119,7 +119,7 @@
"tailwindcss": "^3.4.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"tsx": "^4.7.0",
"tsx": "^4.7.1",
"typescript": "^5.3.3"
},
"optionalDependencies": {
@@ -4969,57 +4969,57 @@
}
},
"node_modules/@sentry-internal/feedback": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.99.0.tgz",
"integrity": "sha512-exIO1o+bE0MW4z30FxC0cYzJ4ZHSMlDPMHCBDPzU+MWGQc/fb8s58QUrx5Dnm6HTh9G3H+YlroCxIo9u0GSwGQ==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.100.1.tgz",
"integrity": "sha512-yqcRVnjf+qS+tC4NxOKLJOaSJ+csHmh/dHUzvCTkf5rLsplwXYRnny2r0tqGTQ4tuXMxwgSMKPYwicg81P+xuw==",
"dependencies": {
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
"@sentry/core": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.99.0.tgz",
"integrity": "sha512-PoIkfusToDq0snfl2M6HJx/1KJYtXxYhQplrn11kYadO04SdG0XGXf4h7wBTMEQ7LDEAtQyvsOu4nEQtTO3YjQ==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.100.1.tgz",
"integrity": "sha512-TnqxqJGhbFhhYRhTG2WLFer+lVieV7mNGeIxFBiw1L4kuj8KGl+C0sknssKyZSRVJFSahhHIosHJGRMkkD//7g==",
"dependencies": {
"@sentry/core": "7.99.0",
"@sentry/replay": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
"@sentry/core": "7.100.1",
"@sentry/replay": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/tracing": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.99.0.tgz",
"integrity": "sha512-z3JQhHjoM1KdM20qrHwRClKJrNLr2CcKtCluq7xevLtXHJWNAQQbafnWD+Aoj85EWXBzKt9yJMv2ltcXJ+at+w==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.100.1.tgz",
"integrity": "sha512-+u9RRf5eL3StiyiRyAHZmdkAR7GTSGx4Mt4Lmi5NEtCcWlTGZ1QgW2r8ZbhouVmTiJkjhQgYCyej3cojtazeJg==",
"dependencies": {
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
"@sentry/core": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.99.0.tgz",
"integrity": "sha512-bgfoUv3wkwwLgN5YUOe0ibB3y268ZCnamZh6nLFqnY/UBKC1+FXWFdvzVON/XKUm62LF8wlpCybOf08ebNj2yg==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.100.1.tgz",
"integrity": "sha512-IxHQ08ixf0bmaWpe4yt1J4UUsOpg02fxax9z3tOQYXw5MSzz5pDXn8M8DFUVJB3wWuyXhHXTub9yD3VIP9fnoA==",
"dependencies": {
"@sentry-internal/feedback": "7.99.0",
"@sentry-internal/replay-canvas": "7.99.0",
"@sentry-internal/tracing": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/replay": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
"@sentry-internal/feedback": "7.100.1",
"@sentry-internal/replay-canvas": "7.100.1",
"@sentry-internal/tracing": "7.100.1",
"@sentry/core": "7.100.1",
"@sentry/replay": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1"
},
"engines": {
"node": ">=8"
@@ -5046,25 +5046,25 @@
}
},
"node_modules/@sentry/core": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.99.0.tgz",
"integrity": "sha512-vOAtzcAXEUtS/oW7wi3wMkZ3hsb5Ch96gKyrrj/mXdOp2zrcwdNV6N9/pawq2E9P/7Pw8AXw4CeDZztZrjQLuA==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.100.1.tgz",
"integrity": "sha512-f+ItUge/o9AjlveQq0ZUbQauKlPH1FIJbC1TRaYLJ4KNfOdrsh8yZ29RmWv0cFJ/e+FGTr603gWpRPObF5rM8Q==",
"dependencies": {
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/integrations": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.99.0.tgz",
"integrity": "sha512-q4Nwpc27DTWlR7nDerd1o6KHlT/0usK+3xfBTZ1feVIAHCxt6ohCyZdoQ97+4kQiJJdX47MEmJYsXUlj62yZNg==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.100.1.tgz",
"integrity": "sha512-RUyZHcsN3Plc8G4hJN3BCMdbwS8ljUY3E3iLjzucA4HroBsGk5AMc6n7Pp/QqFIRgxrPjKEgA52Wgy5Nq6dSvw==",
"dependencies": {
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0",
"@sentry/core": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1",
"localforage": "^1.8.1"
},
"engines": {
@@ -5072,18 +5072,18 @@
}
},
"node_modules/@sentry/nextjs": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-7.99.0.tgz",
"integrity": "sha512-8eeEPFJjRBiCp2sFUhDLQFdWFagQ2yBvmALZIOIuoMei69N+clYVSxz84beeztbLal0zvRadJO5LAkBCb6d66Q==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-7.100.1.tgz",
"integrity": "sha512-JIDS8oQrr/xrU5llXNVoLnFJCFdS7+k6FVrtW7JnP9B+0NmILEVS3jqbabhh+af9Ch67DPZ2G4KWDRIDZE5HSQ==",
"dependencies": {
"@rollup/plugin-commonjs": "24.0.0",
"@sentry/core": "7.99.0",
"@sentry/integrations": "7.99.0",
"@sentry/node": "7.99.0",
"@sentry/react": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0",
"@sentry/vercel-edge": "7.99.0",
"@sentry/core": "7.100.1",
"@sentry/integrations": "7.100.1",
"@sentry/node": "7.100.1",
"@sentry/react": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1",
"@sentry/vercel-edge": "7.100.1",
"@sentry/webpack-plugin": "1.21.0",
"chalk": "3.0.0",
"resolve": "1.22.8",
@@ -5105,47 +5105,44 @@
}
},
"node_modules/@sentry/node": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.99.0.tgz",
"integrity": "sha512-34wYtLddnPcQ8qvKq62AfxowaMFw+GMUZGv7fIs9FxeBqqqn6Ckl0gFCTADudIIBQ3rSbmN7sHJIXdyiQv+pcw==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.100.1.tgz",
"integrity": "sha512-jB6tBLr7BpgdE2SlYZu343vvpa5jMFnqyFlprr+jdDu/ayNF4idB0qFwQe8p4C6LI6M/MNDRLVOgPBiCjjZSpw==",
"dependencies": {
"@sentry-internal/tracing": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
"@sentry-internal/tracing": "7.100.1",
"@sentry/core": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/profiling-node": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@sentry/profiling-node/-/profiling-node-1.3.5.tgz",
"integrity": "sha512-n2bfEbtLW3WuIMQGyxKJKzBNZOb1JYfMeJQ2WQn/42F++69m+u7T0S3EDGRN0Y//fbt5+r0any+4r3kChRXZkQ==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/profiling-node/-/profiling-node-7.100.1.tgz",
"integrity": "sha512-Q/B7SntzB/qt0Y/MZK8dBy8PIf6nCT/kdnn+wrTIFicxozqsF3hq5vmKvGyVUWobb3FrNjc2dSuDXTijN1xmkQ==",
"hasInstallScript": true,
"dependencies": {
"detect-libc": "^2.0.2",
"node-abi": "^3.52.0"
},
"bin": {
"sentry-prune-profiler-binaries": "scripts/prune-profiler-binaries.mjs"
"sentry-prune-profiler-binaries": "scripts/prune-profiler-binaries.js"
},
"engines": {
"node": ">=8.0.0"
},
"peerDependencies": {
"@sentry/node": "^7.44.1"
}
},
"node_modules/@sentry/react": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.99.0.tgz",
"integrity": "sha512-RtHwgzMHJhzJfSQpVG0SDPQYMTGDX3Q37/YWI59S4ALMbSW4/F6n/eQAvGVYZKbh2UCSqgFuRWaXOYkSZT17wA==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.100.1.tgz",
"integrity": "sha512-EdrBtrXVLK2LSx4Rvz/nQP7HZUZQmr+t3GHV8436RAhF6vs5mntACVMBoQJRWiUvtZ1iRo3rIsIdah7DLiFPgQ==",
"dependencies": {
"@sentry/browser": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0",
"@sentry/browser": "7.100.1",
"@sentry/core": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1",
"hoist-non-react-statics": "^3.3.2"
},
"engines": {
@@ -5156,47 +5153,47 @@
}
},
"node_modules/@sentry/replay": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.99.0.tgz",
"integrity": "sha512-gyN/I2WpQrLAZDT+rScB/0jnFL2knEVBo8U8/OVt8gNP20Pq8T/rDZKO/TG0cBfvULDUbJj2P4CJryn2p/O2rA==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.100.1.tgz",
"integrity": "sha512-B1NFjzGEFaqejxBRdUyEzH8ChXc2kfiqlA/W/Lg0aoWIl2/7nuMk+l4ld9gW5F5bIAXDTVd5vYltb1lWEbpr7w==",
"dependencies": {
"@sentry-internal/tracing": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
"@sentry-internal/tracing": "7.100.1",
"@sentry/core": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry/types": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.99.0.tgz",
"integrity": "sha512-94qwOw4w40sAs5mCmzcGyj8ZUu/KhnWnuMZARRq96k+SjRW/tHFAOlIdnFSrt3BLPvSOK7R3bVAskZQ0N4FTmA==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.100.1.tgz",
"integrity": "sha512-fLM+LedHuKzOd8IhXBqaQuym+AA519MGjeczBa5kGakes/BbAsUMwsNfjsKQedp7Kh44RgYF99jwoRPK2oDrXw==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/utils": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.99.0.tgz",
"integrity": "sha512-cYZy5WNTkWs5GgggGnjfGqC44CWir0pAv4GVVSx0fsup4D4pMKBJPrtub15f9uC+QkUf3vVkqwpBqeFxtmJQTQ==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.100.1.tgz",
"integrity": "sha512-Ve6dXr1o6xiBe3VCoJgiutmBKrugryI65EZAbYto5XI+t+PjiLLf9wXtEMF24ZrwImo4Lv3E9Uqza+fWkEbw6A==",
"dependencies": {
"@sentry/types": "7.99.0"
"@sentry/types": "7.100.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/vercel-edge": {
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-7.99.0.tgz",
"integrity": "sha512-9Uw3Iuy8KMlcv71ifnaguwndb1NkHeOAbYcBEeq9W+n0f5ocFZvMlnwszSlVNAL3cK+hlpcBhelXNAO/mBWCfg==",
"version": "7.100.1",
"resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-7.100.1.tgz",
"integrity": "sha512-SEWX7KAQreAQREHv+AYm50f/yK8nkq0DQHBQhr+UNZFKbWtSvytbkSmt4HgvOO6nbx9jeAIcg6Z1IKPYNGLKfg==",
"dependencies": {
"@sentry-internal/tracing": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
"@sentry-internal/tracing": "7.100.1",
"@sentry/core": "7.100.1",
"@sentry/types": "7.100.1",
"@sentry/utils": "7.100.1"
},
"engines": {
"node": ">=8"
@@ -6591,9 +6588,9 @@
}
},
"node_modules/@types/react-dom": {
"version": "18.2.18",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz",
"integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==",
"version": "18.2.19",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz",
"integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==",
"devOptional": true,
"dependencies": {
"@types/react": "*"
@@ -6606,9 +6603,9 @@
"devOptional": true
},
"node_modules/@types/semver": {
"version": "7.5.6",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz",
"integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==",
"version": "7.5.7",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz",
"integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==",
"dev": true
},
"node_modules/@types/stack-utils": {
@@ -6655,16 +6652,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.20.0.tgz",
"integrity": "sha512-fTwGQUnjhoYHeSF6m5pWNkzmDDdsKELYrOBxhjMrofPqCkoC2k3B2wvGHFxa1CTIqkEn88nlW1HVMztjo2K8Hg==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
"integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.5.1",
"@typescript-eslint/scope-manager": "6.20.0",
"@typescript-eslint/type-utils": "6.20.0",
"@typescript-eslint/utils": "6.20.0",
"@typescript-eslint/visitor-keys": "6.20.0",
"@typescript-eslint/scope-manager": "6.21.0",
"@typescript-eslint/type-utils": "6.21.0",
"@typescript-eslint/utils": "6.21.0",
"@typescript-eslint/visitor-keys": "6.21.0",
"debug": "^4.3.4",
"graphemer": "^1.4.0",
"ignore": "^5.2.4",
@@ -6717,7 +6714,7 @@
}
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
"node_modules/@typescript-eslint/scope-manager": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
"integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
@@ -6734,113 +6731,14 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
"integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
"integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.21.0",
"@typescript-eslint/visitor-keys": "6.21.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"minimatch": "9.0.3",
"semver": "^7.5.4",
"ts-api-utils": "^1.0.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
"integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.21.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/parser/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@typescript-eslint/parser/node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.20.0.tgz",
"integrity": "sha512-p4rvHQRDTI1tGGMDFQm+GtxP1ZHyAh64WANVoyEcNMpaTFn3ox/3CcgtIlELnRfKzSs/DwYlDccJEtr3O6qBvA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.20.0",
"@typescript-eslint/visitor-keys": "6.20.0"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.20.0.tgz",
"integrity": "sha512-qnSobiJQb1F5JjN0YDRPHruQTrX7ICsmltXhkV536mp4idGAYrIyr47zF/JmkJtEcAVnIz4gUYJ7gOZa6SmN4g==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
"integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==",
"dev": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "6.20.0",
"@typescript-eslint/utils": "6.20.0",
"@typescript-eslint/typescript-estree": "6.21.0",
"@typescript-eslint/utils": "6.21.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.0.1"
},
@@ -6861,9 +6759,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.20.0.tgz",
"integrity": "sha512-MM9mfZMAhiN4cOEcUOEx+0HmuaW3WBfukBZPCfwSqFnQy0grXYtngKCqpQN339X3RrwtzspWJrpbrupKYUSBXQ==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
"integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -6874,13 +6772,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.20.0.tgz",
"integrity": "sha512-RnRya9q5m6YYSpBN7IzKu9FmLcYtErkDkc8/dKv81I9QiLLtVBHrjz+Ev/crAqgMNW2FCsoZF4g2QUylMnJz+g==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
"integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.20.0",
"@typescript-eslint/visitor-keys": "6.20.0",
"@typescript-eslint/types": "6.21.0",
"@typescript-eslint/visitor-keys": "6.21.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -6926,17 +6824,17 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.20.0.tgz",
"integrity": "sha512-/EKuw+kRu2vAqCoDwDCBtDRU6CTKbUmwwI7SH7AashZ+W+7o8eiyy6V2cdOqN49KsTcASWsC5QeghYuRDTyOOg==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
"integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
"@typescript-eslint/scope-manager": "6.20.0",
"@typescript-eslint/types": "6.20.0",
"@typescript-eslint/typescript-estree": "6.20.0",
"@typescript-eslint/scope-manager": "6.21.0",
"@typescript-eslint/types": "6.21.0",
"@typescript-eslint/typescript-estree": "6.21.0",
"semver": "^7.5.4"
},
"engines": {
@@ -6951,12 +6849,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.20.0.tgz",
"integrity": "sha512-E8Cp98kRe4gKHjJD4NExXKz/zOJ1A2hhZc+IMVD6i7w4yjIvh6VyuRI0gRtxAsXtoC35uGMaQ9rjI2zJaXDEAw==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
"integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.20.0",
"@typescript-eslint/types": "6.21.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
@@ -14988,9 +14886,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.34",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.34.tgz",
"integrity": "sha512-4eLTO36woPSocqZ1zIrFD2K1v6wH7pY1uBh0JIM2KKfrVtGvPFiAku6aNOP0W1Wr9qwnaCsF0Z+CrVnryB2A8Q==",
"version": "8.4.35",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
"integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==",
"funding": [
{
"type": "opencollective",
@@ -15120,9 +15018,9 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
"node_modules/posthog-js": {
"version": "1.104.4",
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.104.4.tgz",
"integrity": "sha512-eZyNh0mhyfC129udFh5ln1QnUy67cPnRITVFvcOK4hdniM1v+T+cPxAkQK+4CjdHvvLM8hjh6OhiMWfppYqUzA==",
"version": "1.105.7",
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.105.7.tgz",
"integrity": "sha512-skpVufQrYllZ4Hi5bdBfe1F9pzeym1rlXUuvKbEYbMhmA+FCz47ZZ0zDX6a72A5hqPW5h7ZBTEJZbwad7jYt1A==",
"dependencies": {
"fflate": "^0.4.8",
"preact": "^10.19.3"
@@ -17675,9 +17573,9 @@
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/tsx": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.0.tgz",
"integrity": "sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==",
"version": "4.7.1",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.7.1.tgz",
"integrity": "sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==",
"dev": true,
"dependencies": {
"esbuild": "~0.19.10",
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "langfuse-core",
"version": "2.3.0",
"version": "2.4.0",
"private": true,
"scripts": {
"prebuild": "cp generated/openapi-client/openapi.yml public/openapi-client.yml && cp generated/openapi-server/openapi.yml public/openapi-server.yml",
@@ -59,8 +59,8 @@
"@radix-ui/react-tooltip": "^1.0.7",
"@react-email/components": "^0.0.14",
"@react-email/render": "^0.0.12",
"@sentry/nextjs": "^7.99.0",
"@sentry/profiling-node": "^1.3.5",
"@sentry/nextjs": "^7.100.1",
"@sentry/profiling-node": "^7.100.1",
"@sentry/types": "^7.88.0",
"@t3-oss/env-nextjs": "^0.8.0",
"@tailwindcss/forms": "^0.5.7",
@@ -88,7 +88,7 @@
"next-auth": "^4.24.5",
"next-query-params": "^5.0.0",
"nodemailer": "^6.9.9",
"posthog-js": "^1.104.4",
"posthog-js": "^1.105.7",
"posthog-node": "^3.6.2",
"react": "18.2.0",
"react-day-picker": "^8.10.0",
@@ -120,9 +120,9 @@
"@types/node": "20.10.5",
"@types/nodemailer": "^6.4.14",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.18",
"@types/react-dom": "^18.2.19",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"autoprefixer": "^10.4.17",
"dotenv-cli": "^7.3.0",
@@ -130,7 +130,7 @@
"eslint-config-next": "^14.1.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8.4.34",
"postcss": "^8.4.35",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"prisma": "^5.9.1",
@@ -139,7 +139,7 @@
"tailwindcss": "^3.4.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"tsx": "^4.7.0",
"tsx": "^4.7.1",
"typescript": "^5.3.3"
},
"ct3aMetadata": {
+5 -1
View File
@@ -92,5 +92,9 @@ describe("model match", () => {
expect(observation.promptTokens).toBeGreaterThan(0);
expect(observation.completionTokens).toBeGreaterThan(0);
});
});
// temporary fix: wait for 5 additional seconds to ensure that the model match is complete
// had issue with the test failing because the model match was not complete and logged to console
await new Promise((resolve) => setTimeout(resolve, 5000));
}, 10000);
});
+2 -5
View File
@@ -30,12 +30,9 @@ export function DeleteTrace({
const mutDeleteTraces = api.traces.deleteMany.useMutation({
onSuccess: () => {
setIsDeleted(true);
void utils.traces.invalidate();
if (!isTableAction) {
void router
.push(`/project/${projectId}/traces`)
.then(() => utils.traces.invalidate());
} else {
void utils.traces.invalidate();
void router.push(`/project/${projectId}/traces`);
}
},
});
+1 -1
View File
@@ -40,7 +40,7 @@ export default function Header({
[...props.breadcrumb.map((i) => i.href).filter(Boolean)].pop();
return (
<div className={cn(level === "h2" ? "mb-8" : "mb-1")}>
<div className={cn(level === "h2" ? "mb-4" : "mb-1")}>
<div>
{backHref ? (
<nav className="sm:hidden" aria-label="Back">
+5 -5
View File
@@ -492,21 +492,21 @@ export default function Layout(props: PropsWithChildren) {
<Info className="h-4 w-4" />
<span className="font-semibold">DEMO (view-only)</span>
</div>
<div>Live data from the Langfuse Q&A Chatbot.</div>
<div>Use demo RAG chat to see live data in this project.</div>
</div>
<Button size="sm" asChild className="ml-2">
<Link
href={
env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION === "EU"
? "https://langfuse.com/docs/qa-chatbot"
: "https://docs-staging.langfuse.com/docs/qa-chatbot"
? "https://langfuse.com/docs/demo"
: "https://docs-staging.langfuse.com/docs/demo"
}
target="_blank"
>
{env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION === "EU"
? "Q&A Chatbot ↗"
: "Q&A Chatbot (staging) ↗"}
? "Use Chat ↗"
: "Use Chat (staging) ↗"}
</Link>
</Button>
</div>
+167 -86
View File
@@ -1,14 +1,21 @@
import { type NestedObservation } from "@/src/utils/types";
import { cn } from "@/src/utils/tailwind";
import { type Trace, type Score } from "@prisma/client";
import { type Trace, type Score, $Enums } from "@prisma/client";
import { GroupedScoreBadges } from "@/src/components/grouped-score-badge";
import { Fragment } from "react";
import { type ObservationReturnType } from "@/src/server/api/routers/traces";
import { LevelColors } from "@/src/components/level-colors";
import { formatInterval } from "@/src/utils/dates";
import { MinusCircle, MinusIcon, PlusCircleIcon, PlusIcon } from "lucide-react";
import { Toggle } from "@/src/components/ui/toggle";
import { Button } from "@/src/components/ui/button";
export const ObservationTree = (props: {
observations: ObservationReturnType[];
collapsedObservations: string[];
toggleCollapsedObservation: (id: string) => void;
collapseAll: () => void;
expandAll: () => void;
trace: Trace;
scores: Score[];
currentObservationId: string | undefined;
@@ -21,6 +28,8 @@ export const ObservationTree = (props: {
return (
<div className={props.className}>
<ObservationTreeTraceNode
expandAll={props.expandAll}
collapseAll={props.collapseAll}
trace={props.trace}
scores={props.scores}
currentObservationId={props.currentObservationId}
@@ -30,6 +39,8 @@ export const ObservationTree = (props: {
/>
<ObservationTreeNode
observations={nestedObservations}
collapsedObservations={props.collapsedObservations}
toggleCollapsedObservation={props.toggleCollapsedObservation}
scores={props.scores}
indentationLevel={1}
currentObservationId={props.currentObservationId}
@@ -40,8 +51,11 @@ export const ObservationTree = (props: {
</div>
);
};
const ObservationTreeTraceNode = (props: {
trace: Trace & { latency?: number };
expandAll: () => void;
collapseAll: () => void;
scores: Score[];
currentObservationId: string | undefined;
setCurrentObservationId: (id: string | undefined) => void;
@@ -50,7 +64,7 @@ const ObservationTreeTraceNode = (props: {
}) => (
<div
className={cn(
"group mb-0.5 flex cursor-pointer flex-col gap-1 rounded-sm p-1.5",
"group mb-0.5 flex cursor-pointer flex-col gap-1 rounded-sm p-1",
props.currentObservationId === undefined ||
props.currentObservationId === ""
? "bg-gray-100"
@@ -60,7 +74,23 @@ const ObservationTreeTraceNode = (props: {
>
<div className="flex gap-2">
<span className={cn("rounded-sm bg-gray-200 p-1 text-xs")}>TRACE</span>
<span className="text-sm">{props.trace.name}</span>
<span className="flex-1 text-sm">{props.trace.name}</span>
<Button
onClick={(ev) => (ev.stopPropagation(), props.expandAll())}
size="xs"
variant="ghost"
title="Expand all"
>
<PlusCircleIcon className="h-4 w-4" />
</Button>
<Button
onClick={(ev) => (ev.stopPropagation(), props.collapseAll())}
size="xs"
variant="ghost"
title="Collapse all"
>
<MinusCircle className="h-4 w-4" />
</Button>
</div>
{props.showMetrics && props.trace.latency ? (
@@ -79,8 +109,11 @@ const ObservationTreeTraceNode = (props: {
) : null}
</div>
);
const ObservationTreeNode = (props: {
observations: NestedObservation[];
collapsedObservations: string[];
toggleCollapsedObservation: (id: string) => void;
scores: Score[];
indentationLevel: number;
currentObservationId: string | undefined;
@@ -91,96 +124,144 @@ const ObservationTreeNode = (props: {
<>
{props.observations
.sort((a, b) => a.startTime.getTime() - b.startTime.getTime())
.map((observation) => (
<Fragment key={observation.id}>
<div className="flex">
{Array.from({ length: props.indentationLevel }, (_, i) => (
<div className="mx-2 border-r" key={i} />
))}
<div
className={cn(
"group my-0.5 flex flex-1 cursor-pointer flex-col gap-1 rounded-sm p-1.5",
props.currentObservationId === observation.id
? "bg-gray-100"
: "hover:bg-gray-50",
)}
onClick={() => props.setCurrentObservationId(observation.id)}
>
<div className="flex gap-2">
<span
className={cn(
"self-start rounded-sm bg-gray-200 p-1 text-xs",
)}
>
{observation.type}
</span>
<span className="line-clamp-1 text-sm">{observation.name}</span>
</div>
{props.showMetrics &&
(observation.promptTokens ||
observation.completionTokens ||
observation.totalTokens ||
observation.endTime) && (
<div className="flex gap-2">
{observation.endTime ? (
<span className="text-xs text-gray-500">
{formatInterval(
(observation.endTime.getTime() -
observation.startTime.getTime()) /
1000,
)}
</span>
) : null}
{observation.promptTokens ||
observation.completionTokens ||
observation.totalTokens ? (
<span className="text-xs text-gray-500">
{observation.promptTokens} {" "}
{observation.completionTokens} ({" "}
{observation.totalTokens})
</span>
) : null}
</div>
.map((observation) => {
const collapsed = props.collapsedObservations.includes(observation.id);
return (
<Fragment key={observation.id}>
<div className="flex">
{Array.from({ length: props.indentationLevel }, (_, i) => (
<div className="mx-2 border-r" key={i} />
))}
<div
className={cn(
"group my-0.5 flex flex-1 cursor-pointer flex-col gap-1 rounded-sm p-1",
props.currentObservationId === observation.id
? "bg-gray-100"
: "hover:bg-gray-50",
)}
{observation.level !== "DEFAULT" ? (
<div className="flex">
<span
className={cn(
"rounded-sm p-0.5 text-xs",
LevelColors[observation.level].bg,
LevelColors[observation.level].text,
)}
>
{observation.level}
</span>
</div>
) : null}
{props.showScores &&
props.scores.find((s) => s.observationId === observation.id) ? (
<div className="flex flex-wrap gap-1">
<GroupedScoreBadges
scores={props.scores.filter(
(s) => s.observationId === observation.id,
)}
onClick={() => props.setCurrentObservationId(observation.id)}
>
<div className="flex gap-2">
<ColorCodedObservationType
observationType={observation.type}
/>
<span className="line-clamp-1 flex-1 text-sm">
{observation.name}
</span>
{observation.children.length === 0 ? null : (
<Toggle
onClick={(ev) => (
ev.stopPropagation(),
props.toggleCollapsedObservation(observation.id)
)}
variant="default"
pressed={collapsed}
size="xs"
className="w-7"
title={
collapsed ? "Expand children" : "Collapse children"
}
>
{collapsed ? (
<PlusIcon className="h-4 w-4" />
) : (
<MinusIcon className="h-4 w-4" />
)}
</Toggle>
)}
</div>
) : null}
{props.showMetrics &&
(observation.promptTokens ||
observation.completionTokens ||
observation.totalTokens ||
observation.endTime) && (
<div className="flex gap-2">
{observation.endTime ? (
<span className="text-xs text-gray-500">
{formatInterval(
(observation.endTime.getTime() -
observation.startTime.getTime()) /
1000,
)}
</span>
) : null}
{observation.promptTokens ||
observation.completionTokens ||
observation.totalTokens ? (
<span className="text-xs text-gray-500">
{observation.promptTokens} {" "}
{observation.completionTokens} ({" "}
{observation.totalTokens})
</span>
) : null}
</div>
)}
{observation.level !== "DEFAULT" ? (
<div className="flex">
<span
className={cn(
"rounded-sm p-0.5 text-xs",
LevelColors[observation.level].bg,
LevelColors[observation.level].text,
)}
>
{observation.level}
</span>
</div>
) : null}
{props.showScores &&
props.scores.find((s) => s.observationId === observation.id) ? (
<div className="flex flex-wrap gap-1">
<GroupedScoreBadges
scores={props.scores.filter(
(s) => s.observationId === observation.id,
)}
/>
</div>
) : null}
</div>
</div>
</div>
<ObservationTreeNode
observations={observation.children}
scores={props.scores}
indentationLevel={props.indentationLevel + 1}
currentObservationId={props.currentObservationId}
setCurrentObservationId={props.setCurrentObservationId}
showMetrics={props.showMetrics}
showScores={props.showScores}
/>
</Fragment>
))}
{!collapsed && (
<ObservationTreeNode
observations={observation.children}
collapsedObservations={props.collapsedObservations}
toggleCollapsedObservation={props.toggleCollapsedObservation}
scores={props.scores}
indentationLevel={props.indentationLevel + 1}
currentObservationId={props.currentObservationId}
setCurrentObservationId={props.setCurrentObservationId}
showMetrics={props.showMetrics}
showScores={props.showScores}
/>
)}
</Fragment>
);
})}
</>
);
const ColorCodedObservationType = (props: {
observationType: $Enums.ObservationType;
}) => {
const colors: Record<$Enums.ObservationType, string> = {
[$Enums.ObservationType.SPAN]: "bg-blue-100",
[$Enums.ObservationType.GENERATION]: "bg-orange-100",
[$Enums.ObservationType.EVENT]: "bg-green-100",
};
return (
<span
className={cn(
"self-start rounded-sm p-1 text-xs",
colors[props.observationType],
)}
>
{props.observationType}
</span>
);
};
export function nestObservations(
list: ObservationReturnType[],
): NestedObservation[] {
+56 -3
View File
@@ -23,6 +23,7 @@ import { Award, ChevronsDownUp, ChevronsUpDown } from "lucide-react";
import { ScrollArea } from "@/src/components/ui/scroll-area";
import { usdFormatter } from "@/src/utils/numbers";
import Decimal from "decimal.js";
import { useCallback, useState } from "react";
export function Trace(props: {
observations: Array<ObservationReturnType>;
@@ -41,9 +42,57 @@ export function Trace(props: {
true,
);
const [collapsedObservations, setCollapsedObservations] = useState<string[]>(
[],
);
const toggleCollapsedObservation = useCallback(
(id: string) => {
if (collapsedObservations.includes(id)) {
setCollapsedObservations(collapsedObservations.filter((i) => i !== id));
} else {
setCollapsedObservations([...collapsedObservations, id]);
}
},
[collapsedObservations],
);
const collapseAll = useCallback(() => {
// exclude all parents of the current observation
let excludeParentObservations = new Set<string>();
let newExcludeParentObservations = new Set<string>();
do {
excludeParentObservations = new Set<string>([
...excludeParentObservations,
...newExcludeParentObservations,
]);
newExcludeParentObservations = new Set<string>(
props.observations
.filter(
(o) =>
o.parentObservationId !== null &&
(o.id === currentObservationId ||
excludeParentObservations.has(o.id)),
)
.map((o) => o.parentObservationId as string)
.filter((id) => !excludeParentObservations.has(id)),
);
} while (newExcludeParentObservations.size > 0);
setCollapsedObservations(
props.observations
.map((o) => o.id)
.filter((id) => !excludeParentObservations.has(id)),
);
}, [props.observations, currentObservationId]);
const expandAll = useCallback(() => {
setCollapsedObservations([]);
}, [setCollapsedObservations]);
return (
<div className="grid gap-4 md:h-full md:grid-cols-3">
<ScrollArea className="md:col-span-2 md:h-full">
<div className="grid gap-4 md:h-full md:grid-cols-5">
<ScrollArea className="md:col-span-3 md:h-full">
{currentObservationId === undefined ||
currentObservationId === "" ||
currentObservationId === null ? (
@@ -62,7 +111,7 @@ export function Trace(props: {
/>
)}
</ScrollArea>
<div className="md:flex md:h-full md:flex-col md:overflow-hidden">
<div className="md:col-span-2 md:flex md:h-full md:flex-col md:overflow-hidden">
<div className="mb-2 flex flex-shrink-0 flex-row justify-end gap-2">
<Toggle
pressed={scoresOnObservationTree}
@@ -92,6 +141,10 @@ export function Trace(props: {
<ScrollArea className="flex flex-grow">
<ObservationTree
observations={props.observations}
collapsedObservations={collapsedObservations}
toggleCollapsedObservation={toggleCollapsedObservation}
collapseAll={collapseAll}
expandAll={expandAll}
trace={props.trace}
scores={props.scores}
currentObservationId={currentObservationId ?? undefined}
+1
View File
@@ -17,6 +17,7 @@ const toggleVariants = cva(
},
size: {
default: "h-10 px-3",
xs: "h-6 px-1.5",
sm: "h-9 px-2.5",
lg: "h-11 px-5",
},
+1 -1
View File
@@ -1 +1 @@
export const VERSION = "v2.3.0";
export const VERSION = "v2.4.0";
@@ -90,13 +90,13 @@ export function FeedbackButtonWrapper({
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle className="mb-5">{title}</DialogTitle>
<DialogTitle>{title}</DialogTitle>
</DialogHeader>
<Form {...form}>
<form
// eslint-disable-next-line @typescript-eslint/no-misused-promises
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
className="space-y-4"
>
<FormField
control={form.control}
@@ -0,0 +1,90 @@
import { Button } from "@/src/components/ui/button";
import { useHasAccess } from "@/src/features/rbac/utils/checkAccess";
import { api } from "@/src/utils/api";
import { Trash2 } from "lucide-react";
import { useState } from "react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/src/components/ui/popover";
import { useRouter } from "next/router";
export function DeletePromptVersion({
promptVersionId,
projectId,
version,
countVersions,
}: {
promptVersionId: string;
projectId: string;
version: number;
countVersions: number;
}) {
const utils = api.useUtils();
const router = useRouter();
const [isOpen, setIsOpen] = useState(false);
const hasAccess = useHasAccess({ projectId, scope: "prompts:CUD" });
const mutDeletePromptVersion = api.prompts.deleteVersion.useMutation({
onSuccess: () => {
void utils.prompts.invalidate();
if (countVersions > 1) {
void router.replace(
{
pathname: router.pathname,
query: { ...router.query, version: undefined },
},
undefined,
{ shallow: true },
);
} else {
void router.push(`/project/${projectId}/prompts`);
}
},
});
if (!hasAccess) {
return null;
}
return (
<Popover
key={promptVersionId}
open={isOpen}
onOpenChange={() => setIsOpen(!isOpen)}
>
<PopoverTrigger asChild>
<Button variant="outline" type="button" size="icon">
<Trash2 className="h-5 w-5" />
</Button>
</PopoverTrigger>
<PopoverContent>
<h2 className="text-md mb-3 font-semibold">Please confirm</h2>
<p className="mb-3 text-sm">
This action deletes the prompt version. Requests of version{" "}
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold">
{version}
</code>
of this prompt will return an error.
</p>
<div className="flex justify-end space-x-4">
<Button
type="button"
variant="destructive"
loading={mutDeletePromptVersion.isLoading}
onClick={() => {
void mutDeletePromptVersion.mutateAsync({
promptVersionId,
projectId,
});
setIsOpen(false);
}}
>
Delete Prompt Version
</Button>
</div>
</PopoverContent>
</Popover>
);
}
@@ -0,0 +1,69 @@
import { Button } from "@/src/components/ui/button";
import { useHasAccess } from "@/src/features/rbac/utils/checkAccess";
import { api } from "@/src/utils/api";
import { Trash2 } from "lucide-react";
import { useState } from "react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/src/components/ui/popover";
export function DeletePrompt({
projectId,
promptName,
}: {
projectId: string;
promptName: string;
}) {
const utils = api.useUtils();
const [isOpen, setIsOpen] = useState(false);
const hasAccess = useHasAccess({ projectId, scope: "prompts:CUD" });
const mutDeletePrompt = api.prompts.delete.useMutation({
onSuccess: () => {
void utils.prompts.invalidate();
},
});
if (!hasAccess) {
return null;
}
return (
<Popover open={isOpen} onOpenChange={() => setIsOpen(!isOpen)}>
<PopoverTrigger asChild>
<Button variant="ghost" size="xs">
<Trash2 className="h-4 w-4" />
</Button>
</PopoverTrigger>
<PopoverContent>
<h2 className="text-md mb-3 font-semibold">Please confirm</h2>
<p className="mb-3 text-sm">
This action permanently deletes this prompt. All requests to fetch
prompt{" "}
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold">
{promptName}
</code>{" "}
will error.
</p>
<div className="flex justify-end space-x-4">
<Button
type="button"
variant="destructive"
loading={mutDeletePrompt.isLoading}
onClick={() => {
void mutDeletePrompt.mutateAsync({
projectId,
promptName,
});
setIsOpen(false);
}}
>
Delete Prompt
</Button>
</div>
</PopoverContent>
</Popover>
);
}
@@ -14,6 +14,7 @@ import { PromotePrompt } from "@/src/features/prompts/components/promote-prompt"
import { ScrollArea } from "@radix-ui/react-scroll-area";
import { useQueryParam, NumberParam } from "use-query-params";
import router from "next/router";
import { DeletePromptVersion } from "@/src/features/prompts/components/delete-prompt-version";
export type PromptDetailProps = {
projectId: string;
@@ -77,6 +78,12 @@ export const PromptDetail = (props: PromptDetailProps) => {
<Pencil className="h-5 w-5" />
</Button>
</CreatePromptDialog>
<DeletePromptVersion
projectId={props.projectId}
promptVersionId={prompt.id}
version={prompt.version}
countVersions={promptHistory.data.length}
/>
<DetailPageNav
key="nav"
currentId={prompt.name}
@@ -5,6 +5,7 @@ import { Button } from "@/src/components/ui/button";
import { useDetailPageLists } from "@/src/features/navigate-detail-pages/context";
import { CreatePromptDialog } from "@/src/features/prompts/components/new-prompt-button";
import { useHasAccess } from "@/src/features/rbac/utils/checkAccess";
import { DeletePrompt } from "@/src/features/prompts/components/delete-prompt";
import { api } from "@/src/utils/api";
import { type RouterOutput } from "@/src/utils/types";
@@ -71,6 +72,18 @@ export function PromptTable(props: { projectId: string }) {
return createdAt.toLocaleString();
},
},
{
accessorKey: "actions",
header: "Actions",
cell: ({ row }) => {
return (
<DeletePrompt
projectId={props.projectId}
promptName={row.getValue("name")}
/>
);
},
},
];
const convertToTableRow = (
@@ -83,6 +83,58 @@ export const promptRouter = createTRPCRouter({
throw e;
}
}),
delete: protectedProjectProcedure
.input(
z.object({
projectId: z.string(),
promptName: z.string(),
}),
)
.mutation(async ({ input, ctx }) => {
try {
throwIfNoAccess({
session: ctx.session,
projectId: input.projectId,
scope: "prompts:CUD",
});
await ctx.prisma.prompt.deleteMany({
where: {
projectId: input.projectId,
name: input.promptName,
},
});
} catch (e) {
console.log(e);
throw e;
}
}),
deleteVersion: protectedProjectProcedure
.input(
z.object({
promptVersionId: z.string(),
projectId: z.string(),
}),
)
.mutation(async ({ input, ctx }) => {
try {
throwIfNoAccess({
session: ctx.session,
projectId: input.projectId,
scope: "prompts:CUD",
});
await ctx.prisma.prompt.delete({
where: {
id: input.promptVersionId,
projectId: input.projectId,
},
});
} catch (e) {
console.log(e);
throw e;
}
}),
promote: protectedProjectProcedure
.input(z.object({ promptId: z.string(), projectId: z.string() }))
.mutation(async ({ input, ctx }) => {
+5 -5
View File
@@ -95,19 +95,19 @@ export default function Start() {
return (
<div className="md:container">
<Header title={project?.name ?? "Dashboard"} />
<div className="flex items-center justify-between">
<div className="flex flex-wrap items-center justify-between">
<DatePickerWithRange
dateRange={dateRange}
setAgg={setAgg}
setDateRangeAndOption={setDateRangeAndOption}
selectedOption={selectedOption}
className=" max-w-full overflow-x-auto"
className="max-w-full overflow-x-auto"
/>
<FeedbackButtonWrapper
className="border-box"
title="Request Chart"
description="Your feedback matters! Let us know what additional data or metrics you'd like to see in your dashboard."
description="Your feedback matters! Let the Langfuse team know what additional data or metrics you'd like to see in your dashboard."
type="dashboard"
className="hidden md:flex"
>
<Button
id="date"
@@ -117,7 +117,7 @@ export default function Start() {
}
>
<BarChart2
className="h-6 w-6 shrink-0 text-gray-700 group-hover:text-indigo-600"
className="hidden h-6 w-6 shrink-0 text-gray-700 group-hover:text-indigo-600 lg:block"
aria-hidden="true"
/>
Request Chart
+4 -2
View File
@@ -11,9 +11,11 @@ export function extractVariables(mustacheString: string): string[] {
// Iterate over all matches
while ((match = regex.exec(mustacheString)) !== null) {
// Push each variable to the array
// Push each variable to the array if it's not already present
const variable = match[1];
if (variable) variables.push(variable);
if (variable && !variables.includes(variable)) {
variables.push(variable);
}
}
return variables;