Compare commits

...

34 Commits

Author SHA1 Message Date
Enrico Ros 2f59e12e20 Remove log 2024-03-06 22:20:40 -08:00
Enrico Ros 30e8652c2a 1.14.1: Release for Claude-3 2024-03-06 22:10:41 -08:00
Enrico Ros 5ee6aceb60 cleanups 2024-03-06 21:51:15 -08:00
Enrico Ros 6940b6a6d1 Anthropic: Full support for Claude-3 models. Closes #443, #450
Thanks to @slapglif in #450 for a reference implementation.
2024-03-06 21:50:24 -08:00
Enrico Ros 4e33ce9415 misc 2024-03-06 20:56:32 -08:00
Enrico Ros 944e22bde6 Anthropic: if there's a single system message, treat it as-if it was a user message 2024-03-06 20:49:59 -08:00
Enrico Ros 6054fa0a26 Anthropic: use the new Messages format (thanks @slapglif #450) 2024-03-06 20:42:33 -08:00
Enrico Ros 4db13cfed4 Anthropic: wire types (fully switch to the new Messages API) 2024-03-06 20:33:59 -08:00
Enrico Ros 6a6adda2e0 misc 2024-03-06 20:33:12 -08:00
Enrico Ros 4afa55c0db Anthropic: update models 2024-03-06 18:36:07 -08:00
Enrico Ros bc120bfb2b Merge branch 'release-1.14.0' 2024-03-05 22:41:40 -08:00
Enrico Ros 88966699e7 1.14.0: Changelog and README 2024-03-05 22:40:49 -08:00
Enrico Ros 9a5db3dcfb 1.14.0: release date 2024-03-05 22:38:56 -08:00
Enrico Ros 392aa1e654 1.14.0: README and Changelog 2024-03-05 22:16:02 -08:00
Enrico Ros f2b32e47ff 1.14.0: README and Changelog 2024-03-05 22:13:59 -08:00
Enrico Ros 58136d0181 maintainers: release name and cover 2024-03-05 21:58:04 -08:00
Enrico Ros 02733e55cb 1.14.0: News items 2024-03-05 21:55:44 -08:00
Enrico Ros 60df8456a7 1.14.0: Icons support 2024-03-05 21:54:48 -08:00
Enrico Ros 6d0ecc805c 1.14.0: Cover Image 2024-03-05 21:54:38 -08:00
Enrico Ros a0e9dd24a3 Explain the Debug page 2024-03-05 20:12:40 -08:00
Enrico Ros d1eb89057d Update flow 2024-03-05 14:51:00 -08:00
Enrico Ros 161c6dc83a 1.14.0: News Version 2024-03-05 14:50:51 -08:00
Enrico Ros 54848b8a7e 1.14.0: news: move around 2024-03-05 14:50:46 -08:00
Enrico Ros 990563c604 1.14.0: Version 2024-03-05 14:45:35 -08:00
Enrico Ros 8489ca8c8d Anthropic: add status update tracking #443 2024-03-05 14:40:43 -08:00
Enrico Ros b57e2c89e3 miniroll 2024-03-05 14:32:44 -08:00
Enrico Ros 66bedf78ac anthropic: cutoff dates 2024-03-04 22:30:09 -08:00
Enrico Ros 592c5cce60 roll packages 2024-03-04 22:01:19 -08:00
Enrico Ros 2ccf9a4e92 swap items 2024-03-04 21:38:30 -08:00
Enrico Ros ed333c0513 make 127.0.0.1 work on airgaped connections 2024-03-04 16:26:20 -08:00
Enrico Ros 89b65b7009 unbreak build #444 2024-03-04 15:20:08 -08:00
Enrico Ros 0cc2d346af Merge pull request #444 from jacksongoode/claude-3
Add Claude 3 models
2024-03-04 14:18:19 -08:00
Jackson 5f81e78bc4 Add Claude 2 to old models 2024-03-04 12:29:04 -08:00
Jackson 554b5fd4b5 Add Claude 3 models 2024-03-04 12:24:12 -08:00
24 changed files with 821 additions and 403 deletions
+24 -2
View File
@@ -21,8 +21,9 @@ assignees: enricoros
- [ ] Create a temporary tag `git tag v1.2.3 && git push opensource --tags`
- [ ] Create a [New Draft GitHub Release](https://github.com/enricoros/big-agi/releases/new), and generate the automated changelog (for new contributors)
- [ ] Update the release version in package.json, and `npm i`
- [ ] Update in-app News [src/apps/news/news.data.tsx](/src/apps/news/news.data.tsx)
- [ ] Update the in-app News version number
- [ ] Update in-app News [src/apps/news/news.data.tsx](/src/apps/news/news.data.tsx)
- [ ] Update in-app Cover graphics
- [ ] Update the README.md with the new release
- [ ] Copy the highlights to the [docs/changelog.md](/docs/changelog.md)
- Release:
@@ -79,11 +80,32 @@ I need the following from you:
1. a table summarizing all the new features in 1.2.3 with the following columns: 4 words description (exactly what it is), short description, usefulness (what it does for the user), significance, link to the issue number (not the commit)), which will be used for the artifacts later
2. then double-check the git log to see if there are any features of significance that are not in the table
3. then score each feature in terms of importance for users (1-10), relative impact of the feature (1-10, where 10 applies to the broadest user base), and novelty and uniqueness (1-10, where 10 is truly unique and novel from what exists already)
3. then score each feature in terms of importance for users (1-10), relative impact of the feature (1-10, where 10 applies to the broadest user base), and novelty and uniqueness (1-10, where 10 is truly unique and novel from what exists already)
4. then improve the table, in decreasing order of importance for features, fixing any detail that's missing, in particular check if there are commits of significance from a user or developer point of view, which are not contained in the table
5. then I want you then to update the news.data.tsx for the new release
```
### release name
```markdown
please brainstorm 10 different names for this release. see the former names here: https://big-agi.com/blog
```
You can follow with 'What do you think of Modelmorphic?' or other selected name
### cover images
```markdown
Great, now I need to generate images for this. Before I used the following prompts (2 releases before).
// An image of a capybara sculpted entirely from black cotton candy, set against a minimalist backdrop with splashes of bright, contrasting sparkles. The capybara is using a computer with split screen made of origami, split keyboard and is wearing origami sunglasses with very different split reflections. Split halves are very contrasting. Close up photography, bokeh, white background.
import coverV113 from '../../../public/images/covers/release-cover-v1.13.0.png';
// An image of a capybara sculpted entirely from black cotton candy, set against a minimalist backdrop with splashes of bright, contrasting sparkles. The capybara is calling on a 3D origami old-school pink telephone and the camera is zooming on the telephone. Close up photography, bokeh, white background.
import coverV112 from '../../../public/images/covers/release-cover-v1.12.0.png';
What can I do now as far as images? Give me 4 prompt ideas with the same style as looks as the former, but different scene or action
```
### Readme (and Changelog)
```markdown
+11
View File
@@ -17,6 +17,17 @@ Or fork & run on Vercel
big-AGI is an open book; see the **[ready-to-ship and future ideas](https://github.com/users/enricoros/projects/4/views/2)** in our open roadmap
### What's New in 1.14.1 · March 7, 2024 · Modelmorphic
- **Anthropic** [Claude-3](https://www.anthropic.com/news/claude-3-family) model family support. [#443](https://github.com/enricoros/big-AGI/issues/443)
- New **[Perplexity](https://www.perplexity.ai/)** and **[Groq](https://groq.com/)** integration (thanks @Penagwin). [#407](https://github.com/enricoros/big-AGI/issues/407), [#427](https://github.com/enricoros/big-AGI/issues/427)
- **[LocalAI](https://localai.io/models/)** deep integration, including support for [model galleries](https://github.com/enricoros/big-AGI/issues/411)
- **Mistral** Large and Google **Gemini 1.5** support
- Performance optimizations: runs [much faster](https://twitter.com/enricoros/status/1756553038293303434?utm_source=localhost:3000&utm_medium=big-agi), saves lots of power, reduces memory usage
- Enhanced UX with auto-sizing charts, refined search and folder functionalities, perfected scaling
- And with more UI improvements, documentation, bug fixes (20 tickets), and developer enhancements
- [Release notes](https://github.com/enricoros/big-AGI/releases/tag/v1.14.0), and changes [v1.13.1...v1.14.1](https://github.com/enricoros/big-AGI/compare/v1.13.1...v1.14.1) (233 commits, 8,000+ lines changed)
### What's New in 1.13.0 · Feb 8, 2024 · Multi + Mind
https://github.com/enricoros/big-AGI/assets/32999/01732528-730e-41dc-adc7-511385686b13
+17 -4
View File
@@ -5,12 +5,25 @@ by release.
- For the live roadmap, please see [the GitHub project](https://github.com/users/enricoros/projects/4/views/2)
### 1.13.0 - Feb 2024
### 1.15.0 - Mar 2024
- milestone: [1.13.0](https://github.com/enricoros/big-agi/milestone/13)
Prediction: OpenAI will release GPT-5 on March 14, 2024. We will support it on day 1.
- milestone: [1.15.0](https://github.com/enricoros/big-agi/milestone/15)
- work in progress: [big-AGI open roadmap](https://github.com/users/enricoros/projects/4/views/2), [help here](https://github.com/users/enricoros/projects/4/views/4)
## What's New in 1.13.0 · Feb 8, 2024 · Multi + Mind
### What's New in 1.14.1 · March 7, 2024 · Modelmorphic
- **Anthropic** [Claude-3](https://www.anthropic.com/news/claude-3-family) model family support. [#443](https://github.com/enricoros/big-AGI/issues/443)
- New **[Perplexity](https://www.perplexity.ai/)** and **[Groq](https://groq.com/)** integration (thanks @Penagwin). [#407](https://github.com/enricoros/big-AGI/issues/407), [#427](https://github.com/enricoros/big-AGI/issues/427)
- **[LocalAI](https://localai.io/models/)** deep integration, including support for [model galleries](https://github.com/enricoros/big-AGI/issues/411)
- **Mistral** Large and Google **Gemini 1.5** support
- Performance optimizations: runs [much faster](https://twitter.com/enricoros/status/1756553038293303434?utm_source=localhost:3000&utm_medium=big-agi), saves lots of power, reduces memory usage
- Enhanced UX with auto-sizing charts, refined search and folder functionalities, perfected scaling
- And with more UI improvements, documentation, bug fixes (20 tickets), and developer enhancements
- [Release notes](https://github.com/enricoros/big-AGI/releases/tag/v1.14.0), and changes [v1.13.1...v1.14.0](https://github.com/enricoros/big-AGI/compare/v1.13.1...v1.14.0) (233 commits, 8,000+ lines changed)
### What's New in 1.13.0 · Feb 8, 2024 · Multi + Mind
https://github.com/enricoros/big-AGI/assets/32999/01732528-730e-41dc-adc7-511385686b13
@@ -22,7 +35,7 @@ https://github.com/enricoros/big-AGI/assets/32999/01732528-730e-41dc-adc7-511385
- Better looking chats with improved spacing, fonts, and menus
- More: new video player, [LM Studio tutorial](https://github.com/enricoros/big-AGI/blob/main/docs/config-local-lmstudio.md) (thanks @aj47), [MongoDB support](https://github.com/enricoros/big-AGI/blob/main/docs/deploy-database.md) (thanks @ranfysvalle02), and speedups
## What's New in 1.12.0 · Jan 26, 2024 · AGI Hotline
### What's New in 1.12.0 · Jan 26, 2024 · AGI Hotline
https://github.com/enricoros/big-AGI/assets/32999/95ceb03c-945d-4fdd-9a9f-3317beb54f3f
+4
View File
@@ -43,6 +43,10 @@ Test your application thoroughly using local development (refer to README.md for
- [deploy-cloudflare.md](deploy-cloudflare.md): for Cloudflare Workers deployment
- [deploy-docker.md](deploy-docker.md): for Docker deployment instructions and examples
## Debugging
We introduced the `/info/debug` page that provides a detailed overview of the application's environment, including the API keys, environment variables, and other configuration settings.
<br/>
## Community Projects - Share Your Project
+205 -172
View File
@@ -1,22 +1,22 @@
{
"name": "big-agi",
"version": "1.13.0",
"version": "1.14.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "big-agi",
"version": "1.13.0",
"version": "1.14.1",
"hasInstallScript": true,
"dependencies": {
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.3",
"@emotion/react": "^11.11.4",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.15.11",
"@mui/joy": "^5.0.0-beta.29",
"@next/bundle-analyzer": "^14.1.0",
"@next/third-parties": "^14.1.0",
"@next/bundle-analyzer": "^14.1.2",
"@next/third-parties": "^14.1.2",
"@prisma/client": "^5.10.2",
"@sanity/diff-match-patch": "^3.1.1",
"@t3-oss/env-nextjs": "^0.9.2",
@@ -30,7 +30,7 @@
"browser-fs-access": "^0.35.0",
"eventsource-parser": "^1.1.2",
"idb-keyval": "^6.2.1",
"next": "^14.1.0",
"next": "^14.1.2",
"nprogress": "^0.2.0",
"pdfjs-dist": "4.0.379",
"plantuml-encoder": "^1.4.0",
@@ -41,8 +41,8 @@
"react-dom": "^18.2.0",
"react-katex": "^3.0.1",
"react-markdown": "^9.0.1",
"react-player": "^2.14.1",
"react-resizable-panels": "^2.0.11",
"react-player": "^2.15.1",
"react-resizable-panels": "^2.0.12",
"react-timeago": "^7.2.0",
"remark-gfm": "^4.0.0",
"sharp": "^0.33.2",
@@ -51,15 +51,15 @@
"tiktoken": "^1.0.13",
"uuid": "^9.0.1",
"zod": "^3.22.4",
"zustand": "^4.5.1"
"zustand": "^4.5.2"
},
"devDependencies": {
"@cloudflare/puppeteer": "^0.0.5",
"@types/node": "^20.11.20",
"@types/node": "^20.11.24",
"@types/nprogress": "^0.2.3",
"@types/plantuml-encoder": "^1.4.2",
"@types/prismjs": "^1.26.3",
"@types/react": "^18.2.59",
"@types/react": "^18.2.62",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-csv": "^1.1.10",
"@types/react-dom": "^18.2.19",
@@ -67,7 +67,7 @@
"@types/react-timeago": "^4.1.7",
"@types/uuid": "^9.0.8",
"eslint": "^8.57.0",
"eslint-config-next": "^14.1.0",
"eslint-config-next": "^14.1.2",
"prettier": "^3.2.5",
"prisma": "^5.10.2",
"typescript": "^5.3.3"
@@ -266,9 +266,9 @@
}
},
"node_modules/@babel/runtime": {
"version": "7.23.9",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
"integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
"version": "7.24.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz",
"integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -277,9 +277,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.23.9",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz",
"integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==",
"version": "7.24.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz",
"integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==",
"dependencies": {
"@babel/helper-string-parser": "^7.23.4",
"@babel/helper-validator-identifier": "^7.22.20",
@@ -359,9 +359,9 @@
"integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
},
"node_modules/@emotion/is-prop-valid": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",
"integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==",
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
"integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
"dependencies": {
"@emotion/memoize": "^0.8.1"
}
@@ -372,9 +372,9 @@
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
},
"node_modules/@emotion/react": {
"version": "11.11.3",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.3.tgz",
"integrity": "sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==",
"version": "11.11.4",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
"integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.11.0",
@@ -1094,14 +1094,14 @@
}
},
"node_modules/@mui/base": {
"version": "5.0.0-beta.37",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.37.tgz",
"integrity": "sha512-/o3anbb+DeCng8jNsd3704XtmmLDZju1Fo8R2o7ugrVtPQ/QpcqddwKNzKPZwa0J5T8YNW3ZVuHyQgbTnQLisQ==",
"version": "5.0.0-beta.38",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.38.tgz",
"integrity": "sha512-AsjD6Y1X5A1qndxz8xCcR8LDqv31aiwlgWMPxFAX/kCKiIGKlK65yMeVZ62iQr/6LBz+9hSKLiD1i4TZdAHKcQ==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"@floating-ui/react-dom": "^2.0.8",
"@mui/types": "^7.2.13",
"@mui/utils": "^5.15.11",
"@mui/utils": "^5.15.12",
"@popperjs/core": "^2.11.8",
"clsx": "^2.1.0",
"prop-types": "^15.8.1"
@@ -1125,18 +1125,18 @@
}
},
"node_modules/@mui/core-downloads-tracker": {
"version": "5.15.11",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.11.tgz",
"integrity": "sha512-JVrJ9Jo4gyU707ujnRzmE8ABBWpXd6FwL9GYULmwZRtfPg89ggXs/S3MStQkpJ1JRWfdLL6S5syXmgQGq5EDAw==",
"version": "5.15.12",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.12.tgz",
"integrity": "sha512-brRO+tMFLpGyjEYHrX97bzqeF6jZmKpqqe1rY0LyIHAwP6xRVzh++zSecOQorDOCaZJg4XkGT9xfD+RWOWxZBA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
}
},
"node_modules/@mui/icons-material": {
"version": "5.15.11",
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.11.tgz",
"integrity": "sha512-R5ZoQqnKpd+5Ew7mBygTFLxgYsQHPhgR3TDXSgIHYIjGzYuyPLmGLSdcPUoMdi6kxiYqHlpPj4NJxlbaFD0UHA==",
"version": "5.15.12",
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.12.tgz",
"integrity": "sha512-3BXiDlOd3AexZoEXa/VqpIpVIvosCzjLHsdMWzKMXbZdnBiJjmb9ECdqfjn5SpTClO49qvkKLhkTqdBH3fSFGw==",
"dependencies": {
"@babel/runtime": "^7.23.9"
},
@@ -1159,16 +1159,16 @@
}
},
"node_modules/@mui/joy": {
"version": "5.0.0-beta.29",
"resolved": "https://registry.npmjs.org/@mui/joy/-/joy-5.0.0-beta.29.tgz",
"integrity": "sha512-23bU7NOSRa6BiWqExEA0p72ttMbzhoISX3qjKI8gcX+gAnk6lKKuhApBc/rD3ORdDQfiPx5LuxxLW0V73atQEg==",
"version": "5.0.0-beta.30",
"resolved": "https://registry.npmjs.org/@mui/joy/-/joy-5.0.0-beta.30.tgz",
"integrity": "sha512-m8f/sYarTohCqZOy3i1q/MYNmAshoccoRbOrWQ7+At1ReaJPz2D2LUYzYjJxxaK7sOjhDtY9etK7WfsrJhqGLA==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"@mui/base": "5.0.0-beta.37",
"@mui/core-downloads-tracker": "^5.15.11",
"@mui/system": "^5.15.11",
"@mui/base": "5.0.0-beta.38",
"@mui/core-downloads-tracker": "^5.15.12",
"@mui/system": "^5.15.12",
"@mui/types": "^7.2.13",
"@mui/utils": "^5.15.11",
"@mui/utils": "^5.15.12",
"clsx": "^2.1.0",
"prop-types": "^15.8.1"
},
@@ -1199,17 +1199,17 @@
}
},
"node_modules/@mui/material": {
"version": "5.15.11",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.11.tgz",
"integrity": "sha512-FA3eEuEZaDaxgN3CgfXezMWbCZ4VCeU/sv0F0/PK5n42qIgsPVD6q+j71qS7/62sp6wRFMHtDMpXRlN+tT/7NA==",
"version": "5.15.12",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.12.tgz",
"integrity": "sha512-vXJGg6KNKucsvbW6l7w9zafnpOp0CWc0Wx4mDykuABTpQ5QQBnZxP7+oB4yAS1hDZQ1WobbeIl0CjxK4EEahkA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"@mui/base": "5.0.0-beta.37",
"@mui/core-downloads-tracker": "^5.15.11",
"@mui/system": "^5.15.11",
"@mui/base": "5.0.0-beta.38",
"@mui/core-downloads-tracker": "^5.15.12",
"@mui/system": "^5.15.12",
"@mui/types": "^7.2.13",
"@mui/utils": "^5.15.11",
"@mui/utils": "^5.15.12",
"@types/react-transition-group": "^4.4.10",
"clsx": "^2.1.0",
"csstype": "^3.1.3",
@@ -1244,12 +1244,12 @@
}
},
"node_modules/@mui/private-theming": {
"version": "5.15.11",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.11.tgz",
"integrity": "sha512-jY/696SnSxSzO1u86Thym7ky5T9CgfidU3NFJjguldqK4f3Z5S97amZ6nffg8gTD0HBjY9scB+4ekqDEUmxZOA==",
"version": "5.15.12",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.12.tgz",
"integrity": "sha512-cqoSo9sgA5HE+8vZClbLrq9EkyOnYysooepi5eKaKvJ41lReT2c5wOZAeDDM1+xknrMDos+0mT2zr3sZmUiRRA==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"@mui/utils": "^5.15.11",
"@mui/utils": "^5.15.12",
"prop-types": "^15.8.1"
},
"engines": {
@@ -1301,15 +1301,15 @@
}
},
"node_modules/@mui/system": {
"version": "5.15.11",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.11.tgz",
"integrity": "sha512-9j35suLFq+MgJo5ktVSHPbkjDLRMBCV17NMBdEQurh6oWyGnLM4uhU4QGZZQ75o0vuhjJghOCA1jkO3+79wKsA==",
"version": "5.15.12",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.12.tgz",
"integrity": "sha512-/pq+GO6yN3X7r3hAwFTrzkAh7K1bTF5r8IzS79B9eyKJg7v6B/t4/zZYMR6OT9qEPtwf6rYN2Utg1e6Z7F1OgQ==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"@mui/private-theming": "^5.15.11",
"@mui/private-theming": "^5.15.12",
"@mui/styled-engine": "^5.15.11",
"@mui/types": "^7.2.13",
"@mui/utils": "^5.15.11",
"@mui/utils": "^5.15.12",
"clsx": "^2.1.0",
"csstype": "^3.1.3",
"prop-types": "^15.8.1"
@@ -1353,9 +1353,9 @@
}
},
"node_modules/@mui/utils": {
"version": "5.15.11",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.11.tgz",
"integrity": "sha512-D6bwqprUa9Stf8ft0dcMqWyWDKEo7D+6pB1k8WajbqlYIRA8J8Kw9Ra7PSZKKePGBGWO+/xxrX1U8HpG/aXQCw==",
"version": "5.15.12",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.12.tgz",
"integrity": "sha512-8SDGCnO2DY9Yy+5bGzu00NZowSDtuyHP4H8gunhHGQoIlhlY2Z3w64wBzAOLpYw/ZhJNzksDTnS/i8qdJvxuow==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"@types/prop-types": "^15.7.11",
@@ -1380,31 +1380,31 @@
}
},
"node_modules/@next/bundle-analyzer": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-14.1.0.tgz",
"integrity": "sha512-RJWjnlMp/1WSW0ahAdawV22WgJiC6BVaFS5Xfhw6gP7NJEX3cAJjh4JqSHKGr8GnLNRaFCVTQdDPoX84E421BA==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-14.1.2.tgz",
"integrity": "sha512-d/fjpUtW5iUQV6cHkrnBDyEK/yabmrk6jl05Evz9te0JG4AYNfQnBfXkzAlHaCkmXJ1YkCuo/LgduVQ05JRoHQ==",
"dependencies": {
"webpack-bundle-analyzer": "4.10.1"
}
},
"node_modules/@next/env": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.0.tgz",
"integrity": "sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw=="
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.2.tgz",
"integrity": "sha512-U0iEG+JF86j6qyu330sfPgsMmDVH8vWVmzZadl+an5EU3o5HqdNytOpM+HsFpl58PmhGBTKx3UmM9c+eoLK0mA=="
},
"node_modules/@next/eslint-plugin-next": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.0.tgz",
"integrity": "sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.2.tgz",
"integrity": "sha512-k9h9NfR1joJI48uwdQd/DuOV1mBgcjlmWaX45eAXCFGT96oc+/6SMjO3s7naVtTXqSKjFAgk2GDlW6Hv41ROXQ==",
"dev": true,
"dependencies": {
"glob": "10.3.10"
}
},
"node_modules/@next/swc-darwin-arm64": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.0.tgz",
"integrity": "sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.2.tgz",
"integrity": "sha512-E4/clgk0ZrYMo9eMRwP/4IO/cvXF1yEYSnGcdGfH+NYTR8bNFy76TSlc1Vb2rK3oaQY4BVHRpx8f/sMN/D5gNw==",
"cpu": [
"arm64"
],
@@ -1417,9 +1417,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz",
"integrity": "sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.2.tgz",
"integrity": "sha512-j8mEOI+ZM0tU9B/L/OGa6F7d9FXYMkog5OWWuhTWzz3iZ91UKIGGpD/ojTNKuejainDMgbqOBTNnLg0jZywM/g==",
"cpu": [
"x64"
],
@@ -1432,9 +1432,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz",
"integrity": "sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.2.tgz",
"integrity": "sha512-qpRrd5hl6BFTWiFLgHtJmqqQGRMs+ol0MN9pEp0SYoLs3j8OTErPiDMhbKWjMWHGdc2E3kg4RRBV3cSTZiePiQ==",
"cpu": [
"arm64"
],
@@ -1447,9 +1447,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz",
"integrity": "sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.2.tgz",
"integrity": "sha512-HAhvVXAv+wnbj0wztT0YnpgJVoHtw1Mv4Y1R/JJcg5yXSU8FsP2uEGUwjQaqPoD76YSZjuKl32YbJlmPgQbLFw==",
"cpu": [
"arm64"
],
@@ -1462,9 +1462,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz",
"integrity": "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.2.tgz",
"integrity": "sha512-PCWC312woXLWOXiedi1E+fEw6B/ECP1fMiK1nSoGS2E43o56Z8kq4WeJLbJoufFQGVj5ZOKU3jIVyV//3CI4wQ==",
"cpu": [
"x64"
],
@@ -1477,9 +1477,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz",
"integrity": "sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.2.tgz",
"integrity": "sha512-KQSKzdWPNrYZjeTPCsepEpagOzU8Nf3Zzu53X1cLsSY6QlOIkYcSgEihRjsMKyeQW4aSvc+nN5pIpC2pLWNSMA==",
"cpu": [
"x64"
],
@@ -1492,9 +1492,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz",
"integrity": "sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.2.tgz",
"integrity": "sha512-3b0PouKd09Ulm2T1tjaRnwQj9+UwSsMO680d/sD4XAlm29KkNmVLAEIwWTfb3L+E11Qyw+jdcN3HtbDCg5+vYA==",
"cpu": [
"arm64"
],
@@ -1507,9 +1507,9 @@
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz",
"integrity": "sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.2.tgz",
"integrity": "sha512-CC1gaJY4h+wg6d5r2biggGM6nCFXh/6WEim2VOQI0WrA6easCQi2P2hzWyrU6moQ0g1GOiWzesGc6nn0a92Kgg==",
"cpu": [
"ia32"
],
@@ -1522,9 +1522,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz",
"integrity": "sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.2.tgz",
"integrity": "sha512-pfASwanOd+yP3D80O63DuQffrBySZPuB7wRN0IGSRq/0rDm9p/MvvnLzzgP2kSiLOUklOrFYVax7P6AEzjGykQ==",
"cpu": [
"x64"
],
@@ -1537,9 +1537,9 @@
}
},
"node_modules/@next/third-parties": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@next/third-parties/-/third-parties-14.1.0.tgz",
"integrity": "sha512-f55SdvQ1WWxi4mb5QqtYQh5wRzbm1XaeP7s39DPn4ks3re+n9VlFccbMxBRHqkE62zAyIKmvkUB2cByT/gugGA==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/@next/third-parties/-/third-parties-14.1.2.tgz",
"integrity": "sha512-RWJ9fEnz4iopvtG0Jq5tcsOcWVe4Dnpk5nbNT97GV2tY0mwjwIL63FGJEarGpAVY8+eTBLMIW0v3Tb42iB6VYQ==",
"dependencies": {
"third-party-capital": "1.0.20"
},
@@ -1872,9 +1872,9 @@
"integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="
},
"node_modules/@types/node": {
"version": "20.11.20",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz",
"integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==",
"version": "20.11.24",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz",
"integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
@@ -1912,9 +1912,9 @@
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
},
"node_modules/@types/react": {
"version": "18.2.59",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.59.tgz",
"integrity": "sha512-DE+F6BYEC8VtajY85Qr7mmhTd/79rJKIHCg99MU9SWPB4xvLb6D1za2vYflgZfmPqQVEr6UqJTnLXEwzpVPuOg==",
"version": "18.2.63",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.63.tgz",
"integrity": "sha512-ppaqODhs15PYL2nGUOaOu2RSCCB4Difu4UFrP4I3NHLloXC/ESQzQMi9nvjfT1+rudd0d2L3fQPJxRSey+rGlQ==",
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@@ -1940,9 +1940,9 @@
}
},
"node_modules/@types/react-dom": {
"version": "18.2.19",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz",
"integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==",
"version": "18.2.20",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.20.tgz",
"integrity": "sha512-HXN/biJY8nv20Cn9ZbCFq3liERd4CozVZmKbaiZ9KiKTrWqsP7eoGDO6OOGvJQwoVFuiXaiJ7nBBjiFFbRmQMQ==",
"dev": true,
"dependencies": {
"@types/react": "*"
@@ -2394,6 +2394,25 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/array.prototype.findlast": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.4.tgz",
"integrity": "sha512-BMtLxpV+8BD+6ZPFIWmnUBpQoy+A+ujcg4rhp2iwCRJYA7PEh2MS4NL3lz8EiDlLrJPp2hg9qWihr5pd//jcGw==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.5",
"define-properties": "^1.2.1",
"es-abstract": "^1.22.3",
"es-errors": "^1.3.0",
"es-shim-unscopables": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/array.prototype.findlastindex": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz",
@@ -2449,6 +2468,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/array.prototype.toreversed": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz",
"integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"define-properties": "^1.2.0",
"es-abstract": "^1.22.1",
"es-shim-unscopables": "^1.0.0"
}
},
"node_modules/array.prototype.tosorted": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz",
@@ -2637,9 +2668,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001589",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz",
"integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==",
"version": "1.0.30001594",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001594.tgz",
"integrity": "sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g==",
"funding": [
{
"type": "opencollective",
@@ -3134,9 +3165,9 @@
"dev": true
},
"node_modules/enhanced-resolve": {
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
"version": "5.15.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz",
"integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.2.4",
@@ -3155,18 +3186,18 @@
}
},
"node_modules/es-abstract": {
"version": "1.22.4",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz",
"integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==",
"version": "1.22.5",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz",
"integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==",
"dev": true,
"dependencies": {
"array-buffer-byte-length": "^1.0.1",
"arraybuffer.prototype.slice": "^1.0.3",
"available-typed-arrays": "^1.0.6",
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.7",
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"es-set-tostringtag": "^2.0.2",
"es-set-tostringtag": "^2.0.3",
"es-to-primitive": "^1.2.1",
"function.prototype.name": "^1.1.6",
"get-intrinsic": "^1.2.4",
@@ -3174,15 +3205,15 @@
"globalthis": "^1.0.3",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2",
"has-proto": "^1.0.1",
"has-proto": "^1.0.3",
"has-symbols": "^1.0.3",
"hasown": "^2.0.1",
"internal-slot": "^1.0.7",
"is-array-buffer": "^3.0.4",
"is-callable": "^1.2.7",
"is-negative-zero": "^2.0.2",
"is-negative-zero": "^2.0.3",
"is-regex": "^1.1.4",
"is-shared-array-buffer": "^1.0.2",
"is-shared-array-buffer": "^1.0.3",
"is-string": "^1.0.7",
"is-typed-array": "^1.1.13",
"is-weakref": "^1.0.2",
@@ -3195,10 +3226,10 @@
"string.prototype.trim": "^1.2.8",
"string.prototype.trimend": "^1.0.7",
"string.prototype.trimstart": "^1.0.7",
"typed-array-buffer": "^1.0.1",
"typed-array-byte-length": "^1.0.0",
"typed-array-byte-offset": "^1.0.0",
"typed-array-length": "^1.0.4",
"typed-array-buffer": "^1.0.2",
"typed-array-byte-length": "^1.0.1",
"typed-array-byte-offset": "^1.0.2",
"typed-array-length": "^1.0.5",
"unbox-primitive": "^1.0.2",
"which-typed-array": "^1.1.14"
},
@@ -3369,12 +3400,12 @@
}
},
"node_modules/eslint-config-next": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.1.0.tgz",
"integrity": "sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.1.2.tgz",
"integrity": "sha512-g46mlgWmHoWhHuDbaQS8PLNQtBkVkiQMnVLhFcqnPSXN2I+R4Obom3ihCIQuNLbjVUgiFFHqmEwwtDuWv1wYKA==",
"dev": true,
"dependencies": {
"@next/eslint-plugin-next": "14.1.0",
"@next/eslint-plugin-next": "14.1.2",
"@rushstack/eslint-patch": "^1.3.3",
"@typescript-eslint/parser": "^5.4.2 || ^6.0.0",
"eslint-import-resolver-node": "^0.3.6",
@@ -3440,9 +3471,9 @@
}
},
"node_modules/eslint-module-utils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
"integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz",
"integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==",
"dev": true,
"dependencies": {
"debug": "^3.2.7"
@@ -3557,27 +3588,29 @@
}
},
"node_modules/eslint-plugin-react": {
"version": "7.33.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz",
"integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==",
"version": "7.34.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.0.tgz",
"integrity": "sha512-MeVXdReleBTdkz/bvcQMSnCXGi+c9kvy51IpinjnJgutl3YTHWsDdke7Z1ufZpGfDG8xduBDKyjtB9JH1eBKIQ==",
"dev": true,
"dependencies": {
"array-includes": "^3.1.6",
"array.prototype.flatmap": "^1.3.1",
"array.prototype.tosorted": "^1.1.1",
"array-includes": "^3.1.7",
"array.prototype.findlast": "^1.2.4",
"array.prototype.flatmap": "^1.3.2",
"array.prototype.toreversed": "^1.1.2",
"array.prototype.tosorted": "^1.1.3",
"doctrine": "^2.1.0",
"es-iterator-helpers": "^1.0.12",
"es-iterator-helpers": "^1.0.17",
"estraverse": "^5.3.0",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
"object.entries": "^1.1.6",
"object.fromentries": "^2.0.6",
"object.hasown": "^1.1.2",
"object.values": "^1.1.6",
"object.entries": "^1.1.7",
"object.fromentries": "^2.0.7",
"object.hasown": "^1.1.3",
"object.values": "^1.1.7",
"prop-types": "^15.8.1",
"resolve": "^2.0.0-next.4",
"resolve": "^2.0.0-next.5",
"semver": "^6.3.1",
"string.prototype.matchall": "^4.0.8"
"string.prototype.matchall": "^4.0.10"
},
"engines": {
"node": ">=4"
@@ -6097,11 +6130,11 @@
"dev": true
},
"node_modules/next": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/next/-/next-14.1.0.tgz",
"integrity": "sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==",
"version": "14.1.2",
"resolved": "https://registry.npmjs.org/next/-/next-14.1.2.tgz",
"integrity": "sha512-p4RfNmopqkzRP1uUyBJnHii+qMg71f2udWhTTZopBB8b3T5QXNzn7yO+LCYHPWZG2kAvEn4l4neyJHqkXvo2wg==",
"dependencies": {
"@next/env": "14.1.0",
"@next/env": "14.1.2",
"@swc/helpers": "0.5.2",
"busboy": "1.6.0",
"caniuse-lite": "^1.0.30001579",
@@ -6116,15 +6149,15 @@
"node": ">=18.17.0"
},
"optionalDependencies": {
"@next/swc-darwin-arm64": "14.1.0",
"@next/swc-darwin-x64": "14.1.0",
"@next/swc-linux-arm64-gnu": "14.1.0",
"@next/swc-linux-arm64-musl": "14.1.0",
"@next/swc-linux-x64-gnu": "14.1.0",
"@next/swc-linux-x64-musl": "14.1.0",
"@next/swc-win32-arm64-msvc": "14.1.0",
"@next/swc-win32-ia32-msvc": "14.1.0",
"@next/swc-win32-x64-msvc": "14.1.0"
"@next/swc-darwin-arm64": "14.1.2",
"@next/swc-darwin-x64": "14.1.2",
"@next/swc-linux-arm64-gnu": "14.1.2",
"@next/swc-linux-arm64-musl": "14.1.2",
"@next/swc-linux-x64-gnu": "14.1.2",
"@next/swc-linux-x64-musl": "14.1.2",
"@next/swc-win32-arm64-msvc": "14.1.2",
"@next/swc-win32-ia32-msvc": "14.1.2",
"@next/swc-win32-x64-msvc": "14.1.2"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
@@ -6784,9 +6817,9 @@
}
},
"node_modules/react-player": {
"version": "2.14.1",
"resolved": "https://registry.npmjs.org/react-player/-/react-player-2.14.1.tgz",
"integrity": "sha512-jILj7F9o+6NHzrJ1GqZIxfJgskvGmKeJ05FNhPvgiCpvMZFmFneKEkukywHcULDO2lqITm+zcEkLSq42mX0FbA==",
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/react-player/-/react-player-2.15.1.tgz",
"integrity": "sha512-ni1XFuYZuhIKKdeFII+KRLmIPcvCYlyXvtSMhNOgssdfnSovmakBtBTW2bxowPvmpKy5BTR4jC4CF79ucgHT+g==",
"dependencies": {
"deepmerge": "^4.0.0",
"load-script": "^1.0.0",
@@ -6828,9 +6861,9 @@
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/react-resizable-panels": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.0.11.tgz",
"integrity": "sha512-tA3OvGFEK/U9rKuEg6TpXcr+i+cN5X8B4UIvs7jqr5lby629pDTGvqRjo1EJLhBpRZfkg0Zz1INJlSYigaS99g==",
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.0.12.tgz",
"integrity": "sha512-m0cfwlVQ+460iQbOSVfs3MljVniHI/LGpHGQBa7aNCYUYwaERHcf5W/lCTsoRhbGQfMW9An0M8gxUHILA53Jeg==",
"peerDependencies": {
"react": "^16.14.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0"
@@ -7292,12 +7325,12 @@
}
},
"node_modules/side-channel": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz",
"integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.6",
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.4",
"object-inspect": "^1.13.1"
@@ -8550,9 +8583,9 @@
}
},
"node_modules/zustand": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.1.tgz",
"integrity": "sha512-XlauQmH64xXSC1qGYNv00ODaQ3B+tNPoy22jv2diYiP4eoDKr9LA+Bh5Bc3gplTrFdb6JVI+N4kc1DZ/tbtfPg==",
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.2.tgz",
"integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==",
"dependencies": {
"use-sync-external-store": "1.2.0"
},
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "big-agi",
"version": "1.13.0",
"version": "1.14.1",
"private": true,
"author": "Enrico Ros <enrico.ros@gmail.com>",
"repository": "https://github.com/enricoros/big-agi",
@@ -19,13 +19,13 @@
},
"dependencies": {
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.3",
"@emotion/react": "^11.11.4",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.15.11",
"@mui/joy": "^5.0.0-beta.29",
"@next/bundle-analyzer": "^14.1.0",
"@next/third-parties": "^14.1.0",
"@next/bundle-analyzer": "^14.1.2",
"@next/third-parties": "^14.1.2",
"@prisma/client": "^5.10.2",
"@sanity/diff-match-patch": "^3.1.1",
"@t3-oss/env-nextjs": "^0.9.2",
@@ -39,7 +39,7 @@
"browser-fs-access": "^0.35.0",
"eventsource-parser": "^1.1.2",
"idb-keyval": "^6.2.1",
"next": "^14.1.0",
"next": "^14.1.2",
"nprogress": "^0.2.0",
"pdfjs-dist": "4.0.379",
"plantuml-encoder": "^1.4.0",
@@ -50,8 +50,8 @@
"react-dom": "^18.2.0",
"react-katex": "^3.0.1",
"react-markdown": "^9.0.1",
"react-player": "^2.14.1",
"react-resizable-panels": "^2.0.11",
"react-player": "^2.15.1",
"react-resizable-panels": "^2.0.12",
"react-timeago": "^7.2.0",
"remark-gfm": "^4.0.0",
"sharp": "^0.33.2",
@@ -60,15 +60,15 @@
"tiktoken": "^1.0.13",
"uuid": "^9.0.1",
"zod": "^3.22.4",
"zustand": "^4.5.1"
"zustand": "^4.5.2"
},
"devDependencies": {
"@cloudflare/puppeteer": "^0.0.5",
"@types/node": "^20.11.20",
"@types/node": "^20.11.24",
"@types/nprogress": "^0.2.3",
"@types/plantuml-encoder": "^1.4.2",
"@types/prismjs": "^1.26.3",
"@types/react": "^18.2.59",
"@types/react": "^18.2.62",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-csv": "^1.1.10",
"@types/react-dom": "^18.2.19",
@@ -76,7 +76,7 @@
"@types/react-timeago": "^4.1.7",
"@types/uuid": "^9.0.8",
"eslint": "^8.57.0",
"eslint-config-next": "^14.1.0",
"eslint-config-next": "^14.1.2",
"prettier": "^3.2.5",
"prisma": "^5.10.2",
"typescript": "^5.3.3"
Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

@@ -64,6 +64,7 @@ const avatarIconSx = { width: 36, height: 36 };
export function makeAvatar(messageAvatar: string | null, messageRole: DMessage['role'] | string, messageOriginLLM: string | undefined, messagePurposeId: SystemPurposeId | undefined, messageSender: string, messageTyping: boolean, size: 'sm' | undefined = undefined): React.JSX.Element {
if (typeof messageAvatar === 'string' && messageAvatar)
return <Avatar alt={messageSender} src={messageAvatar} />;
const mascotSx = size === 'sm' ? avatarIconSx : { width: 64, height: 64 };
switch (messageRole) {
case 'system':
@@ -76,17 +77,18 @@ export function makeAvatar(messageAvatar: string | null, messageRole: DMessage['
// typing gif (people seem to love this, so keeping it after april fools')
const isTextToImage = messageOriginLLM === 'DALL·E' || messageOriginLLM === 'Prodia';
const isReact = messageOriginLLM?.startsWith('react-');
if (messageTyping) {
// animation: message typing
if (messageTyping)
return <Avatar
alt={messageSender} variant='plain'
src={isTextToImage ? 'https://i.giphy.com/media/5t9ujj9cMisyVjUZ0m/giphy.webp'
: isReact ? 'https://i.giphy.com/media/l44QzsOLXxcrigdgI/giphy.webp'
: 'https://i.giphy.com/media/jJxaUysjzO9ri/giphy.webp'}
src={isTextToImage ? 'https://i.giphy.com/media/5t9ujj9cMisyVjUZ0m/giphy.webp' // brush
: isReact ? 'https://i.giphy.com/media/l44QzsOLXxcrigdgI/giphy.webp' // mind
: 'https://i.giphy.com/media/jJxaUysjzO9ri/giphy.webp'} // typing
sx={{ ...mascotSx, borderRadius: 'sm' }}
/>;
}
// text-to-image: icon
// icon: text-to-image
if (isTextToImage)
return <FormatPaintIcon sx={{
...avatarIconSx,
@@ -95,15 +97,16 @@ export function makeAvatar(messageAvatar: string | null, messageRole: DMessage['
// purpose symbol (if present)
const symbol = SystemPurposes[messagePurposeId!]?.symbol;
if (symbol) return <Box sx={{
fontSize: '24px',
textAlign: 'center',
width: '100%',
minWidth: `${avatarIconSx.width}px`,
lineHeight: `${avatarIconSx.height}px`,
}}>
{symbol}
</Box>;
if (symbol)
return <Box sx={{
fontSize: '24px',
textAlign: 'center',
width: '100%',
minWidth: `${avatarIconSx.width}px`,
lineHeight: `${avatarIconSx.height}px`,
}}>
{symbol}
</Box>;
// default assistant avatar
return <SmartToyOutlinedIcon sx={avatarIconSx} />; // https://mui.com/static/images/avatar/2.jpg
+46 -8
View File
@@ -3,8 +3,9 @@ import { keyframes } from '@emotion/react';
import NextImage from 'next/image';
import TimeAgo from 'react-timeago';
import { AspectRatio, Box, Button, Card, CardContent, CardOverflow, Container, IconButton, Typography } from '@mui/joy';
import { AspectRatio, Box, Button, Card, CardContent, CardOverflow, Container, Grid, IconButton, Typography } from '@mui/joy';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import LaunchIcon from '@mui/icons-material/Launch';
import { Brand } from '~/common/app.config';
import { Link } from '~/common/components/Link';
@@ -12,7 +13,8 @@ import { ROUTE_INDEX } from '~/common/app.routes';
import { capitalizeFirstLetter } from '~/common/util/textUtils';
import { cssRainbowColorKeyframes } from '~/common/app.theme';
import { NewsItems, newsRoadmapCallout } from './news.data';
import { NewsItems } from './news.data';
// number of news items to show by default, before the expander
const DEFAULT_NEWS_COUNT = 3;
@@ -32,6 +34,39 @@ export const cssColorKeyframes = keyframes`
}`;
// callout, for special occasions
export const newsRoadmapCallout =
<Card variant='solid' invertedColors>
<CardContent sx={{ gap: 2 }}>
<Typography level='title-lg'>
Open Roadmap
</Typography>
<Typography level='body-sm'>
Take a peek at our roadmap to see what&apos;s in the pipeline.
Discover upcoming features and let us know what excites you the most!
</Typography>
<Grid container spacing={1}>
<Grid xs={12} sm={7}>
<Button
fullWidth variant='soft' color='primary' endDecorator={<LaunchIcon />}
component={Link} href={Brand.URIs.OpenProject} noLinkStyle target='_blank'
>
Explore
</Button>
</Grid>
<Grid xs={12} sm={5} sx={{ display: 'flex', flexAlign: 'center', justifyContent: 'center' }}>
<Button
fullWidth variant='plain' color='primary' endDecorator={<LaunchIcon />}
component={Link} href={Brand.URIs.OpenRepo + '/issues/new?template=roadmap-request.md&title=%5BSuggestion%5D'} noLinkStyle target='_blank'
>
Suggest a Feature
</Button>
</Grid>
</Grid>
</CardContent>
</Card>;
export function AppNews() {
// state
const [lastNewsIdx, setLastNewsIdx] = React.useState<number>(DEFAULT_NEWS_COUNT - 1);
@@ -111,12 +146,15 @@ export function AppNews() {
</Box>
{!!ni.items && (ni.items.length > 0) && (
<ul style={{ marginTop: 8, marginBottom: 8, paddingInlineStart: '1.5rem' }}>
{ni.items.filter(item => item.dev !== true).map((item, idx) => <li key={idx}>
< Typography component='div' level='body-sm'>
{item.text}
</Typography>
</li>)}
<ul style={{ marginTop: 8, marginBottom: 8, paddingInlineStart: '1.5rem', listStyleType: '"- "' }}>
{ni.items.filter(item => item.dev !== true).map((item, idx) => (
<li key={idx} style={{ listStyle: item.icon ? '" "' : '"- "', marginLeft: item.icon ? '-1.125rem' : undefined }}>
<Typography component='div' sx={{ fontSize: 'sm' }}>
{item.icon && <item.icon sx={{ fontSize: 'xs', mr: 0.75 }} />}
{item.text}
</Typography>
</li>
))}
</ul>
)}
+82 -74
View File
@@ -2,90 +2,32 @@ import * as React from 'react';
import { StaticImageData } from 'next/image';
import { SxProps } from '@mui/joy/styles/types';
import { Box, Button, Card, CardContent, Chip, Grid, Typography } from '@mui/joy';
import { Box, Chip, SvgIconProps, Typography } from '@mui/joy';
import AutoStoriesOutlinedIcon from '@mui/icons-material/AutoStoriesOutlined';
import GoogleIcon from '@mui/icons-material/Google';
import LaunchIcon from '@mui/icons-material/Launch';
import { AnthropicIcon } from '~/common/components/icons/vendors/AnthropicIcon';
import { GroqIcon } from '~/common/components/icons/vendors/GroqIcon';
import { LocalAIIcon } from '~/common/components/icons/vendors/LocalAIIcon';
import { MistralIcon } from '~/common/components/icons/vendors/MistralIcon';
import { PerplexityIcon } from '~/common/components/icons/vendors/PerplexityIcon';
import { Brand } from '~/common/app.config';
import { Link } from '~/common/components/Link';
import { clientUtmSource } from '~/common/util/pwaUtils';
import { platformAwareKeystrokes } from '~/common/components/KeyStroke';
// Images
// An image of a capybara sculpted entirely from black cotton candy, set against a minimalist backdrop with splashes of bright, contrasting sparkles. The capybara is calling on a 3D origami old-school pink telephone and the camera is zooming on the telephone. Close up photography, bokeh, white background.
// An image of a capybara sculpted entirely from iridescent blue cotton candy, gazing into a holographic galaxy of floating AI model icons (representing various AI models like Perplexity, Groq, etc.). The capybara is wearing a lightweight, futuristic headset, and its paws are gesturing as if orchestrating the movement of the models in the galaxy. The backdrop is minimalist, with occasional bursts of neon light beams, creating a sense of depth and wonder. Close-up photography, bokeh effect, with a dark but vibrant background to make the colors pop.
import coverV114 from '../../../public/images/covers/release-cover-v1.14.0.png';
// An image of a capybara sculpted entirely from black cotton candy, set against a minimalist backdrop with splashes of bright, contrasting sparkles. The capybara is using a computer with split screen made of origami, split keyboard and is wearing origami sunglasses with very different split reflections. Split halves are very contrasting. Close up photography, bokeh, white background.
import coverV113 from '../../../public/images/covers/release-cover-v1.13.0.png';
// An image of a capybara sculpted entirely from black cotton candy, set against a minimalist backdrop with splashes of bright, contrasting sparkles. The capybara is calling on a 3D origami old-school pink telephone and the camera is zooming on the telephone. Close up photography, bokeh, white background.
import coverV112 from '../../../public/images/covers/release-cover-v1.12.0.png';
const wowStyle: SxProps = {
textDecoration: 'underline',
textDecorationThickness: '0.4em',
textDecorationColor: 'rgba(var(--joy-palette-primary-lightChannel) / 1)',
// textDecorationColor: 'rgba(0 255 0 / 0.5)',
textDecorationSkipInk: 'none',
// textUnderlineOffset: '-0.5em',
};
function B(props: {
// one-of
href?: string,
issue?: number,
code?: string,
wow?: boolean,
children: React.ReactNode
}) {
const href =
props.issue ? `${Brand.URIs.OpenRepo}/issues/${props.issue}`
: props.code ? `${Brand.URIs.OpenRepo}/blob/main/${props.code}`
: props.href;
const boldText = (
<Typography component='span' color={!!href ? 'primary' : 'neutral'} sx={{ fontWeight: 'lg' }}>
{props.children}
</Typography>
);
if (!href)
return boldText;
return (
<Link href={href + clientUtmSource()} target='_blank' sx={props.wow ? wowStyle : undefined}>
{boldText} <LaunchIcon sx={{ mx: 0.5, fontSize: 16 }} />
</Link>
);
}
// callout, for special occasions
export const newsRoadmapCallout =
<Card variant='solid' invertedColors>
<CardContent sx={{ gap: 2 }}>
<Typography level='title-lg'>
Open Roadmap
</Typography>
<Typography level='body-sm'>
Take a peek at our roadmap to see what&apos;s in the pipeline.
Discover upcoming features and let us know what excites you the most!
</Typography>
<Grid container spacing={1}>
<Grid xs={12} sm={7}>
<Button
fullWidth variant='soft' color='primary' endDecorator={<LaunchIcon />}
component={Link} href={Brand.URIs.OpenProject} noLinkStyle target='_blank'
>
Explore
</Button>
</Grid>
<Grid xs={12} sm={5} sx={{ display: 'flex', flexAlign: 'center', justifyContent: 'center' }}>
<Button
fullWidth variant='plain' color='primary' endDecorator={<LaunchIcon />}
component={Link} href={Brand.URIs.OpenRepo + '/issues/new?template=roadmap-request.md&title=%5BSuggestion%5D'} noLinkStyle target='_blank'
>
Suggest a Feature
</Button>
</Grid>
</Grid>
</CardContent>
</Card>;
interface NewsItem {
versionCode: string;
versionName?: string;
@@ -94,15 +36,43 @@ interface NewsItem {
versionCoverImage?: StaticImageData;
text?: string | React.JSX.Element;
items?: {
text: string | React.JSX.Element;
text: React.ReactNode;
dev?: boolean;
issue?: number;
icon?: React.FC<SvgIconProps>;
}[];
}
// news and feature surfaces
export const NewsItems: NewsItem[] = [
// still unannounced: screen capture (when removed from labs)
/*{
versionCode: '1.15.0',
items: [
Best-Of
Draw
...
Screen Capture (when removed from labs)
]
}*/
{
versionCode: '1.14.1',
versionName: 'Modelmorphic',
versionCoverImage: coverV114,
versionDate: new Date('2024-03-07T08:00:00Z'),
items: [
{ text: <>Anthropic <B href='https://www.anthropic.com/news/claude-3-family'>Claude-3</B> support for smarter chats</>, issue: 443, icon: AnthropicIcon },
{ text: <><B issue={407}>Perplexity</B> support, including Online models</>, issue: 407, icon: PerplexityIcon },
{ text: <><B issue={427}>Groq</B> support, with speeds up to 500 tok/s</>, issue: 427, icon: GroqIcon },
{ text: <>Support for new Mistral-Large models</>, icon: MistralIcon },
{ text: <>Support for Google Gemini 1.5 models and various improvements</>, icon: GoogleIcon as any },
{ text: <>Deeper LocalAI integration including support for <B issue={411}>model galleries</B></>, icon: LocalAIIcon },
{ text: <>Major <B href='https://twitter.com/enricoros/status/1756553038293303434'>performance optimizations</B>: runs faster, saves power, saves memory</> },
{ text: <>Improvements: auto-size charts, search and folder experience</> },
{ text: <>Perfect chat scaling, with rapid keyboard shortcuts</> },
{ text: <>Also: diagrams auto-resize, open code with StackBlitz and JSFiddle, quick model visibility toggle, open links externally, docs on the web</> },
{ text: <>Fixes: standalone LaTeX blocks, close views by dragging, knowledge cutoff dates, crashes on Google translate (thanks dad)</> },
],
},
{
versionCode: '1.13.0',
versionName: 'Multi + Mind',
@@ -286,3 +256,41 @@ export const NewsItems: NewsItem[] = [
],
},
];
const wowStyle: SxProps = {
textDecoration: 'underline',
textDecorationThickness: '0.4em',
textDecorationColor: 'rgba(var(--joy-palette-primary-lightChannel) / 1)',
// textDecorationColor: 'rgba(0 255 0 / 0.5)',
textDecorationSkipInk: 'none',
// textUnderlineOffset: '-0.5em',
};
function B(props: {
// one-of
href?: string,
issue?: number,
code?: string,
wow?: boolean,
children: React.ReactNode
}) {
const href =
props.issue ? `${Brand.URIs.OpenRepo}/issues/${props.issue}`
: props.code ? `${Brand.URIs.OpenRepo}/blob/main/${props.code}`
: props.href;
const isExtIcon = !props.issue;
const boldText = (
<Typography component='span' color={!!href ? 'primary' : 'neutral'} sx={{ fontWeight: 'lg' }}>
{props.children}
</Typography>
);
if (!href)
return boldText;
return (
<Link href={href + clientUtmSource()} target='_blank' sx={props.wow ? wowStyle : undefined}>
{boldText} {isExtIcon ? <LaunchIcon sx={{ mx: 0.5, fontSize: 16 }} /> : <AutoStoriesOutlinedIcon sx={{ mx: 0.5, fontSize: 16 }} />}
</Link>
);
}
+1 -1
View File
@@ -4,7 +4,7 @@
import { useAppStateStore } from '~/common/state/store-appstate';
export const incrementalNewsVersion: number = 13;
export const incrementalNewsVersion: number = 14.1;
export function shallRedirectToNews() {
+4 -4
View File
@@ -38,13 +38,13 @@ export function UxLabsSettings() {
/>}
<FormSwitchControl
title={<><TitleIcon color={labsChatBarAlt ? 'primary' : undefined} sx={{ mr: 0.25 }} />Chat Title</>} description={'v1.14 · ' + (labsChatBarAlt === 'title' ? 'Show Title' : 'Show Options')}
checked={labsChatBarAlt === 'title'} onChange={(on) => setLabsChatBarAlt(on ? 'title' : false)}
title={<><SpeedIcon color={labsHighPerformance ? 'primary' : undefined} sx={{ mr: 0.25 }} />Performance</>} description={'v1.14 · ' + (labsHighPerformance ? 'Unlocked' : 'Default')}
checked={labsHighPerformance} onChange={setLabsHighPerformance}
/>
<FormSwitchControl
title={<><SpeedIcon color={labsHighPerformance ? 'primary' : undefined} sx={{ mr: 0.25 }} />Performance</>} description={'v1.14 · ' + (labsHighPerformance ? 'Unlocked' : 'Default')}
checked={labsHighPerformance} onChange={setLabsHighPerformance}
title={<><TitleIcon color={labsChatBarAlt ? 'primary' : undefined} sx={{ mr: 0.25 }} />Chat Title</>} description={'v1.14 · ' + (labsChatBarAlt === 'title' ? 'Show Title' : 'Show Models')}
checked={labsChatBarAlt === 'title'} onChange={(on) => setLabsChatBarAlt(on ? 'title' : false)}
/>
{!isMobile && <FormSwitchControl
@@ -8,9 +8,15 @@ export function ProviderTRPCQueryClient(props: { children: React.ReactNode }) {
defaultOptions: {
queries: {
retry: false,
// call functions even when the network is disconnected; this makes 127.0.0.1 work, while probably not causing other issues
networkMode: 'always',
// not tested yet, but they could be good defaults
// refetchOnWindowFocus: false,
// refetchOnMount: false,
},
mutations: {
retry: false,
networkMode: 'always',
},
},
}));
+3
View File
@@ -15,6 +15,9 @@ export function prettyBaseModel(model: string | undefined): string {
if (model.includes('gpt-3.5-turbo-16k')) return '3.5 Turbo 16k';
if (model.includes('gpt-3.5-turbo')) return '3.5 Turbo';
if (model.endsWith('.bin')) return model.slice(0, -4);
// [Anthropic]
if (model.includes('claude-3-opus')) return 'Claude 3 Opus';
if (model.includes('claude-3-sonnet')) return 'Claude 3 Sonnet';
// [LM Studio]
if (model.startsWith('C:\\') || model.startsWith('D:\\'))
return getModelFromFile(model).replace('.gguf', '');
+1 -1
View File
@@ -1,5 +1,5 @@
export function capitalizeFirstLetter(string: string) {
return string.charAt(0).toUpperCase() + string.slice(1);
return string?.length ? (string.charAt(0).toUpperCase() + string.slice(1)) : string;
}
export function createBase36Uid(checkDuplicates: string[]): string {
@@ -1,16 +1,46 @@
import type { ModelDescriptionSchema } from '../llm.server.types';
import { LLM_IF_OAI_Chat } from '../../store-llms';
import { LLM_IF_OAI_Chat, LLM_IF_OAI_Vision } from '../../store-llms';
const roundTime = (date: string) => Math.round(new Date(date).getTime() / 1000);
export const hardcodedAnthropicModels: ModelDescriptionSchema[] = [
{
id: 'claude-3-opus-20240229',
label: 'Claude 3 Opus',
created: roundTime('2024-02-29'),
description: 'Most powerful model for highly complex tasks',
contextWindow: 200000,
maxCompletionTokens: 4096,
pricing: {
cpmPrompt: 0.015,
cpmCompletion: 0.075,
},
trainingDataCutoff: 'Aug 2023',
interfaces: [LLM_IF_OAI_Chat, LLM_IF_OAI_Vision],
},
{
id: 'claude-3-sonnet-20240229',
label: 'Claude 3 Sonnet',
created: roundTime('2024-02-29'),
description: 'Ideal balance of intelligence and speed for enterprise workloads',
contextWindow: 200000,
maxCompletionTokens: 4096,
pricing: {
cpmPrompt: 0.003,
cpmCompletion: 0.015,
},
trainingDataCutoff: 'Aug 2023',
interfaces: [LLM_IF_OAI_Chat, LLM_IF_OAI_Vision],
},
/* Claude 3 Haiku will be here */
{
id: 'claude-2.1',
label: 'Claude 2.1',
created: roundTime('2023-11-21'),
description: 'Superior performance on tasks that require complex reasoning, with reduced model hallucination rates',
contextWindow: 200000,
maxCompletionTokens: 4096,
pricing: {
cpmPrompt: 0.008,
cpmCompletion: 0.024,
@@ -23,6 +53,7 @@ export const hardcodedAnthropicModels: ModelDescriptionSchema[] = [
created: roundTime('2023-07-11'),
description: 'Superior performance on tasks that require complex reasoning',
contextWindow: 100000,
maxCompletionTokens: 4096,
pricing: {
cpmPrompt: 0.008,
cpmCompletion: 0.024,
@@ -36,6 +67,7 @@ export const hardcodedAnthropicModels: ModelDescriptionSchema[] = [
created: roundTime('2023-08-09'),
description: 'Low-latency, high throughput model',
contextWindow: 100000,
maxCompletionTokens: 4096,
pricing: {
cpmPrompt: 0.00163,
cpmCompletion: 0.00551,
@@ -48,6 +80,7 @@ export const hardcodedAnthropicModels: ModelDescriptionSchema[] = [
created: roundTime('2023-03-14'),
description: 'Precise and fast',
contextWindow: 100000,
maxCompletionTokens: 2048,
interfaces: [LLM_IF_OAI_Chat],
hidden: true,
},
@@ -57,16 +90,8 @@ export const hardcodedAnthropicModels: ModelDescriptionSchema[] = [
created: roundTime('2023-03-14'),
description: 'Claude 1.3 is the latest version of Claude v1',
contextWindow: 100000,
maxCompletionTokens: 4096,
interfaces: [LLM_IF_OAI_Chat],
hidden: true,
},
{
id: 'claude-1.0',
label: 'Claude 1',
created: roundTime('2023-03-14'),
description: 'Claude 1.0 is the first version of Claude',
contextWindow: 9000,
interfaces: [LLM_IF_OAI_Chat],
hidden: true,
},
}
];
@@ -8,30 +8,36 @@ import { fetchJsonOrTRPCError } from '~/server/api/trpc.router.fetchers';
import { fixupHost } from '~/common/util/urlUtils';
import { OpenAIHistorySchema, openAIHistorySchema, OpenAIModelSchema, openAIModelSchema } from '../openai/openai.router';
import { llmsListModelsOutputSchema, llmsChatGenerateOutputSchema } from '../llm.server.types';
import { llmsChatGenerateOutputSchema, llmsListModelsOutputSchema } from '../llm.server.types';
import { AnthropicWire } from './anthropic.wiretypes';
import { AnthropicWireMessagesRequest, anthropicWireMessagesRequestSchema, AnthropicWireMessagesResponse, anthropicWireMessagesResponseSchema } from './anthropic.wiretypes';
import { hardcodedAnthropicModels } from './anthropic.models';
// Default hosts
const DEFAULT_API_VERSION_HEADERS = {
'anthropic-version': '2023-06-01',
'anthropic-beta': 'messages-2023-12-15',
};
const DEFAULT_MAX_TOKENS = 2048;
const DEFAULT_ANTHROPIC_HOST = 'api.anthropic.com';
const DEFAULT_HELICONE_ANTHROPIC_HOST = 'anthropic.hconeai.com';
// Mappers
export function anthropicAccess(access: AnthropicAccessSchema, apiPath: string): { headers: HeadersInit, url: string } {
// API version
const apiVersion = '2023-06-01';
async function anthropicPOST<TOut extends object, TPostBody extends object>(access: AnthropicAccessSchema, body: TPostBody, apiPath: string /*, signal?: AbortSignal*/): Promise<TOut> {
const { headers, url } = anthropicAccess(access, apiPath);
return await fetchJsonOrTRPCError<TOut, TPostBody>(url, 'POST', headers, body, 'Anthropic');
}
export function anthropicAccess(access: AnthropicAccessSchema, apiPath: string): { headers: HeadersInit, url: string } {
// API key
const anthropicKey = access.anthropicKey || env.ANTHROPIC_API_KEY || '';
// break for the missing key only on the default host
if (!anthropicKey)
if (!access.anthropicHost && !env.ANTHROPIC_API_HOST)
throw new Error('Missing Anthropic API Key. Add it on the UI (Models Setup) or server side (your deployment).');
if (!anthropicKey && !(access.anthropicHost || env.ANTHROPIC_API_HOST))
throw new Error('Missing Anthropic API Key. Add it on the UI (Models Setup) or server side (your deployment).');
// API host
let anthropicHost = fixupHost(access.anthropicHost || env.ANTHROPIC_API_HOST || DEFAULT_ANTHROPIC_HOST, apiPath);
@@ -49,7 +55,7 @@ export function anthropicAccess(access: AnthropicAccessSchema, apiPath: string):
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'anthropic-version': apiVersion,
...DEFAULT_API_VERSION_HEADERS,
'X-API-Key': anthropicKey,
...(heliKey && { 'Helicone-Auth': `Bearer ${heliKey}` }),
},
@@ -57,23 +63,68 @@ export function anthropicAccess(access: AnthropicAccessSchema, apiPath: string):
};
}
export function anthropicChatCompletionPayload(model: OpenAIModelSchema, history: OpenAIHistorySchema, stream: boolean): AnthropicWire.Complete.Request {
// encode the prompt for Claude models
const prompt = history.map(({ role, content }) => {
return role === 'assistant' ? `\n\nAssistant: ${content}` : `\n\nHuman: ${content}`;
}).join('') + '\n\nAssistant:';
return {
prompt,
model: model.id,
stream,
...(model.temperature && { temperature: model.temperature }),
...(model.maxTokens && { max_tokens_to_sample: model.maxTokens })
};
}
export function anthropicMessagesPayloadOrThrow(model: OpenAIModelSchema, history: OpenAIHistorySchema, stream: boolean): AnthropicWireMessagesRequest {
async function anthropicPOST<TOut extends object, TPostBody extends object>(access: AnthropicAccessSchema, body: TPostBody, apiPath: string /*, signal?: AbortSignal*/): Promise<TOut> {
const { headers, url } = anthropicAccess(access, apiPath);
return await fetchJsonOrTRPCError<TOut, TPostBody>(url, 'POST', headers, body, 'Anthropic');
// Take the System prompt, if it's the first message
// But if it's the only message, treat it as a user message
history = [...history];
let systemPrompt: string | undefined = undefined;
if (history[0]?.role === 'system' && history.length > 1)
systemPrompt = history.shift()?.content;
// Transform the OpenAIHistorySchema into the target messages format, ensuring that roles alternate between 'user' and 'assistant's
const messages = history.reduce(
(acc, historyItem, index) => {
const lastMessage: AnthropicWireMessagesRequest['messages'][number] | undefined = acc[acc.length - 1];
const anthropicRole = historyItem.role === 'assistant' ? 'assistant' : 'user';
if (index === 0 || anthropicRole !== lastMessage?.role) {
// Add a new message object if the role is different from the previous message
acc.push({
role: anthropicRole,
content: [
{ type: 'text', text: historyItem.content },
],
});
} else {
// Merge consecutive messages with the same role
(lastMessage.content as AnthropicWireMessagesRequest['messages'][number]['content']).push(
{ type: 'text', text: historyItem.content },
);
}
return acc;
},
[] as AnthropicWireMessagesRequest['messages'],
);
// NOTE: if the last message is 'assistant', then the API will perform a continuation - shall we add a user message? TBD
// NOTE: the following code has been disabled because Anthropic will reject empty text blocks
// If the messages array is empty, add a default user message
// if (messages.length === 0)
// messages.push({ role: 'user', content: [{ type: 'text', text: '' }] });
// Construct the request payload
const payload: AnthropicWireMessagesRequest = {
model: model.id,
...(systemPrompt !== undefined && { system: systemPrompt }),
messages: messages,
max_tokens: model.maxTokens || DEFAULT_MAX_TOKENS,
stream: stream,
...(model.temperature !== undefined && { temperature: model.temperature }),
// metadata: not useful to us
// stop_sequences: not useful to us
// top_p: not useful to us
// top_k: not useful to us
};
// Validate the payload against the schema to ensure correctness
const validated = anthropicWireMessagesRequestSchema.safeParse(payload);
if (!validated.success)
throw new Error(`Invalid message sequence for Anthropic models: ${validated.error.errors?.[0]?.message || validated.error}`);
return validated.data;
}
@@ -101,45 +152,36 @@ const chatGenerateInputSchema = z.object({
export const llmAnthropicRouter = createTRPCRouter({
/* Anthropic: list models
*
* See https://github.com/anthropics/anthropic-sdk-typescript/commit/7c53ded6b7f5f3efec0df295181f18469c37e09d?diff=unified for
* some details on the models, as the API docs are scarce: https://docs.anthropic.com/claude/reference/selecting-a-model
*/
/* [Anthropic] list models - https://docs.anthropic.com/claude/docs/models-overview */
listModels: publicProcedure
.input(listModelsInputSchema)
.output(llmsListModelsOutputSchema)
.query(() => ({ models: hardcodedAnthropicModels })),
/* Anthropic: Chat generation */
chatGenerate: publicProcedure
/* [Anthropic] Message generation (non-streaming) */
chatGenerateMessage: publicProcedure
.input(chatGenerateInputSchema)
.output(llmsChatGenerateOutputSchema)
.mutation(async ({ input }) => {
.mutation(async ({ input: { access, model, history } }) => {
const { access, model, history } = input;
// NOTES: doesn't support functions yet, supports multi-modal inputs (but they're not in our history, yet)
// ensure history has at least one message, and not from the assistant
if (history.length === 0 || history[0].role === 'assistant')
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: `[Anthropic Issue] Need one human character at least` });
// throw if the message sequence is not okay
const payload = anthropicMessagesPayloadOrThrow(model, history, false);
const response = await anthropicPOST<AnthropicWireMessagesResponse, AnthropicWireMessagesRequest>(access, payload, '/v1/messages');
const completion = anthropicWireMessagesResponseSchema.parse(response);
const wireCompletions = await anthropicPOST<AnthropicWire.Complete.Response, AnthropicWire.Complete.Request>(
access,
anthropicChatCompletionPayload(model, history, false),
'/v1/complete',
);
// validate output
if (!completion || completion.type !== 'message' || completion.role !== 'assistant' || completion.stop_reason === undefined)
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: `[Anthropic Issue] Invalid Message` });
if (completion.content.length !== 1 || completion.content[0].type !== 'text')
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: `[Anthropic Issue] No Single Text Message (${completion.content.length})` });
// expect a single output
if (wireCompletions.completion === undefined)
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: `[Anthropic Issue] No completions` });
if (wireCompletions.stop_reason === undefined)
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: `[Anthropic Issue] No stop_reason` });
// check for a function output
// got the completion (non-streaming)
return {
role: 'assistant',
finish_reason: wireCompletions.stop_reason === 'stop_sequence' ? 'stop' : 'length',
content: wireCompletions.completion || '',
role: completion.role,
content: completion.content[0].text,
finish_reason: completion.stop_reason === 'max_tokens' ? 'length' : 'stop',
};
}),
@@ -1,29 +1,151 @@
export namespace AnthropicWire {
export namespace Complete {
export interface Request {
prompt: string;
model: string;
max_tokens_to_sample?: number;
stop_sequences?: string[];
stream?: boolean;
temperature?: number;
top_k?: number;
top_p?: number;
metadata?: {
user_id?: string;
};
}
import { z } from 'zod';
export interface Response {
completion: string;
stop_reason: 'stop_sequence' | 'max_tokens' | string;
model: string;
stop: string | null; // the stop sequence, if stop_reason is 'stop_sequence'
log_id: string; // some log
// removed since the 2023-06-01 API version
// truncated: boolean;
// exception: string | null;
}
}
}
// text, e.g.: { 'type': 'text', 'text': 'Hello, Claude' }
const anthropicWireTextBlockSchema = z.object({
type: z.literal('text'),
text: z.string(),
});
// image, e.g.: { 'type': 'image', 'source': { 'type': 'base64', 'media_type': 'image/jpeg', 'data': '/9j/4AAQSkZJRg...' } }
const anthropicWireImageBlockSchema = z.object({
type: z.literal('image'),
source: z.object({
type: z.enum(['base64']),
media_type: z.enum(['image/jpeg', 'image/png', 'image/gif', 'image/webp']),
data: z.string(),
}),
});
const anthropicWireMessagesSchema = z.array(
z.object({
role: z.enum(['user', 'assistant']),
// NOTE: could be a string or an array of text/image blocks, but for a better implementation
// we will assume it's always an array
// content: z.union([
// z.array(z.union([anthropicWireTextBlockSchema, anthropicWireImageBlockSchema])),
// z.string(),
// ]),
content: z.array(
z.union([
anthropicWireTextBlockSchema,
anthropicWireImageBlockSchema,
]),
),
}),
);
export const anthropicWireMessagesRequestSchema = z.object({
model: z.string(),
/**
* If you want to include a system prompt, you can use the top-level system parameter — there is no "system" role for input messages in the Messages API.
*/
system: z.string().optional(),
/**
* (required) Input messages. - operates on alternating user and assistant conversational turns - the first message must always use the user role
* If the final message uses the assistant role, the response content will continue immediately from the content in that message.
* This can be used to constrain part of the model's response.
*/
messages: anthropicWireMessagesSchema.refine(
(messages) => {
// Ensure the first message uses the user role
if (messages.length === 0 || messages[0].role !== 'user')
return false;
// Ensure messages alternate between user and assistant roles
for (let i = 1; i < messages.length; i++)
if (messages[i].role === messages[i - 1].role)
return false;
return true;
},
{ message: `messages must alternate between User and Assistant roles, starting with the User role` },
),
/**
* (required) The maximum number of tokens to generate before stopping.
*/
max_tokens: z.number(),
/**
* (optional) Metadata to include with the request.
* user_id: This should be a uuid, hash value, or other opaque identifier.
*/
metadata: z.object({
user_id: z.string().optional(),
}).optional(),
/**
* Custom text sequences that will cause the model to stop generating.
*/
stop_sequences: z.array(z.string()).optional(),
/**
* Whether to incrementally stream the response using server-sent events. Default: false
*/
stream: z.boolean().optional(),
/**
* Defaults to 1.0. Ranges from 0.0 to 1.0. Use temperature closer to 0.0 for analytical / multiple choice, and closer to 1.0 for creative and generative tasks.
*/
temperature: z.number().optional(),
/**
* Use nucleus sampling.
* Recommended for advanced use cases only. You usually only need to use temperature.
*/
top_p: z.number().optional(),
/**
* Only sample from the top K options for each subsequent token.
* Recommended for advanced use cases only. You usually only need to use temperature.
*/
top_k: z.number().optional(),
});
export type AnthropicWireMessagesRequest = z.infer<typeof anthropicWireMessagesRequestSchema>;
export const anthropicWireMessagesResponseSchema = z.object({
// Unique object identifier.
id: z.string(),
// For Messages, this is always "message".
type: z.literal('message'),
// Conversational role of the generated message. This will always be "assistant".
role: z.literal('assistant'),
/**
* Content generated by the model.
* This is an array of content blocks, each of which has a type that determines its shape. Currently, the only type in responses is "text".
*/
content: z.array(anthropicWireTextBlockSchema),
// The model that handled the request.
model: z.string(),
/**
* This may be one the following values:
*
* "end_turn": the model reached a natural stopping point
* "max_tokens": we exceeded the requested max_tokens or the model's maximum
* "stop_sequence": one of your provided custom stop_sequences was generated
* Note that these values are different than those in /v1/complete, where end_turn and stop_sequence were not differentiated.
*
* In non-streaming mode this value is always non-null. In streaming mode, it is null in the message_start event and non-null otherwise.
*/
stop_reason: z.enum(['end_turn', 'max_tokens', 'stop_sequence']).nullable(),
// Which custom stop sequence was generated, if any.
stop_sequence: z.string().nullable(),
// Billing and rate-limit usage.
usage: z.object({
input_tokens: z.number(),
output_tokens: z.number(),
}),
});
export type AnthropicWireMessagesResponse = z.infer<typeof anthropicWireMessagesResponseSchema>;
+94 -19
View File
@@ -2,12 +2,12 @@ import { z } from 'zod';
import { NextRequest, NextResponse } from 'next/server';
import { createParser as createEventsourceParser, EventSourceParseCallback, EventSourceParser, ParsedEvent, ReconnectInterval } from 'eventsource-parser';
import { createEmptyReadableStream, debugGenerateCurlCommand, nonTrpcServerFetchOrThrow, safeErrorString, SERVER_DEBUG_WIRE } from '~/server/wire';
import { createEmptyReadableStream, debugGenerateCurlCommand, nonTrpcServerFetchOrThrow, safeErrorString, SERVER_DEBUG_WIRE, serverCapitalizeFirstLetter } from '~/server/wire';
// Anthropic server imports
import type { AnthropicWire } from './anthropic/anthropic.wiretypes';
import { anthropicAccess, anthropicAccessSchema, anthropicChatCompletionPayload } from './anthropic/anthropic.router';
import { AnthropicWireMessagesResponse, anthropicWireMessagesResponseSchema } from './anthropic/anthropic.wiretypes';
import { anthropicAccess, anthropicAccessSchema, anthropicMessagesPayloadOrThrow } from './anthropic/anthropic.router';
// Gemini server imports
import { geminiAccess, geminiAccessSchema, geminiGenerateContentTextPayload } from './gemini/gemini.router';
@@ -38,7 +38,7 @@ type MuxingFormat = 'sse' | 'json-nl';
* The peculiarity of our parser is the injection of a JSON structure at the beginning of the stream, to
* communicate parameters before the text starts flowing to the client.
*/
type AIStreamParser = (data: string) => { text: string, close: boolean };
type AIStreamParser = (data: string, eventType?: string) => { text: string, close: boolean };
const chatStreamingInputSchema = z.object({
@@ -74,9 +74,9 @@ export async function llmStreamingRelayHandler(req: NextRequest): Promise<Respon
let body: object;
switch (access.dialect) {
case 'anthropic':
requestAccess = anthropicAccess(access, '/v1/complete');
body = anthropicChatCompletionPayload(model, history, true);
vendorStreamParser = createStreamParserAnthropic();
requestAccess = anthropicAccess(access, '/v1/messages');
body = anthropicMessagesPayloadOrThrow(model, history, true);
vendorStreamParser = createStreamParserAnthropicMessages();
break;
case 'gemini':
@@ -121,7 +121,7 @@ export async function llmStreamingRelayHandler(req: NextRequest): Promise<Respon
console.error(`/api/llms/stream: fetch issue:`, access.dialect, fetchOrVendorError, requestAccess?.url);
// client-side users visible message
return new NextResponse(`[Issue] ${access.dialect}: ${fetchOrVendorError}`
return new NextResponse(`[Issue] ${serverCapitalizeFirstLetter(access.dialect)}: ${fetchOrVendorError}`
+ (process.env.NODE_ENV === 'development' ? ` · [URL: ${requestAccess?.url}]` : ''), { status: 500 });
}
@@ -217,7 +217,7 @@ function createEventStreamTransformer(muxingFormat: MuxingFormat, vendorTextPars
}
try {
const { text, close } = vendorTextParser(event.data);
const { text, close } = vendorTextParser(event.data, event.event);
if (text)
controller.enqueue(textEncoder.encode(text));
if (close)
@@ -246,19 +246,94 @@ function createEventStreamTransformer(muxingFormat: MuxingFormat, vendorTextPars
/// Stream Parsers
function createStreamParserAnthropic(): AIStreamParser {
let hasBegun = false;
function createStreamParserAnthropicMessages(): AIStreamParser {
let responseMessage: AnthropicWireMessagesResponse | null = null;
let hasErrored = false;
return (data: string) => {
// Note: at this stage, the parser only returns the text content as text, which is streamed as text
// to the client. It is however building in parallel the responseMessage object, which is not
// yet used, but contains token counts, for instance.
return (data: string, eventName?: string) => {
let text = '';
const json: AnthropicWire.Complete.Response = JSON.parse(data);
let text = json.completion;
// if we've errored, we should not be receiving more data
if (hasErrored)
console.log('Anthropic stream has errored already, but received more data:', data);
// hack: prepend the model name to the first packet
if (!hasBegun) {
hasBegun = true;
const firstPacket: ChatStreamingFirstOutputPacketSchema = { model: json.model };
text = JSON.stringify(firstPacket) + text;
switch (eventName) {
// Ignore pings
case 'ping':
break;
// Initialize the message content for a new message
case 'message_start':
const firstMessage = !responseMessage;
const { message } = JSON.parse(data);
responseMessage = anthropicWireMessagesResponseSchema.parse(message);
// hack: prepend the model name to the first packet
if (firstMessage) {
const firstPacket: ChatStreamingFirstOutputPacketSchema = { model: responseMessage.model };
text = JSON.stringify(firstPacket);
}
break;
// Initialize content block if needed
case 'content_block_start':
if (responseMessage) {
const { index, content_block } = JSON.parse(data);
if (responseMessage.content[index] === undefined)
responseMessage.content[index] = content_block;
text = responseMessage.content[index].text;
} else
throw new Error('Unexpected content block start');
break;
// Append delta text to the current message content
case 'content_block_delta':
if (responseMessage) {
const { index, delta } = JSON.parse(data);
if (delta.type !== 'text_delta')
throw new Error(`Unexpected content block non-text delta (${delta.type})`);
if (responseMessage.content[index] === undefined)
throw new Error(`Unexpected content block delta location (${index})`);
responseMessage.content[index].text += delta.text;
text = delta.text;
} else
throw new Error('Unexpected content block delta');
break;
// Finalize content block if needed.
case 'content_block_stop':
if (responseMessage) {
const { index } = JSON.parse(data);
if (responseMessage.content[index] === undefined)
throw new Error(`Unexpected content block end location (${index})`);
} else
throw new Error('Unexpected content block stop');
break;
// Optionally handle top-level message changes. Example: updating stop_reason
case 'message_delta':
if (responseMessage) {
const { delta } = JSON.parse(data);
Object.assign(responseMessage, delta);
} else
throw new Error('Unexpected message delta');
break;
// We can now close the message
case 'message_stop':
return { text: '', close: true };
// Occasionaly, the server will send errors, such as {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}
case 'error':
hasErrored = true;
const { error } = JSON.parse(data);
const errorText = (error.type && error.message) ? `${error.type}: ${error.message}` : safeErrorString(error);
return { text: `[Anthropic Server Error] ${errorText}`, close: true };
default:
throw new Error(`Unexpected event name: ${eventName}`);
}
return { text, close: false };
@@ -23,6 +23,7 @@ const modelDescriptionSchema = z.object({
maxCompletionTokens: z.number().optional(),
pricing: pricingSchema.optional(),
// rateLimits: rateLimitsSchema.optional(),
trainingDataCutoff: z.string().optional(),
interfaces: z.array(z.enum([LLM_IF_OAI_Chat, LLM_IF_OAI_Fn, LLM_IF_OAI_Complete, LLM_IF_OAI_Vision])),
hidden: z.boolean().optional(),
});
@@ -491,7 +491,8 @@ export function oobaboogaModelToModelDescription(modelId: string, created: numbe
const orOldModelIDs = [
'openai/gpt-3.5-turbo-0301', 'openai/gpt-4-0314', 'openai/gpt-4-32k-0314', 'openai/text-davinci-002',
'anthropic/claude-v1', 'anthropic/claude-1.2', 'anthropic/claude-instant-v1-100k', 'anthropic/claude-v1-100k', 'anthropic/claude-instant-1.0',
'anthropic/claude-2.1', 'anthropic/claude-2.0', 'anthropic/claude-v1', 'anthropic/claude-1.2',
'anthropic/claude-instant-v1-100k', 'anthropic/claude-v1-100k', 'anthropic/claude-instant-1.0',
];
const orModelFamilyOrder = [
@@ -39,6 +39,12 @@ export function AnthropicSourceSetup(props: { sourceId: DModelSourceId }) {
return <>
<Alert variant='soft' color='success'>
<div>
Note: <strong>Claude-3</strong> models are now supported.
</div>
</Alert>
<FormInputKey
id='anthropic-key' label={!!anthropicHost ? 'API Key' : 'Anthropic API Key'}
rightLabel={<>{needsUserKey
@@ -77,4 +83,5 @@ export function AnthropicSourceSetup(props: { sourceId: DModelSourceId }) {
{isError && <InlineError error={error} />}
</>;
;
}
+1 -1
View File
@@ -62,7 +62,7 @@ export const ModelVendorAnthropic: IModelVendor<SourceSetupAnthropic, AnthropicA
const { llmRef, llmTemperature, llmResponseTokens } = llmOptions;
try {
return await apiAsync.llmAnthropic.chatGenerate.mutate({
return await apiAsync.llmAnthropic.chatGenerateMessage.mutate({
access,
model: {
id: llmRef,
+4
View File
@@ -48,6 +48,10 @@ export function safeErrorString(error: any): string | null {
return error.toString();
}
export function serverCapitalizeFirstLetter(string: string) {
return string?.length ? (string.charAt(0).toUpperCase() + string.slice(1)) : string;
}
/**
* Weak (meaning the string could be encoded poorly) function that returns a string that can be used to debug a request