Compare commits

...
27 Commits
Author SHA1 Message Date
Marc Klingen cd537fb571 chore: release v2.1.2
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 53s
CI/CD / tests (20) (push) Failing after 42s
CI/CD / test-docker-build (push) Successful in 2m59s
CI/CD / e2e-tests (push) Failing after 45s
release.yml / release (push) Failing after 3s
CI/CD / lint (push) Failing after 22m27s
CI/CD / all-ci-passed (push) Waiting to run
2024-02-02 23:22:12 +01:00
Marc KlingenandGitHub 3cbd252980 chore(cloud): add environment labeling (#1058) 2024-02-02 23:02:19 +01:00
Max DeichmannandGitHub 0a99988e6e perf: do not load observation i/o from db on traces.byId (#1053) 2024-02-02 16:01:19 +00:00
Marc KlingenandGitHub a19d20d973 fix: remove Expires from S3 PutObject (#1047)
Fixes #1046
2024-02-02 03:56:47 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b86eab9e04 chore(deps-dev): bump the patches group with 1 update (#1037)
Bumps the patches group with 1 update: [@playwright/test](https://github.com/microsoft/playwright).


Updates `@playwright/test` from 1.41.1 to 1.41.2
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.41.1...v1.41.2)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  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-02 00:57:37 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b36530ff96 chore(deps): bump lucide-react from 0.316.0 to 0.321.0 (#1039)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.316.0 to 0.321.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.321.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  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-02 00:50:03 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1019298060 chore(deps-dev): bump @testing-library/react from 14.1.2 to 14.2.1 (#1040)
Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 14.1.2 to 14.2.1.
- [Release notes](https://github.com/testing-library/react-testing-library/releases)
- [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/react-testing-library/compare/v14.1.2...v14.2.1)

---
updated-dependencies:
- dependency-name: "@testing-library/react"
  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-02 00:45:30 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
99a2ad30ce chore(deps-dev): bump @typescript-eslint/parser from 6.19.1 to 6.20.0 (#1038)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.19.1 to 6.20.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.20.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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-02 00:40:21 +00:00
Marc Klingen 9783a22abf chore: release v2.1.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / test-docker-build (push) Successful in 2m42s
CI/CD / tests (18) (push) Failing after 1m13s
CI/CD / tests (20) (push) Failing after 42s
CI/CD / e2e-tests (push) Failing after 44s
CI/CD / lint (push) Successful in 4m9s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 17s
2024-02-02 00:48:34 +01:00
Marc KlingenandGitHub 68f63b3b90 fix(ui): generation exports from UI (#1042) 2024-02-02 00:18:58 +01:00
Marc Klingen 1189d13c14 chore: release v2.1.0
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (20) (push) Failing after 47s
CI/CD / e2e-tests (push) Failing after 44s
CI/CD / lint (push) Successful in 4m1s
CI/CD / test-docker-build (push) Successful in 3m43s
release.yml / release (push) Failing after 3s
CI/CD / tests (18) (push) Failing after 11m20s
CI/CD / all-ci-passed (push) Waiting to run
2024-02-01 21:08:59 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
243a784480 chore(deps): bump the patches group with 4 updates (#1035)
Bumps the patches group with 4 updates: cmdk, [@testing-library/jest-dom](https://github.com/testing-library/jest-dom), [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react).


Updates `cmdk` from 0.2.0 to 0.2.1

Updates `@testing-library/jest-dom` from 6.4.0 to 6.4.1
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v6.4.0...v6.4.1)

Updates `@types/jest` from 29.5.11 to 29.5.12
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

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

---
updated-dependencies:
- dependency-name: cmdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@types/react"
  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-01 21:08:19 +01:00
c89b8c3bab fix(ui): update regex matching description (#1031)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-01 20:54:57 +01:00
b5172219af security: upgrade nodemailer from 6.9.8 to 6.9.9 (#1027)
* fix: package.json to reduce vulnerabilities

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-NODEMAILER-6219989

* update

---------

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2024-02-01 20:53:40 +01:00
Marc Klingen db90f85041 fix(ui): disabled state of AddModel button 2024-02-01 17:41:19 +01:00
Marc KlingenandGitHub db9f90aa91 fix(models): allow price = 0 (#1030) 2024-02-01 15:56:51 +00:00
Marc KlingenandGitHub 41b19582cc feat(models): allow to set input/output/total price without restrictions (#1029) 2024-02-01 16:50:25 +01:00
766102797b feat(models): allow custom regex for user-defined models (#1022)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-01 16:42:21 +01:00
Max Deichmann 773cb1312b chore: release v2.0.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 1m0s
CI/CD / test-docker-build (push) Successful in 3m27s
CI/CD / e2e-tests (push) Failing after 49s
CI/CD / tests (20) (push) Failing after 1m39s
CI/CD / lint (push) Successful in 4m44s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 3s
2024-02-01 16:31:54 +01:00
Max DeichmannandGitHub bb593020d0 fix: gh action (#1028) 2024-02-01 16:27:06 +01:00
Max DeichmannandGitHub 33ffe62add fix: display total cost correctly (#1026) 2024-02-01 14:56:49 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6e1aabb2de chore(deps-dev): bump @testing-library/jest-dom from 6.2.1 to 6.4.0 (#988)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 6.2.1 to 6.4.0.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v6.2.1...v6.4.0)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  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-01-31 22:14:20 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ab3bdebc57 chore(deps): bump the sentry group with 1 update (#1000)
Bumps the sentry group with 1 update: [@sentry/nextjs](https://github.com/getsentry/sentry-javascript).


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

---
updated-dependencies:
- dependency-name: "@sentry/nextjs"
  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-01-31 22:09:55 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
20d00e5ef2 chore(deps-dev): bump @mermaid-js/mermaid-cli from 10.6.1 to 10.7.0 (#1003)
Bumps [@mermaid-js/mermaid-cli](https://github.com/mermaid-js/mermaid-cli) from 10.6.1 to 10.7.0.
- [Release notes](https://github.com/mermaid-js/mermaid-cli/releases)
- [Commits](https://github.com/mermaid-js/mermaid-cli/compare/10.6.1...10.7.0)

---
updated-dependencies:
- dependency-name: "@mermaid-js/mermaid-cli"
  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-01-31 22:04:28 +00:00
Marc Klingen e689c1cacb chore: move github discussions to org level 2024-01-31 22:59:35 +01:00
Richard KrümmelandGitHub 37c0737624 feat(db): add openai fine tuned and vertex ai models (#995) 2024-01-31 14:19:17 +01:00
23bc448088 fix(ui): fix create new model label (#1005)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-01-31 11:46:15 +01:00
22 changed files with 489 additions and 502 deletions
+4 -4
View File
@@ -1,7 +1,7 @@
contact_links:
- name: 🤗 Get Help
url: https://github.com/langfuse/langfuse/discussions/new?category=q-a
about: If you cant get something to work the way you expect, open a question in our discussion forums.
- name: 💡 Feature Request
url: https://github.com/langfuse/langfuse/discussions/new?category=ideas
url: https://github.com/orgs/langfuse/discussions/new?category=ideas
about: Suggest any ideas you have using our discussion forums.
- name: 🤗 Get Help
url: https://github.com/orgs/langfuse/discussions/new?category=support
about: If you cant get something to work the way you expect, open a question in our discussion forums.
+5
View File
@@ -66,6 +66,11 @@ jobs:
matrix:
node-version: [18, 20]
steps:
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 10
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
+149 -383
View File
@@ -1,12 +1,12 @@
{
"name": "langfuse-core",
"version": "2.0.0",
"version": "2.1.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "langfuse-core",
"version": "2.0.0",
"version": "2.1.2",
"hasInstallScript": true,
"dependencies": {
"@anthropic-ai/tokenizer": "^0.0.4",
@@ -39,7 +39,7 @@
"@radix-ui/react-tooltip": "^1.0.7",
"@react-email/components": "^0.0.14",
"@react-email/render": "^0.0.12",
"@sentry/nextjs": "^7.95.0",
"@sentry/nextjs": "^7.99.0",
"@sentry/profiling-node": "^1.3.5",
"@sentry/types": "^7.88.0",
"@t3-oss/env-nextjs": "^0.8.0",
@@ -55,7 +55,7 @@
"bcryptjs": "^2.4.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cmdk": "^0.2.0",
"cmdk": "^0.2.1",
"core-js": "^3.35.1",
"cors": "^2.8.5",
"date-fns": "^3.3.1",
@@ -63,11 +63,11 @@
"exponential-backoff": "^3.1.1",
"js-tiktoken": "^1.0.10",
"lodash": "^4.17.21",
"lucide-react": "^0.316.0",
"lucide-react": "^0.321.0",
"next": "^14.1.0",
"next-auth": "^4.24.5",
"next-query-params": "^5.0.0",
"nodemailer": "^6.9.8",
"nodemailer": "^6.9.9",
"posthog-js": "^1.103.1",
"posthog-node": "^3.6.1",
"react": "18.2.0",
@@ -86,23 +86,23 @@
},
"devDependencies": {
"@jedmao/location": "^3.0.0",
"@mermaid-js/mermaid-cli": "^10.6.1",
"@playwright/test": "^1.41.1",
"@mermaid-js/mermaid-cli": "^10.7.0",
"@playwright/test": "^1.41.2",
"@release-it/bumper": "^6.0.1",
"@testing-library/jest-dom": "^6.2.1",
"@testing-library/react": "^14.1.2",
"@testing-library/jest-dom": "^6.4.1",
"@testing-library/react": "^14.2.1",
"@types/bcryptjs": "^2.4.6",
"@types/cors": "^2.8.17",
"@types/eslint": "^8.56.2",
"@types/jest": "^29.5.11",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.14.202",
"@types/node": "20.10.5",
"@types/nodemailer": "^6.4.14",
"@types/react": "^18.2.48",
"@types/react": "^18.2.51",
"@types/react-dom": "^18.2.18",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.19.1",
"@typescript-eslint/parser": "^6.20.0",
"autoprefixer": "^10.4.17",
"dotenv-cli": "^7.3.0",
"eslint": "^8.56.0",
@@ -2844,9 +2844,9 @@
}
},
"node_modules/@mermaid-js/mermaid-cli": {
"version": "10.6.1",
"resolved": "https://registry.npmjs.org/@mermaid-js/mermaid-cli/-/mermaid-cli-10.6.1.tgz",
"integrity": "sha512-OH2uOXW3/GBaMGagVF7Fzu/9TJrGge+Bu/+Tm8OyIaRBaKa2NN+3SggJOmr5s51oTPaGKu/X1XBDoauvtlXAPg==",
"version": "10.7.0",
"resolved": "https://registry.npmjs.org/@mermaid-js/mermaid-cli/-/mermaid-cli-10.7.0.tgz",
"integrity": "sha512-b1kHdzSStWaxoNdU5KnzXJ/OQzYqFo4mZsHobX44l6gb2s1O6DzD0g801VzxUmcJ+5OWt6piDL1Ug//cQUsrZg==",
"dev": true,
"dependencies": {
"chalk": "^5.0.1",
@@ -3288,12 +3288,12 @@
}
},
"node_modules/@playwright/test": {
"version": "1.41.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.1.tgz",
"integrity": "sha512-9g8EWTjiQ9yFBXc6HjCWe41msLpxEX0KhmfmPl9RPLJdfzL4F0lg2BdJ91O9azFdl11y1pmpwdjBiSxvqc+btw==",
"version": "1.41.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz",
"integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==",
"dev": true,
"dependencies": {
"playwright": "1.41.1"
"playwright": "1.41.2"
},
"bin": {
"playwright": "cli.js"
@@ -4923,57 +4923,57 @@
}
},
"node_modules/@sentry-internal/feedback": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.95.0.tgz",
"integrity": "sha512-UWNUUg+OrhV58/ChQNY0yLCCYdEI2cIYVwq1riZ+AFU9Z2ZyCxEoSRVLh7c5tnCPLbKAPR+VvlEsSjMqucAKnA==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.99.0.tgz",
"integrity": "sha512-exIO1o+bE0MW4z30FxC0cYzJ4ZHSMlDPMHCBDPzU+MWGQc/fb8s58QUrx5Dnm6HTh9G3H+YlroCxIo9u0GSwGQ==",
"dependencies": {
"@sentry/core": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0"
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.95.0.tgz",
"integrity": "sha512-nK+VYLnhlxLnnEUPMnzN8BSCFXPy2dQ5OVFO+fiTNPlGCbxsq8O9SnkX6E+u1oPLSA/151s2B3VxIasR8bXJAQ==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.99.0.tgz",
"integrity": "sha512-PoIkfusToDq0snfl2M6HJx/1KJYtXxYhQplrn11kYadO04SdG0XGXf4h7wBTMEQ7LDEAtQyvsOu4nEQtTO3YjQ==",
"dependencies": {
"@sentry/core": "7.95.0",
"@sentry/replay": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0"
"@sentry/core": "7.99.0",
"@sentry/replay": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/tracing": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.95.0.tgz",
"integrity": "sha512-YKiLPMnEgTsTh7u/W1Zep9HtV1rJqAetqJ4ekaIxyUUB6ppi6V00MacSjb01o++fwlNNDYFxNpJlgQqNPqsCNA==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.99.0.tgz",
"integrity": "sha512-z3JQhHjoM1KdM20qrHwRClKJrNLr2CcKtCluq7xevLtXHJWNAQQbafnWD+Aoj85EWXBzKt9yJMv2ltcXJ+at+w==",
"dependencies": {
"@sentry/core": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0"
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.95.0.tgz",
"integrity": "sha512-J+bAryc/7StRZSeaJByLTnEslWu7uXaZ1zERQF17sZbRxvbyaYbAO7cqSUKZ1gK3p9QfrkqzNl7xA8thg4FtHQ==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.99.0.tgz",
"integrity": "sha512-bgfoUv3wkwwLgN5YUOe0ibB3y268ZCnamZh6nLFqnY/UBKC1+FXWFdvzVON/XKUm62LF8wlpCybOf08ebNj2yg==",
"dependencies": {
"@sentry-internal/feedback": "7.95.0",
"@sentry-internal/replay-canvas": "7.95.0",
"@sentry-internal/tracing": "7.95.0",
"@sentry/core": "7.95.0",
"@sentry/replay": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0"
"@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"
},
"engines": {
"node": ">=8"
@@ -5000,25 +5000,25 @@
}
},
"node_modules/@sentry/core": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.95.0.tgz",
"integrity": "sha512-z+ffO6jK/ZUxnRbBGmnj5sOouKZ4mvRY0KJa33kbyqcmeiJKrN81M7Ecj1IJUCamo/6RqX0GCwDDxgUPZZZBwA==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.99.0.tgz",
"integrity": "sha512-vOAtzcAXEUtS/oW7wi3wMkZ3hsb5Ch96gKyrrj/mXdOp2zrcwdNV6N9/pawq2E9P/7Pw8AXw4CeDZztZrjQLuA==",
"dependencies": {
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0"
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/integrations": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.95.0.tgz",
"integrity": "sha512-5d2RlQr8SHuAZ1gMT5G+R3DjyK//r24b686j18RB8k61qVhylE0SoSpJWmonDwNZnmvmpbLkYvh2kNhlAIKUTA==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.99.0.tgz",
"integrity": "sha512-q4Nwpc27DTWlR7nDerd1o6KHlT/0usK+3xfBTZ1feVIAHCxt6ohCyZdoQ97+4kQiJJdX47MEmJYsXUlj62yZNg==",
"dependencies": {
"@sentry/core": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0",
"localforage": "^1.8.1"
},
"engines": {
@@ -5026,18 +5026,18 @@
}
},
"node_modules/@sentry/nextjs": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-7.95.0.tgz",
"integrity": "sha512-6RinlFxsnZjDSuApFgWnupPNBbqgHW7h/+I02dLWhy7TkTfmfGEiQ8pPENrQlKUvyEGLJv2+Pk7RXi+Xj2DC0g==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-7.99.0.tgz",
"integrity": "sha512-8eeEPFJjRBiCp2sFUhDLQFdWFagQ2yBvmALZIOIuoMei69N+clYVSxz84beeztbLal0zvRadJO5LAkBCb6d66Q==",
"dependencies": {
"@rollup/plugin-commonjs": "24.0.0",
"@sentry/core": "7.95.0",
"@sentry/integrations": "7.95.0",
"@sentry/node": "7.95.0",
"@sentry/react": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0",
"@sentry/vercel-edge": "7.95.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/webpack-plugin": "1.21.0",
"chalk": "3.0.0",
"resolve": "1.22.8",
@@ -5059,14 +5059,14 @@
}
},
"node_modules/@sentry/node": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.95.0.tgz",
"integrity": "sha512-3fbN+4ajPly9rhbuJtuZ+o2FGmka8Y7A3T/ooHuhCGoWegKtn3OzaOIrdwcYoBIy1fO6SuldTi/P72Y7wgIPtw==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.99.0.tgz",
"integrity": "sha512-34wYtLddnPcQ8qvKq62AfxowaMFw+GMUZGv7fIs9FxeBqqqn6Ckl0gFCTADudIIBQ3rSbmN7sHJIXdyiQv+pcw==",
"dependencies": {
"@sentry-internal/tracing": "7.95.0",
"@sentry/core": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0"
"@sentry-internal/tracing": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
},
"engines": {
"node": ">=8"
@@ -5092,14 +5092,14 @@
}
},
"node_modules/@sentry/react": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.95.0.tgz",
"integrity": "sha512-L1WVoRJ14uUBhnpVURVO3G7szuA2hk5pzNWMGjNhE7I+ERdfYjgRS5FMnjcsZsnyNtELe/56jLCBirKqwWZJIQ==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.99.0.tgz",
"integrity": "sha512-RtHwgzMHJhzJfSQpVG0SDPQYMTGDX3Q37/YWI59S4ALMbSW4/F6n/eQAvGVYZKbh2UCSqgFuRWaXOYkSZT17wA==",
"dependencies": {
"@sentry/browser": "7.95.0",
"@sentry/core": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0",
"@sentry/browser": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0",
"hoist-non-react-statics": "^3.3.2"
},
"engines": {
@@ -5110,47 +5110,47 @@
}
},
"node_modules/@sentry/replay": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.95.0.tgz",
"integrity": "sha512-WAAEvWCXoNC7hfPI1fNoxODB9UzUYhXtscrWIm89Mn3AAi8haayVNNiUWKVj6+Vpt87C+/sb9UsERwdPWpl/Sw==",
"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==",
"dependencies": {
"@sentry-internal/tracing": "7.95.0",
"@sentry/core": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0"
"@sentry-internal/tracing": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry/types": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.95.0.tgz",
"integrity": "sha512-ouU7NsEcrwmcnXHMNBGmKZEmKMzmgPGoBydZn1gukCI67Ci71fAYpPNrbtmjai6+jtsY21o45rVLqExru2sdfw==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.99.0.tgz",
"integrity": "sha512-94qwOw4w40sAs5mCmzcGyj8ZUu/KhnWnuMZARRq96k+SjRW/tHFAOlIdnFSrt3BLPvSOK7R3bVAskZQ0N4FTmA==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/utils": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.95.0.tgz",
"integrity": "sha512-0zget8AOaQWLIEA9cTx/qiQQYpx2x0UfnaW5xRmQg12QGTSngo/cUm9O04zuHw5gpBBGG0ocMDHxwwr+UCCBiw==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.99.0.tgz",
"integrity": "sha512-cYZy5WNTkWs5GgggGnjfGqC44CWir0pAv4GVVSx0fsup4D4pMKBJPrtub15f9uC+QkUf3vVkqwpBqeFxtmJQTQ==",
"dependencies": {
"@sentry/types": "7.95.0"
"@sentry/types": "7.99.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/vercel-edge": {
"version": "7.95.0",
"resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-7.95.0.tgz",
"integrity": "sha512-BQ9NIUNe8T1crQIfLB88YQhgWO114Ru9ZxzteuUNWN4+kqNgPNBe25jHLERmZ6pRPLtWdSXIUeIZVxwuKXMUjQ==",
"version": "7.99.0",
"resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-7.99.0.tgz",
"integrity": "sha512-9Uw3Iuy8KMlcv71ifnaguwndb1NkHeOAbYcBEeq9W+n0f5ocFZvMlnwszSlVNAL3cK+hlpcBhelXNAO/mBWCfg==",
"dependencies": {
"@sentry-internal/tracing": "7.95.0",
"@sentry/core": "7.95.0",
"@sentry/types": "7.95.0",
"@sentry/utils": "7.95.0"
"@sentry-internal/tracing": "7.99.0",
"@sentry/core": "7.99.0",
"@sentry/types": "7.99.0",
"@sentry/utils": "7.99.0"
},
"engines": {
"node": ">=8"
@@ -6091,9 +6091,9 @@
"dev": true
},
"node_modules/@testing-library/jest-dom": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.2.1.tgz",
"integrity": "sha512-Nuy/uFFDe9h/2jwoUuMKgoxvgkUv4S9jI9bARj6dGUKJ3euRhg8JFi5sciYbrayoxkadEOZednRT9+vo6LvvxQ==",
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.1.tgz",
"integrity": "sha512-Z7qMM3J2Zw5H/nC2/5CYx5YcuaD56JmDFKNIozZ89VIo6o6Y9FMhssics4e2madEKYDNEpZz3+glPGz0yWMOag==",
"dev": true,
"dependencies": {
"@adobe/css-tools": "^4.3.2",
@@ -6142,9 +6142,9 @@
"dev": true
},
"node_modules/@testing-library/react": {
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.1.2.tgz",
"integrity": "sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==",
"version": "14.2.1",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.2.1.tgz",
"integrity": "sha512-sGdjws32ai5TLerhvzThYFbpnF9XtL65Cjf+gB0Dhr29BGqK+mAeN7SURSdu+eqgET4ANcWoC7FQpkaiGvBr+A==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
@@ -6463,9 +6463,9 @@
}
},
"node_modules/@types/jest": {
"version": "29.5.11",
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz",
"integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==",
"version": "29.5.12",
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz",
"integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==",
"dev": true,
"dependencies": {
"expect": "^29.0.0",
@@ -6534,9 +6534,9 @@
"devOptional": true
},
"node_modules/@types/react": {
"version": "18.2.48",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz",
"integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==",
"version": "18.2.51",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.51.tgz",
"integrity": "sha512-XeoMaU4CzyjdRr3c4IQQtiH7Rpo18V07rYZUucEZQwOUEtGgTXv7e6igQiQ+xnV6MbMe1qjEmKdgMNnfppnXfg==",
"devOptional": true,
"dependencies": {
"@types/prop-types": "*",
@@ -6643,63 +6643,16 @@
}
}
},
"node_modules/@typescript-eslint/eslint-plugin/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/eslint-plugin/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==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/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==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.20.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": {
"version": "6.19.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz",
"integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==",
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.20.0.tgz",
"integrity": "sha512-bYerPDF/H5v6V76MdMYhjwmwgMA+jlPVqjSDq2cRqMi8bP5sR3Z+RLOiOMad3nsnmDVmn2gAFCyNgh/dIrfP/w==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "6.19.1",
"@typescript-eslint/types": "6.19.1",
"@typescript-eslint/typescript-estree": "6.19.1",
"@typescript-eslint/visitor-keys": "6.19.1",
"@typescript-eslint/scope-manager": "6.20.0",
"@typescript-eslint/types": "6.20.0",
"@typescript-eslint/typescript-estree": "6.20.0",
"@typescript-eslint/visitor-keys": "6.20.0",
"debug": "^4.3.4"
},
"engines": {
@@ -6719,13 +6672,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "6.19.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz",
"integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==",
"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.19.1",
"@typescript-eslint/visitor-keys": "6.19.1"
"@typescript-eslint/types": "6.20.0",
"@typescript-eslint/visitor-keys": "6.20.0"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -6762,7 +6715,7 @@
}
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
"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==",
@@ -6775,7 +6728,7 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
"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==",
@@ -6803,88 +6756,6 @@
}
}
},
"node_modules/@typescript-eslint/type-utils/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==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.20.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/type-utils/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/type-utils/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/types": {
"version": "6.19.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz",
"integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "6.19.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz",
"integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.19.1",
"@typescript-eslint/visitor-keys": "6.19.1",
"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/typescript-estree/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@@ -6934,65 +6805,7 @@
"eslint": "^7.0.0 || ^8.0.0"
}
},
"node_modules/@typescript-eslint/utils/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/utils/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==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/utils/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==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.20.0",
"@typescript-eslint/visitor-keys": "6.20.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/utils/node_modules/@typescript-eslint/visitor-keys": {
"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==",
@@ -7009,47 +6822,6 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/utils/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/utils/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/visitor-keys": {
"version": "6.19.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz",
"integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.19.1",
"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/@ungap/structured-clone": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
@@ -8273,12 +8045,11 @@
}
},
"node_modules/cmdk": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/cmdk/-/cmdk-0.2.0.tgz",
"integrity": "sha512-JQpKvEOb86SnvMZbYaFKYhvzFntWBeSZdyii0rZPhKJj9uwJBxu4DaVYDrRN7r3mPop56oPhRw+JYWTKs66TYw==",
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/cmdk/-/cmdk-0.2.1.tgz",
"integrity": "sha512-U6//9lQ6JvT47+6OF6Gi8BvkxYQ8SCRRSKIJkthIMsFsLZRG0cKvTtuTaefyIKMQb8rvvXy0wGdpTNq/jPtm+g==",
"dependencies": {
"@radix-ui/react-dialog": "1.0.0",
"command-score": "0.1.2"
"@radix-ui/react-dialog": "1.0.0"
},
"peerDependencies": {
"react": "^18.0.0",
@@ -8561,11 +8332,6 @@
"node": ">= 0.8"
}
},
"node_modules/command-score": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/command-score/-/command-score-0.1.2.tgz",
"integrity": "sha512-VtDvQpIJBvBatnONUsPzXYFVKQQAhuf3XTNOAsdBxCNO/QCtUUd8LSgjn0GVarBkCad6aJCZfXgrjYbl/KRr7w=="
},
"node_modules/commander": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
@@ -13678,9 +13444,9 @@
}
},
"node_modules/lucide-react": {
"version": "0.316.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.316.0.tgz",
"integrity": "sha512-dTmYX1H4IXsRfVcj/KUxworV6814ApTl7iXaS21AimK2RUEl4j4AfOmqD3VR8phe5V91m4vEJ8tCK4uT1jE5nA==",
"version": "0.321.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.321.0.tgz",
"integrity": "sha512-Fi9VahIna6642U+2nAGSjnXwUBV3WyfFFPQq4yi3w30jtqxDLfSyiYCtCYCYQZ2KWNZc1MDI+rcsa0t+ChdYpw==",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0"
}
@@ -14172,9 +13938,9 @@
"dev": true
},
"node_modules/nodemailer": {
"version": "6.9.8",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.8.tgz",
"integrity": "sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ==",
"version": "6.9.9",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.9.tgz",
"integrity": "sha512-dexTll8zqQoVJEZPwQAKzxxtFn0qTnjdQTchoU6Re9BUUGBJiOy3YMn/0ShTW6J5M0dfQ1NeDeRTTl4oIWgQMA==",
"engines": {
"node": ">=6.0.0"
}
@@ -15033,12 +14799,12 @@
}
},
"node_modules/playwright": {
"version": "1.41.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.1.tgz",
"integrity": "sha512-gdZAWG97oUnbBdRL3GuBvX3nDDmUOuqzV/D24dytqlKt+eI5KbwusluZRGljx1YoJKZ2NRPaeWiFTeGZO7SosQ==",
"version": "1.41.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz",
"integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==",
"dev": true,
"dependencies": {
"playwright-core": "1.41.1"
"playwright-core": "1.41.2"
},
"bin": {
"playwright": "cli.js"
@@ -15051,9 +14817,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.41.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.1.tgz",
"integrity": "sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg==",
"version": "1.41.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz",
"integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
+12 -12
View File
@@ -1,6 +1,6 @@
{
"name": "langfuse-core",
"version": "2.0.0",
"version": "2.1.2",
"private": true,
"scripts": {
"prebuild": "cp generated/openapi-client/openapi.yml public/openapi-client.yml && cp generated/openapi-server/openapi.yml public/openapi-server.yml",
@@ -57,7 +57,7 @@
"@radix-ui/react-tooltip": "^1.0.7",
"@react-email/components": "^0.0.14",
"@react-email/render": "^0.0.12",
"@sentry/nextjs": "^7.95.0",
"@sentry/nextjs": "^7.99.0",
"@sentry/profiling-node": "^1.3.5",
"@sentry/types": "^7.88.0",
"@t3-oss/env-nextjs": "^0.8.0",
@@ -73,7 +73,7 @@
"bcryptjs": "^2.4.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cmdk": "^0.2.0",
"cmdk": "^0.2.1",
"core-js": "^3.35.1",
"cors": "^2.8.5",
"date-fns": "^3.3.1",
@@ -81,11 +81,11 @@
"exponential-backoff": "^3.1.1",
"js-tiktoken": "^1.0.10",
"lodash": "^4.17.21",
"lucide-react": "^0.316.0",
"lucide-react": "^0.321.0",
"next": "^14.1.0",
"next-auth": "^4.24.5",
"next-query-params": "^5.0.0",
"nodemailer": "^6.9.8",
"nodemailer": "^6.9.9",
"posthog-js": "^1.103.1",
"posthog-node": "^3.6.1",
"react": "18.2.0",
@@ -104,23 +104,23 @@
},
"devDependencies": {
"@jedmao/location": "^3.0.0",
"@mermaid-js/mermaid-cli": "^10.6.1",
"@playwright/test": "^1.41.1",
"@mermaid-js/mermaid-cli": "^10.7.0",
"@playwright/test": "^1.41.2",
"@release-it/bumper": "^6.0.1",
"@testing-library/jest-dom": "^6.2.1",
"@testing-library/react": "^14.1.2",
"@testing-library/jest-dom": "^6.4.1",
"@testing-library/react": "^14.2.1",
"@types/bcryptjs": "^2.4.6",
"@types/cors": "^2.8.17",
"@types/eslint": "^8.56.2",
"@types/jest": "^29.5.11",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.14.202",
"@types/node": "20.10.5",
"@types/nodemailer": "^6.4.14",
"@types/react": "^18.2.48",
"@types/react": "^18.2.51",
"@types/react-dom": "^18.2.18",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.19.1",
"@typescript-eslint/parser": "^6.20.0",
"autoprefixer": "^10.4.17",
"dotenv-cli": "^7.3.0",
"eslint": "^8.56.0",
@@ -0,0 +1,40 @@
DELETE FROM models
WHERE id in ('clrp1wopz000808l09nwy32xh', 'clrp1wopz000408l05xcycki1');
INSERT INTO models (
id,
project_id,
model_name,
match_pattern,
start_date,
input_price,
output_price,
total_price,
unit,
tokenizer_id,
tokenizer_config
)
VALUES
-- https://openai.com/blog/new-embedding-models-and-api-updates
-- https://openai.com/blog/gpt-3-5-turbo-fine-tuning-and-api-updates
-- ft model tokens are getting counted like the base model https://github.com/openai/tiktoken/blob/db5bda9fc93b3171db6c4afea329394e6b6d31ca/tiktoken/model.py
('cls08r8sq000308jq14ae96f0', NULL, 'ft:gpt-3.5-turbo-1106', '(?i)^(ft:)(gpt-3.5-turbo-1106:)(.+)(:)(.*)(:)(.+)$', NULL, 0.000003, 0.000006, NULL, 'TOKENS', 'openai', '{"tokensPerName": 1, "tokenizerModel": "gpt-3.5-turbo-1106", "tokensPerMessage": 3}'),
('cls08rp99000408jqepxoakjv', NULL, 'ft:gpt-3.5-turbo-0613', '(?i)^(ft:)(gpt-3.5-turbo-0613:)(.+)(:)(.*)(:)(.+)$', NULL, 0.000012, 0.000016, NULL, 'TOKENS', 'openai', '{"tokensPerName": 1, "tokenizerModel": "gpt-3.5-turbo-0613", "tokensPerMessage": 3}'),
('cls08rv9g000508jq5p4z4nlr', NULL, 'ft:davinci-002', '(?i)^(ft:)(davinci-002:)(.+)(:)(.*)(:)(.+)$$', NULL, 0.000012, 0.000012, NULL, 'TOKENS', 'openai', '{"tokenizerModel": "davinci-002"}'),
('cls08s2bw000608jq57wj4un2', NULL, 'ft:babbage-002', '(?i)^(ft:)(babbage-002:)(.+)(:)(.*)(:)(.+)$$', NULL, 0.0000016, 0.0000016, NULL, 'TOKENS', 'openai', '{"tokenizerModel": "babbage-002"}'),
-- https://cloud.google.com/vertex-ai/docs/generative-ai/pricing
('cls0k4lqt000008ky1o1s8wd5', NULL, 'gemini-pro', '(?i)^(gemini-pro)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls0jni4t000008jk3kyy803r', NULL, 'chat-bison-32k', '(?i)^(chat-bison-32k)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls0iv12d000108l251gf3038', NULL, 'chat-bison', '(?i)^(chat-bison)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls0jmjt3000108l83ix86w0d', NULL, 'text-bison-32k', '(?i)^(text-bison-32k)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls0juygp000308jk2a6x9my2', NULL, 'text-bison', '(?i)^(text-bison)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls0jungb000208jk12gm4gk1', NULL, 'text-unicorn', '(?i)^(text-unicorn)(@[a-zA-Z0-9]+)?$', NULL, 0.0000025, 0.0000075, NULL, 'CHARACTERS', NULL, NULL),
('cls1nyj5q000208l33ne901d8', NULL, 'textembedding-gecko', '(?i)^(textembedding-gecko)(@[a-zA-Z0-9]+)?$', NULL, NULL, NULL, 0.0000001, 'CHARACTERS', NULL, NULL),
('cls1nyyjp000308l31gxy1bih', NULL, 'textembedding-gecko-multilingual', '(?i)^(textembedding-gecko-multilingual)(@[a-zA-Z0-9]+)?$', NULL, NULL, NULL, 0.0000001, 'CHARACTERS', NULL, NULL),
('cls1nzjt3000508l3dnwad3g0', NULL, 'code-gecko', '(?i)^(code-gecko)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls1nzwx4000608l38va7e4tv', NULL, 'code-bison', '(?i)^(code-bison)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls1o053j000708l39f8g4bgs', NULL, 'code-bison-32k', '(?i)^(code-bison-32k)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls0j33v1000008joagkc4lql', NULL, 'codechat-bison-32k', '(?i)^(codechat-bison-32k)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL),
('cls0jmc9v000008l8ee6r3gsd', NULL, 'codechat-bison', '(?i)^(codechat-bison)(@[a-zA-Z0-9]+)?$', NULL, 0.00000025, 0.0000005, NULL, 'CHARACTERS', NULL, NULL)
+34
View File
@@ -353,6 +353,40 @@ describe("/api/public/ingestion API Endpoint", () => {
},
],
},
{
observationExternalModel: "ft:gpt-3.5-turbo-1106:my-org:custom_suffix:id",
observationStartTime: new Date("2022-01-01T10:00:00.000Z"),
modelUnit: "TOKENS",
expectedInternalModel: "ft:gpt-3.5-turbo-1106",
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
models: [
{
modelName: "ft:gpt-3.5-turbo-1106",
matchPattern: "(?i)^(ft:)(gpt-3.5-turbo-1106:)(.+)(:)(.*)(:)(.+)$",
startDate: new Date("2022-01-01T00:00:00.000Z"),
unit: "TOKENS",
tokenizerId: "openai",
},
],
},
{
observationExternalModel: "ft:babbage-002:my-org#2:custom_suffix-2:id",
observationStartTime: new Date("2022-01-01T10:00:00.000Z"),
modelUnit: "TOKENS",
expectedInternalModel: "ft:babbage-002",
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
models: [
{
modelName: "ft:babbage-002",
matchPattern: "(?i)^(ft:)(babbage-002:)(.+)(:)(.*)(:)(.+)$",
startDate: new Date("2022-01-01T00:00:00.000Z"),
unit: "TOKENS",
tokenizerId: "openai",
},
],
},
{
observationExternalModel: "GPT-4",
observationStartTime: new Date("2021-01-01T00:00:00.000Z"),
+44 -19
View File
@@ -1,5 +1,7 @@
import { VERSION } from "@/src/constants/VERSION";
import { env } from "@/src/env.mjs";
import { cn } from "@/src/utils/tailwind";
import { AlertTriangle } from "lucide-react";
export const LangfuseIcon = ({
size = 32,
@@ -22,31 +24,54 @@ export const LangfuseLogo = ({
className,
size = "sm",
version = false,
showEnvLabel = false,
}: {
size?: "sm" | "xl";
className?: string;
version?: boolean;
showEnvLabel?: boolean;
}) => (
<div className={cn("flex items-center", className)}>
<LangfuseIcon size={size === "sm" ? 16 : 20} />
<span
className={cn(
"font-mono font-semibold",
size === "sm" ? "ml-2 text-sm" : "ml-3 text-xl",
)}
>
Langfuse
</span>
{version && (
<a
href="https://github.com/langfuse/langfuse/releases"
target="_blank"
rel="noopener"
title="View releases on GitHub"
className="ml-2 text-xs text-gray-400"
<div className={cn("flex gap-4 xl:flex-col xl:items-start", className)}>
{/* Environment Labeling for Langfuse Maintainers */}
{showEnvLabel && env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION && (
<div
className={cn(
"flex items-center gap-2 self-stretch rounded-md px-3 py-1 ring-1 xl:-mx-2",
env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION === "STAGING"
? "bg-blue-100 text-blue-500 ring-blue-500"
: "bg-red-100 text-red-500 ring-red-500",
)}
>
{VERSION}
</a>
<AlertTriangle size={16} />
<span className="whitespace-nowrap">
{["EU", "US"].includes(env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION)
? `PRODUCTION-${env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION}`
: env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION}
</span>
</div>
)}
{/* Langfuse Logo */}
<div className="flex items-center">
<LangfuseIcon size={size === "sm" ? 16 : 20} />
<span
className={cn(
"font-mono font-semibold",
size === "sm" ? "ml-2 text-sm" : "ml-3 text-xl",
)}
>
Langfuse
</span>
{version && (
<a
href="https://github.com/langfuse/langfuse/releases"
target="_blank"
rel="noopener"
title="View releases on GitHub"
className="ml-2 text-xs text-gray-400"
>
{VERSION}
</a>
)}
</div>
</div>
);
+20 -3
View File
@@ -220,7 +220,13 @@ export default function Layout(props: PropsWithChildren) {
</Transition.Child>
{/* Sidebar component, swap this element with another sidebar if you like */}
<div className="flex grow flex-col gap-y-5 overflow-y-auto bg-white px-6 py-4">
<LangfuseLogo version size="xl" />
<LangfuseLogo
version
size="xl"
showEnvLabel={session.data?.user?.email?.endsWith(
"@langfuse.com",
)}
/>
<nav className="flex flex-1 flex-col">
<ul role="list" className="flex flex-1 flex-col gap-y-7">
<MainNavigation nav={navigation} />
@@ -286,7 +292,14 @@ export default function Layout(props: PropsWithChildren) {
<div className="hidden xl:fixed xl:inset-y-0 xl:z-50 xl:flex xl:w-72 xl:flex-col">
{/* Sidebar component, swap this element with another sidebar if you like */}
<div className="flex h-screen grow flex-col gap-y-5 border-r border-gray-200 bg-white pt-7">
<LangfuseLogo version size="xl" className="mb-2 px-6" />
<LangfuseLogo
version
size="xl"
className="mb-2 px-6"
showEnvLabel={session.data?.user?.email?.endsWith(
"@langfuse.com",
)}
/>
<nav className="flex h-full flex-1 flex-col overflow-y-auto px-6 pb-3">
<ul role="list" className="flex h-full flex-col gap-y-4">
<MainNavigation nav={navigation} />
@@ -408,7 +421,11 @@ export default function Layout(props: PropsWithChildren) {
<span className="sr-only">Open sidebar</span>
<Bars3Icon className="h-6 w-6" aria-hidden="true" />
</button>
<LangfuseLogo version className="flex-1" />
<LangfuseLogo
version
className="flex-1"
showEnvLabel={session.data?.user?.email?.endsWith("@langfuse.com")}
/>
<Menu as="div" className="relative">
<Menu.Button className="flex items-center gap-x-4 text-sm font-semibold leading-6 text-gray-900">
<span className="sr-only">Open user menu</span>
@@ -125,6 +125,7 @@ export default function GenerationsTable({ projectId }: GenerationsTableProps) {
fileFormat,
filter: filterState,
searchQuery,
orderBy: orderByState,
});
let url: string;
+7 -4
View File
@@ -24,6 +24,7 @@ import { IOPreview } from "@/src/components/trace/IOPreview";
import { formatInterval } from "@/src/utils/dates";
import Link from "next/link";
import { usdFormatter } from "@/src/utils/numbers";
import { calculateDisplayTotalCost } from "@/src/components/trace";
export const ObservationPreview = (props: {
observations: Array<ObservationReturnType>;
@@ -41,6 +42,10 @@ export const ObservationPreview = (props: {
(o) => o.id === props.currentObservationId,
);
const totalCost = calculateDisplayTotalCost(
preloadedObservation ? [preloadedObservation] : [],
);
if (!preloadedObservation) return <div className="flex-1">Not found</div>;
return (
<Card className="flex-1">
@@ -97,11 +102,9 @@ export const ObservationPreview = (props: {
{preloadedObservation.model ? (
<Badge variant="outline">{preloadedObservation.model}</Badge>
) : null}
{preloadedObservation.calculatedTotalCost ? (
{totalCost ? (
<Badge variant="outline">
{usdFormatter(
preloadedObservation.calculatedTotalCost.toNumber(),
)}
{usdFormatter(totalCost.toNumber())}
</Badge>
) : undefined}
+41 -10
View File
@@ -22,7 +22,7 @@ import { Toggle } from "@/src/components/ui/toggle";
import { Award, ChevronsDownUp, ChevronsUpDown } from "lucide-react";
import { ScrollArea } from "@/src/components/ui/scroll-area";
import { usdFormatter } from "@/src/utils/numbers";
import type Decimal from "decimal.js";
import Decimal from "decimal.js";
export function Trace(props: {
observations: Array<ObservationReturnType>;
@@ -134,16 +134,8 @@ export function TracePage({ traceId }: { traceId: string }) {
const filterOptionTags = traceFilterOptions.data?.tags ?? [];
const allTags = filterOptionTags.map((t) => t.value);
const totalCost: Decimal | undefined = trace.data?.observations.reduce(
(prev: Decimal | undefined, curr: ObservationReturnType) => {
if (!curr.calculatedTotalCost) return prev;
const totalCost = calculateDisplayTotalCost(trace.data?.observations ?? []);
return prev
? prev.plus(curr.calculatedTotalCost)
: curr.calculatedTotalCost;
},
undefined,
);
if (trace.error?.data?.code === "UNAUTHORIZED") return <NoAccessError />;
if (!trace.data) return <div>loading...</div>;
return (
@@ -232,3 +224,42 @@ export function TracePage({ traceId }: { traceId: string }) {
</div>
);
}
export const calculateDisplayTotalCost = (
observations: ObservationReturnType[],
) => {
return observations.reduce(
(prev: Decimal | undefined, curr: ObservationReturnType) => {
// if we don't have any calculated costs, we can't do anything
if (
!curr.calculatedTotalCost &&
!curr.calculatedInputCost &&
!curr.calculatedOutputCost
)
return prev;
// if we have either input or output cost, but not total cost, we can use that
if (
!curr.calculatedTotalCost &&
(curr.calculatedInputCost || curr.calculatedOutputCost)
) {
return prev
? prev.plus(
curr.calculatedInputCost ??
new Decimal(0).plus(
curr.calculatedOutputCost ?? new Decimal(0),
),
)
: curr.calculatedInputCost ?? curr.calculatedOutputCost ?? undefined;
}
if (!curr.calculatedTotalCost) return prev;
// if we have total cost, we can use that
return prev
? prev.plus(curr.calculatedTotalCost)
: curr.calculatedTotalCost;
},
undefined,
);
};
+1 -1
View File
@@ -1 +1 @@
export const VERSION = "v2.0.0";
export const VERSION = "v2.1.2";
@@ -88,7 +88,7 @@ export const MetricTable = ({
>
<DocPopup
description="Calculated multiplying the number of tokens with cost per token for each model."
href="https://langfuse.com/docs/token-usage"
href="https://langfuse.com/docs/model-usage-and-cost"
/>
</TotalMetric>
</DashboardTable>
+1
View File
@@ -197,6 +197,7 @@ function unicodeToBytesInString(input: string): string {
}
return result;
}
function unicodeToBytes(input: string): Uint8Array {
const encoder = new TextEncoder();
return encoder.encode(input);
@@ -29,12 +29,7 @@ import JsonView from "react18-json-view";
const formSchema = z.object({
modelName: z.string().min(1),
exactMatchPattern: z
.string()
.regex(
/^[a-zA-Z0-9_.-]+$/,
"Match pattern must be alphanumeric and may contain _.-",
), // risk of invalid regex injection that would break the db join,
matchPattern: z.string(),
startDate: z.date().optional(),
inputPrice: z
.string()
@@ -81,7 +76,7 @@ export const NewModelForm = (props: {
resolver: zodResolver(formSchema),
defaultValues: {
modelName: "",
exactMatchPattern: "",
matchPattern: "",
startDate: undefined,
inputPrice: "",
outputPrice: "",
@@ -108,7 +103,7 @@ export const NewModelForm = (props: {
.mutateAsync({
projectId: props.projectId,
modelName: values.modelName,
exactMatchPattern: values.exactMatchPattern,
matchPattern: values.matchPattern,
inputPrice: !!values.inputPrice
? parseFloat(values.inputPrice)
: undefined,
@@ -171,6 +166,7 @@ export const NewModelForm = (props: {
onValueChange={(option) => field.onChange(option.value)}
value={{ value: field.value, label: field.value }}
disabled={false}
createLabel="Create a new model name"
/>
</FormControl>
<FormDescription>
@@ -185,7 +181,7 @@ export const NewModelForm = (props: {
<Header level="h3" title="Scope" />
<FormField
control={form.control}
name="exactMatchPattern"
name="matchPattern"
render={({ field }) => (
<FormItem>
<FormLabel>Match pattern</FormLabel>
@@ -193,8 +189,10 @@ export const NewModelForm = (props: {
<Input {...field} />
</FormControl>
<FormDescription>
`model` on generations that should match this model,
case-insensitive.
Regular expression (Postgres syntax) to match ingested
generations (model attribute) to this model definition. For an
exact, case-insensitive match to a model name, use the
expression: (?i)^modelname$
</FormDescription>
<FormMessage />
</FormItem>
@@ -23,6 +23,7 @@ type AutoCompleteProps = {
onValueChange?: (value: AutoCompleteOption) => void;
disabled?: boolean;
placeholder?: string;
createLabel: string;
};
export const AutoComplete = ({
@@ -31,6 +32,7 @@ export const AutoComplete = ({
value,
onValueChange,
disabled,
createLabel,
}: AutoCompleteProps) => {
const inputRef = useRef<HTMLInputElement>(null);
const [isOpen, setOpen] = useState(false);
@@ -138,6 +140,7 @@ export const AutoComplete = ({
onSelect={() =>
handleSelectOption({ value: inputValue, label: inputValue })
}
createLabel={createLabel}
{...{ inputValue, options }}
/>
</CommandList>
@@ -151,11 +154,13 @@ export const AutoComplete = ({
const CommandItemCreate = ({
inputValue,
options,
createLabel,
onSelect,
onMouseDown,
}: {
inputValue: string;
options: AutoCompleteOption[];
createLabel: string;
onSelect: () => void;
onMouseDown: (event: React.MouseEvent<HTMLElement>) => void;
}) => {
@@ -176,7 +181,7 @@ const CommandItemCreate = ({
onMouseDown={onMouseDown}
>
<div className={cn("m-2 h-4 w-4")} />
Create new prompt name: &quot;{inputValue}&quot;
{createLabel}: &quot;{inputValue}&quot;
</CommandItem>
);
};
@@ -191,6 +191,7 @@ export const NewPromptForm = (props: {
onValueChange={setNameValue}
value={{ value: field.value, label: field.value }}
disabled={false}
createLabel="Create a new prompt name"
/>
</FormControl>
<FormMessage />
+5 -3
View File
@@ -19,13 +19,15 @@ export default function ModelsPage() {
help={{
description:
"A model represents a LLM model. It is used to calculate tokens and cost.",
href: "https://langfuse.com/docs/token-usage",
href: "https://langfuse.com/docs/model-usage-and-cost",
}}
actionButtons={
<Button disabled={!hasWriteAccess} asChild>
<Link href={`/project/${projectId}/models/new`}>
<Link
href={hasWriteAccess ? `/project/${projectId}/models/new` : "#"}
>
{!hasWriteAccess && <Lock size={16} className="mr-2" />}
Add model definition{" "}
Add model definition
</Link>
</Button>
}
+6 -1
View File
@@ -10,7 +10,7 @@ export default function ModelsPage() {
return (
<div className="mb-12 md:container">
<Header
title="New Model"
title="New Model Definition"
breadcrumb={[
{
name: "Models",
@@ -20,6 +20,11 @@ export default function ModelsPage() {
name: "New",
},
]}
help={{
description:
"Create a project-specific model definition. This will be used by Langfuse to infer model usage (eg tokens) and cost (USD).",
href: "https://langfuse.com/docs/model-usage-and-cost",
}}
/>
<NewModelForm
projectId={projectId}
+42 -12
View File
@@ -31,19 +31,19 @@ import {
import { orderBy } from "@/src/server/api/interfaces/orderBy";
import { orderByToPrismaSql } from "@/src/features/orderBy/server/orderByToPrisma";
const GenerationFilterOptions = z.object({
const GenerationTableOptions = z.object({
projectId: z.string(), // Required for protectedProjectProcedure
filter: z.array(singleFilter),
searchQuery: z.string().nullable(),
orderBy: orderBy,
});
const ListInputs = GenerationFilterOptions.extend({
orderBy: orderBy,
const ListInputs = GenerationTableOptions.extend({
...paginationZod,
});
// extend generationfilteroptions with export options
const ExportInputs = GenerationFilterOptions.extend({
const ExportInputs = GenerationTableOptions.extend({
fileFormat: z.enum(exportFileFormats),
});
@@ -51,6 +51,7 @@ export const generationsRouter = createTRPCRouter({
all: protectedProjectProcedure
.input(ListInputs)
.query(async ({ input, ctx }) => {
// ATTENTION: When making changes to this query, make sure to also update the export query
const searchCondition = input.searchQuery
? Prisma.sql`AND (
o."id" ILIKE ${`%${input.searchQuery}%`} OR
@@ -240,6 +241,7 @@ export const generationsRouter = createTRPCRouter({
export: protectedProjectProcedure
.input(ExportInputs)
.query(async ({ input, ctx }) => {
// ATTENTION: When making changes to this query, make sure to also update the all query
const searchCondition = input.searchQuery
? Prisma.sql`AND (
o."id" ILIKE ${`%${input.searchQuery}%`} OR
@@ -253,18 +255,45 @@ export const generationsRouter = createTRPCRouter({
input.filter,
observationsTableCols,
);
console.log("filters: ", filterCondition);
const orderByCondition = orderByToPrismaSql(
input.orderBy,
observationsTableCols,
);
// to improve query performance, add timeseries filter to observation queries as well
const startTimeFilter = input.filter.find(
(f) => f.column === "start_time" && f.type === "datetime",
);
const datetimeFilter =
startTimeFilter && startTimeFilter.type === "datetime"
? datetimeFilterToPrismaSql(
"start_time",
startTimeFilter.operator,
startTimeFilter.value,
)
: Prisma.empty;
const generations = await ctx.prisma.$queryRaw<
Array<
ObservationView & {
traceId: string;
traceName: string;
latency: number | null;
}
>
>(
Prisma.sql`
-- used for filtering
WITH observations_with_latency AS (
SELECT
o.*,
CASE WHEN o.end_time IS NULL THEN NULL ELSE (EXTRACT(EPOCH FROM o."end_time") - EXTRACT(EPOCH FROM o."start_time"))::double precision END AS "latency"
FROM observations_view o
WHERE o.type = 'GENERATION'
AND o.project_id = ${input.projectId}
${datetimeFilter}
),
-- used for filtering
scores_avg AS (
SELECT
trace_id,
@@ -293,6 +322,7 @@ export const generationsRouter = createTRPCRouter({
o.model,
o.start_time as "startTime",
o.end_time as "endTime",
o.latency,
o.input,
o.output,
o.metadata,
@@ -302,6 +332,8 @@ export const generationsRouter = createTRPCRouter({
o.prompt_tokens as "promptTokens",
o.completion_tokens as "completionTokens",
o.total_tokens as "totalTokens",
o.level,
o.status_message as "statusMessage",
o.version,
o.model_id as "modelId",
o.input_price as "inputPrice",
@@ -310,15 +342,14 @@ export const generationsRouter = createTRPCRouter({
o.calculated_input_cost as "calculatedInputCost",
o.calculated_output_cost as "calculatedOutputCost",
o.calculated_total_cost as "calculatedTotalCost"
FROM observations_view o
FROM observations_with_latency o
JOIN traces t ON t.id = o.trace_id
LEFT JOIN scores_avg AS s_avg ON s_avg.trace_id = t.id and s_avg.observation_id = o.id
WHERE o.type = 'GENERATION'
AND o.project_id = ${input.projectId}
AND t.project_id = ${input.projectId}
WHERE
t.project_id = ${input.projectId}
${searchCondition}
${filterCondition}
ORDER BY o.start_time DESC
${orderByCondition}
`,
);
@@ -445,7 +476,6 @@ export const generationsRouter = createTRPCRouter({
Key: fileName,
Body: output,
ContentType: exportOptions[input.fileFormat].fileType,
Expires: new Date(Date.now() + 60 * 60 * 1000), // in 1 hour, file will be deleted
}),
);
const signedUrl = await getSignedUrl(
+29 -32
View File
@@ -6,6 +6,8 @@ import {
} from "@/src/server/api/trpc";
import { paginationZod } from "@/src/utils/zod";
import { throwIfNoAccess } from "@/src/features/rbac/utils/checkAccess";
import { Prisma } from "@prisma/client";
import { TRPCError } from "@trpc/server";
const ModelAllOptions = z.object({
projectId: z.string(),
@@ -39,9 +41,6 @@ export const modelRouter = createTRPCRouter({
OR: [{ projectId: input.projectId }, { projectId: null }],
},
});
console.log("models", models);
return {
models,
totalCount: totalAmount,
@@ -86,34 +85,18 @@ export const modelRouter = createTRPCRouter({
}),
create: protectedProjectProcedure
.input(
z
.object({
projectId: z.string(),
modelName: z.string(),
exactMatchPattern: z
.string()
.regex(
/^[a-zA-Z0-9_.-]+$/,
"Match pattern must be alphanumeric and may contain _.-",
), // risk of invalid regex injection that would break the db join
startDate: z.date().optional(),
inputPrice: z.number().positive().optional(),
outputPrice: z.number().positive().optional(),
totalPrice: z.number().positive().optional(),
unit: z.enum(["TOKENS", "CHARACTERS"]),
tokenizerId: z.enum(["openai", "claude"]).optional(),
tokenizerConfig: z
.record(z.union([z.string(), z.number()]))
.optional(),
})
.refine(
({ inputPrice, outputPrice, totalPrice }) =>
(!!inputPrice && !!outputPrice) || !!totalPrice,
{
message:
"Either inputPrice and outputPrice or totalPrice needs to be set",
},
),
z.object({
projectId: z.string(),
modelName: z.string(),
matchPattern: z.string(),
startDate: z.date().optional(),
inputPrice: z.number().nonnegative().optional(),
outputPrice: z.number().nonnegative().optional(),
totalPrice: z.number().nonnegative().optional(),
unit: z.enum(["TOKENS", "CHARACTERS"]),
tokenizerId: z.enum(["openai", "claude"]).optional(),
tokenizerConfig: z.record(z.union([z.string(), z.number()])).optional(),
}),
)
.mutation(async ({ input, ctx }) => {
throwIfNoAccess({
@@ -121,11 +104,25 @@ export const modelRouter = createTRPCRouter({
projectId: input.projectId,
scope: "models:CUD",
});
// Check if regex is valid POSIX regex
// Use DB to check, because JS regex is not POSIX compliant
try {
await ctx.prisma.$queryRaw(
Prisma.sql`SELECT 'test_string' ~ ${input.matchPattern}`,
);
} catch (error) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Invalid regex, needs to be Postgres syntax",
});
}
return ctx.prisma.model.create({
data: {
projectId: input.projectId,
modelName: input.modelName,
matchPattern: `(?i)^(${input.exactMatchPattern})$`,
matchPattern: input.matchPattern,
startDate: input.startDate,
inputPrice: input.inputPrice,
outputPrice: input.outputPrice,
+31 -5
View File
@@ -208,6 +208,36 @@ export const traceRouter = createTRPCRouter({
},
});
const observations = await ctx.prisma.observationView.findMany({
select: {
id: true,
traceId: true,
projectId: true,
type: true,
startTime: true,
endTime: true,
name: true,
metadata: true,
parentObservationId: true,
level: true,
statusMessage: true,
version: true,
createdAt: true,
model: true,
modelParameters: true,
promptTokens: true,
completionTokens: true,
totalTokens: true,
unit: true,
completionStartTime: true,
promptId: true,
modelId: true,
inputPrice: true,
outputPrice: true,
totalPrice: true,
calculatedInputCost: true,
calculatedOutputCost: true,
calculatedTotalCost: true,
},
where: {
traceId: {
equals: input.traceId,
@@ -237,11 +267,7 @@ export const traceRouter = createTRPCRouter({
return {
...trace,
latency: latencyMs !== undefined ? latencyMs / 1000 : undefined,
observations: observations.map(
({ input: _input, output: _output, ...rest }) => {
return { ...rest };
},
) as ObservationReturnType[],
observations: observations as ObservationReturnType[],
};
}),
deleteMany: protectedProjectProcedure