mirror of
				https://github.com/amithkoujalgi/ollama4j.git
				synced 2025-10-31 00:20:40 +01:00 
			
		
		
		
	Compare commits
	
		
			19 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 0d091d1826 | ||
|   | 9fd77a6743 | ||
|   | 57a962148b | ||
|   | 3c64f2099f | ||
|   | a9c7f4e5e0 | ||
|   | e7f58d4e0d | ||
|   | 7ef859bba5 | ||
|   | 3c30593e1e | ||
|   | 98b794ca2b | ||
|   | bc90a15a68 | ||
|   | bb4689e94b | ||
|   | 6739c93edc | ||
|   | c8c30d703b | ||
|   | 419b0369c9 | ||
|   | d9a94b95e1 | ||
|   | db1db948c8 | ||
|   | 41ad780224 | ||
|   | cb58c6a9b0 | ||
|   | d1115e0b35 | 
							
								
								
									
										2
									
								
								.github/workflows/publish-docs.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/publish-docs.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| # Simple workflow for deploying static content to GitHub Pages | ||||
| name: Deploy Docs to GH Pages | ||||
| name: Publish Docs to GH Pages | ||||
|  | ||||
| on: | ||||
|   release: | ||||
|   | ||||
							
								
								
									
										13
									
								
								.github/workflows/run-tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								.github/workflows/run-tests.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,15 +1,19 @@ | ||||
| name: Run Tests | ||||
| name: Run Unit and Integration Tests | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - main | ||||
|  | ||||
|   workflow_dispatch: | ||||
|     inputs: | ||||
|       branch: | ||||
|         description: 'Branch name to run tests on' | ||||
|         description: 'Branch name to run the tests on' | ||||
|         required: true | ||||
|         default: 'main' | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|   run-tests: | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     steps: | ||||
| @@ -27,3 +31,6 @@ jobs: | ||||
|  | ||||
|       - name: Run unit tests | ||||
|         run: mvn clean test -Punit-tests | ||||
|  | ||||
|       - name: Run integration tests | ||||
|         run: mvn clean verify -Pintegration-tests | ||||
							
								
								
									
										89
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								README.md
									
									
									
									
									
								
							| @@ -31,8 +31,11 @@ Find more details on the [website](https://ollama4j.github.io/ollama4j/). | ||||
|  | ||||
|  | ||||
| [](https://codecov.io/gh/ollama4j/ollama4j) | ||||
|  | ||||
| [](https://github.com/ollama4j/ollama4j/actions/workflows/run-tests.yml) | ||||
|  | ||||
|  | ||||
|  | ||||
| </div> | ||||
|  | ||||
| [//]: # () | ||||
| @@ -45,6 +48,7 @@ Find more details on the [website](https://ollama4j.github.io/ollama4j/). | ||||
| - [Requirements](#requirements) | ||||
| - [Installation](#installation) | ||||
| - [API Spec](https://ollama4j.github.io/ollama4j/category/apis---model-management) | ||||
| - [Examples](#examples) | ||||
| - [Javadoc](https://ollama4j.github.io/ollama4j/apidocs/) | ||||
| - [Development](#development) | ||||
| - [Contributions](#get-involved) | ||||
| @@ -73,61 +77,6 @@ Find more details on the [website](https://ollama4j.github.io/ollama4j/). | ||||
|   <img src="https://img.shields.io/badge/v0.3.0-green.svg?style=for-the-badge&labelColor=gray&label=Ollama&color=blue" alt=""/> | ||||
| </a> | ||||
|  | ||||
| <table> | ||||
| <tr> | ||||
| <td>  | ||||
|  | ||||
| <a href="https://ollama.ai/" target="_blank">Local Installation</a> | ||||
|  | ||||
| </td>  | ||||
|  | ||||
| <td>  | ||||
|  | ||||
| <a href="https://hub.docker.com/r/ollama/ollama" target="_blank">Docker Installation</a> | ||||
|  | ||||
| </td> | ||||
| </tr> | ||||
| <tr> | ||||
| <td> | ||||
|  | ||||
| <a href="https://ollama.com/download/Ollama-darwin.zip" target="_blank">Download for macOS</a> | ||||
|  | ||||
| <a href="https://ollama.com/download/OllamaSetup.exe" target="_blank">Download for Windows</a> | ||||
|  | ||||
| Install on Linux | ||||
|  | ||||
| ```shell  | ||||
| curl -fsSL https://ollama.com/install.sh | sh | ||||
| ``` | ||||
|  | ||||
| </td> | ||||
| <td> | ||||
|  | ||||
|  | ||||
|  | ||||
| CPU only | ||||
|  | ||||
| ```shell | ||||
| docker run -d -p 11434:11434 \ | ||||
|   -v ollama:/root/.ollama \ | ||||
|   --name ollama \ | ||||
|   ollama/ollama | ||||
| ``` | ||||
|  | ||||
| NVIDIA GPU | ||||
|  | ||||
| ```shell | ||||
| docker run -d -p 11434:11434 \ | ||||
|   --gpus=all \ | ||||
|   -v ollama:/root/.ollama \ | ||||
|   --name ollama \ | ||||
|   ollama/ollama | ||||
| ``` | ||||
|  | ||||
| </td> | ||||
| </tr> | ||||
| </table> | ||||
|  | ||||
| ## Installation | ||||
|  | ||||
| > [!NOTE] | ||||
| @@ -266,25 +215,29 @@ make integration-tests | ||||
|  | ||||
| Newer artifacts are published via GitHub Actions CI workflow when a new release is created from `main` branch. | ||||
|  | ||||
| ## Examples | ||||
|  | ||||
| The `ollama4j-examples` repository contains examples for using the Ollama4j library. You can explore it [here](https://github.com/ollama4j/ollama4j-examples).  | ||||
|  | ||||
| ## ⭐ Give us a Star! | ||||
|  | ||||
| If you like or are using this project to build your own, please give us a star. It's a free way to show your support. | ||||
|  | ||||
| ## Who's using Ollama4j? | ||||
|  | ||||
| | # | Project Name      | Description                                                                                                   | Link                                                                                                                                           | | ||||
| |---|-------------------|---------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | 1 | Datafaker         | A library to generate fake data                                                                               | [GitHub](https://github.com/datafaker-net/datafaker-experimental/tree/main/ollama-api)                                                         | | ||||
| | 2 | Vaadin Web UI     | UI-Tester for interactions with Ollama via ollama4j                                                           | [GitHub](https://github.com/TEAMPB/ollama4j-vaadin-ui)                                                                                         | | ||||
| | 3 | ollama-translator | A Minecraft 1.20.6 Spigot plugin that translates all messages into a specific target language via Ollama      | [GitHub](https://github.com/liebki/ollama-translator)                                                                                          | | ||||
| | 4 | AI Player         | A Minecraft mod that adds an intelligent "second player" to the game                                          | [GitHub](https://github.com/shasankp000/AI-Player), <br/> [Reddit Thread](https://www.reddit.com/r/fabricmc/comments/1e65x5s/comment/ldr2vcf/) | | ||||
| | 5 | Ollama4j Web UI   | A web UI for Ollama written in Java using Spring Boot, Vaadin, and Ollama4j                                   | [GitHub](https://github.com/ollama4j/ollama4j-web-ui)                                                                                          | | ||||
| | 6 | JnsCLI            | A command-line tool for Jenkins that manages jobs, builds, and configurations, with AI-powered error analysis | [GitHub](https://github.com/mirum8/jnscli)                                                                                                     | | ||||
| | 7 | Katie Backend     | An open-source AI-based question-answering platform for accessing private domain knowledge                    | [GitHub](https://github.com/wyona/katie-backend)                                                                                               | | ||||
| | 8 | TeleLlama3 Bot    | A question-answering Telegram bot                                                                             | [Repo](https://git.hiast.edu.sy/mohamadbashar.disoki/telellama3-bot)                                                                           | | ||||
| | 9 | moqui-wechat      | A moqui-wechat component                                                                                      | [GitHub](https://github.com/heguangyong/moqui-wechat)                                                                                          | | ||||
| | 10 | B4X      | A set of simple and powerful RAD tool for Desktop and Server development                                              | [Website](https://www.b4x.com/android/forum/threads/ollama4j-library-pnd_ollama4j-your-local-offline-llm-like-chatgpt.165003/)     |                                                               | ||||
|  | ||||
| | #  | Project Name      | Description                                                                                                                                                        | Link                                                                                                                                                                                          | | ||||
| |----|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | 1  | Datafaker         | A library to generate fake data                                                                                                                                    | [GitHub](https://github.com/datafaker-net/datafaker-experimental/tree/main/ollama-api)                                                                                                        | | ||||
| | 2  | Vaadin Web UI     | UI-Tester for interactions with Ollama via ollama4j                                                                                                                | [GitHub](https://github.com/TEAMPB/ollama4j-vaadin-ui)                                                                                                                                        | | ||||
| | 3  | ollama-translator | A Minecraft 1.20.6 Spigot plugin that translates all messages into a specific target language via Ollama                                                           | [GitHub](https://github.com/liebki/ollama-translator)                                                                                                                                         | | ||||
| | 4  | AI Player         | A Minecraft mod that adds an intelligent "second player" to the game                                                                                               | [Website](https://modrinth.com/mod/ai-player), [GitHub](https://github.com/shasankp000/AI-Player), <br/> [Reddit Thread](https://www.reddit.com/r/fabricmc/comments/1e65x5s/comment/ldr2vcf/) | | ||||
| | 5  | Ollama4j Web UI   | A web UI for Ollama written in Java using Spring Boot, Vaadin, and Ollama4j                                                                                        | [GitHub](https://github.com/ollama4j/ollama4j-web-ui)                                                                                                                                         | | ||||
| | 6  | JnsCLI            | A command-line tool for Jenkins that manages jobs, builds, and configurations, with AI-powered error analysis                                                      | [GitHub](https://github.com/mirum8/jnscli)                                                                                                                                                    | | ||||
| | 7  | Katie Backend     | An open-source AI-based question-answering platform for accessing private domain knowledge                                                                         | [GitHub](https://github.com/wyona/katie-backend)                                                                                                                                              | | ||||
| | 8  | TeleLlama3 Bot    | A question-answering Telegram bot                                                                                                                                  | [Repo](https://git.hiast.edu.sy/mohamadbashar.disoki/telellama3-bot)                                                                                                                          | | ||||
| | 9  | moqui-wechat      | A moqui-wechat component                                                                                                                                           | [GitHub](https://github.com/heguangyong/moqui-wechat)                                                                                                                                         | | ||||
| | 10 | B4X               | A set of simple and powerful RAD tool for Desktop and Server development                                                                                           | [Website](https://www.b4x.com/android/forum/threads/ollama4j-library-pnd_ollama4j-your-local-offline-llm-like-chatgpt.165003/)                                                                |                                                               | ||||
| | 11 | Research Article  | Article: `Large language model based mutations in genetic improvement` - published on National Library of Medicine (National Center for Biotechnology Information) | [Website](https://pmc.ncbi.nlm.nih.gov/articles/PMC11750896/)                                                                                                                                 | | ||||
|  | ||||
| ## Traction | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,8 @@ sidebar_position: 7 | ||||
| This API lets you create a conversation with LLMs. Using this API enables you to ask questions to the model including | ||||
| information using the history of already asked questions and the respective answers. | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Create a new conversation and use chat history to augment follow up questions | ||||
|  | ||||
| ```java | ||||
| @@ -269,4 +271,12 @@ You will get a response similar to: | ||||
| > Second Answer: Based on the image, it's difficult to definitively determine the breed of the dog. However, the dog | ||||
| > appears to be medium-sized with a short coat and a brown coloration, which might suggest that it is a Golden Retriever | ||||
| > or a similar breed. Without more details like ear shape and tail length, it's not possible to identify the exact breed | ||||
| > confidently. | ||||
| > confidently. | ||||
|  | ||||
|  | ||||
| [//]: # (Generated using: https://emgithub.com/) | ||||
| <iframe style={{ width: '100%', height: '919px', border: 'none' }} allow="clipboard-write" src="https://emgithub.com/iframe.html?target=https%3A%2F%2Fgithub.com%2Follama4j%2Follama4j-examples%2Fblob%2Fmain%2Fsrc%2Fmain%2Fjava%2Fio%2Fgithub%2Follama4j%2Fexamples%2FChatExample.java&style=default&type=code&showBorder=on&showLineNumbers=on&showFileMeta=on&showFullPath=on&showCopy=on" /> | ||||
|  | ||||
| <a href="https://github.com/ollama4j/ollama4j-examples/blob/main/src/main/java/io/github/ollama4j/examples/ChatExample.java" target="_blank"> | ||||
|   View ChatExample.java on GitHub | ||||
| </a> | ||||
| @@ -84,6 +84,7 @@ const config = { | ||||
|                         position: 'left', | ||||
|                         label: 'Docs', | ||||
|                     }, | ||||
|                     {to: 'https://github.com/ollama4j/ollama4j-examples', label: 'Examples', position: 'left'}, | ||||
|                     {to: 'https://ollama4j.github.io/ollama4j/apidocs/', label: 'Javadoc', position: 'left'}, | ||||
|                     {to: 'https://ollama4j.github.io/ollama4j/doxygen/html/', label: 'Doxygen', position: 'left'}, | ||||
|                     {to: '/blog', label: 'Blog', position: 'left'}, | ||||
| @@ -106,6 +107,15 @@ const config = { | ||||
|                             }, | ||||
|                         ], | ||||
|                     }, | ||||
|                     { | ||||
|                         title: 'Usage', | ||||
|                         items: [ | ||||
|                             { | ||||
|                                 label: 'Examples', | ||||
|                                 to: 'https://github.com/ollama4j/ollama4j-examples', | ||||
|                             }, | ||||
|                         ], | ||||
|                     }, | ||||
|                     { | ||||
|                         title: 'Community', | ||||
|                         items: [ | ||||
|   | ||||
							
								
								
									
										492
									
								
								docs/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										492
									
								
								docs/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -4242,9 +4242,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/body-parser": { | ||||
|       "version": "1.20.2", | ||||
|       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", | ||||
|       "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", | ||||
|       "version": "1.20.3", | ||||
|       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", | ||||
|       "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "bytes": "3.1.2", | ||||
| @@ -4255,7 +4255,7 @@ | ||||
|         "http-errors": "2.0.0", | ||||
|         "iconv-lite": "0.4.24", | ||||
|         "on-finished": "2.4.1", | ||||
|         "qs": "6.11.0", | ||||
|         "qs": "6.13.0", | ||||
|         "raw-body": "2.5.2", | ||||
|         "type-is": "~1.6.18", | ||||
|         "unpipe": "1.0.0" | ||||
| @@ -4446,6 +4446,35 @@ | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/call-bind-apply-helpers": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", | ||||
|       "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "es-errors": "^1.3.0", | ||||
|         "function-bind": "^1.1.2" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/call-bound": { | ||||
|       "version": "1.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", | ||||
|       "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bind-apply-helpers": "^1.0.2", | ||||
|         "get-intrinsic": "^1.3.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/callsites": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", | ||||
| @@ -4945,9 +4974,9 @@ | ||||
|       "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" | ||||
|     }, | ||||
|     "node_modules/cookie": { | ||||
|       "version": "0.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", | ||||
|       "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", | ||||
|       "version": "0.7.1", | ||||
|       "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", | ||||
|       "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.6" | ||||
| @@ -5103,9 +5132,10 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/cross-spawn": { | ||||
|       "version": "7.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", | ||||
|       "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", | ||||
|       "version": "7.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", | ||||
|       "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "path-key": "^3.1.0", | ||||
|         "shebang-command": "^2.0.0", | ||||
| @@ -5419,30 +5449,6 @@ | ||||
|         "cytoscape": "^3.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/cytoscape-fcose": { | ||||
|       "version": "2.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", | ||||
|       "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", | ||||
|       "dependencies": { | ||||
|         "cose-base": "^2.2.0" | ||||
|       }, | ||||
|       "peerDependencies": { | ||||
|         "cytoscape": "^3.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/cytoscape-fcose/node_modules/cose-base": { | ||||
|       "version": "2.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", | ||||
|       "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", | ||||
|       "dependencies": { | ||||
|         "layout-base": "^2.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/cytoscape-fcose/node_modules/layout-base": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", | ||||
|       "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==" | ||||
|     }, | ||||
|     "node_modules/d3": { | ||||
|       "version": "7.8.5", | ||||
|       "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", | ||||
| @@ -6048,6 +6054,7 @@ | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", | ||||
|       "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.8" | ||||
|       } | ||||
| @@ -6064,6 +6071,7 @@ | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", | ||||
|       "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.8", | ||||
|         "npm": "1.2.8000 || >= 1.4.16" | ||||
| @@ -6210,9 +6218,10 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/dompurify": { | ||||
|       "version": "3.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", | ||||
|       "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" | ||||
|       "version": "3.1.6", | ||||
|       "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", | ||||
|       "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==", | ||||
|       "license": "(MPL-2.0 OR Apache-2.0)" | ||||
|     }, | ||||
|     "node_modules/domutils": { | ||||
|       "version": "3.1.0", | ||||
| @@ -6258,6 +6267,20 @@ | ||||
|         "node": ">=8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/dunder-proto": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", | ||||
|       "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bind-apply-helpers": "^1.0.1", | ||||
|         "es-errors": "^1.3.0", | ||||
|         "gopd": "^1.2.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/duplexer": { | ||||
|       "version": "0.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", | ||||
| @@ -6271,7 +6294,8 @@ | ||||
|     "node_modules/ee-first": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | ||||
|       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" | ||||
|       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/electron-to-chromium": { | ||||
|       "version": "1.4.827", | ||||
| @@ -6279,9 +6303,10 @@ | ||||
|       "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" | ||||
|     }, | ||||
|     "node_modules/elkjs": { | ||||
|       "version": "0.8.2", | ||||
|       "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", | ||||
|       "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" | ||||
|       "version": "0.9.3", | ||||
|       "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", | ||||
|       "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==", | ||||
|       "license": "EPL-2.0" | ||||
|     }, | ||||
|     "node_modules/emoji-regex": { | ||||
|       "version": "9.2.2", | ||||
| @@ -6311,9 +6336,10 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/encodeurl": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | ||||
|       "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", | ||||
|       "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.8" | ||||
|       } | ||||
| @@ -6351,13 +6377,10 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/es-define-property": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", | ||||
|       "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", | ||||
|       "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "get-intrinsic": "^1.2.4" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       } | ||||
| @@ -6376,6 +6399,18 @@ | ||||
|       "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", | ||||
|       "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" | ||||
|     }, | ||||
|     "node_modules/es-object-atoms": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", | ||||
|       "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "es-errors": "^1.3.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/escalade": { | ||||
|       "version": "3.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", | ||||
| @@ -6567,6 +6602,7 @@ | ||||
|       "version": "1.8.1", | ||||
|       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", | ||||
|       "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.6" | ||||
|       } | ||||
| @@ -6619,37 +6655,37 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/express": { | ||||
|       "version": "4.19.2", | ||||
|       "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", | ||||
|       "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", | ||||
|       "version": "4.21.2", | ||||
|       "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", | ||||
|       "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "accepts": "~1.3.8", | ||||
|         "array-flatten": "1.1.1", | ||||
|         "body-parser": "1.20.2", | ||||
|         "body-parser": "1.20.3", | ||||
|         "content-disposition": "0.5.4", | ||||
|         "content-type": "~1.0.4", | ||||
|         "cookie": "0.6.0", | ||||
|         "cookie": "0.7.1", | ||||
|         "cookie-signature": "1.0.6", | ||||
|         "debug": "2.6.9", | ||||
|         "depd": "2.0.0", | ||||
|         "encodeurl": "~1.0.2", | ||||
|         "encodeurl": "~2.0.0", | ||||
|         "escape-html": "~1.0.3", | ||||
|         "etag": "~1.8.1", | ||||
|         "finalhandler": "1.2.0", | ||||
|         "finalhandler": "1.3.1", | ||||
|         "fresh": "0.5.2", | ||||
|         "http-errors": "2.0.0", | ||||
|         "merge-descriptors": "1.0.1", | ||||
|         "merge-descriptors": "1.0.3", | ||||
|         "methods": "~1.1.2", | ||||
|         "on-finished": "2.4.1", | ||||
|         "parseurl": "~1.3.3", | ||||
|         "path-to-regexp": "0.1.7", | ||||
|         "path-to-regexp": "0.1.12", | ||||
|         "proxy-addr": "~2.0.7", | ||||
|         "qs": "6.11.0", | ||||
|         "qs": "6.13.0", | ||||
|         "range-parser": "~1.2.1", | ||||
|         "safe-buffer": "5.2.1", | ||||
|         "send": "0.18.0", | ||||
|         "serve-static": "1.15.0", | ||||
|         "send": "0.19.0", | ||||
|         "serve-static": "1.16.2", | ||||
|         "setprototypeof": "1.2.0", | ||||
|         "statuses": "2.0.1", | ||||
|         "type-is": "~1.6.18", | ||||
| @@ -6658,6 +6694,10 @@ | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.10.0" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "type": "opencollective", | ||||
|         "url": "https://opencollective.com/express" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/express/node_modules/array-flatten": { | ||||
| @@ -6690,9 +6730,10 @@ | ||||
|       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" | ||||
|     }, | ||||
|     "node_modules/express/node_modules/path-to-regexp": { | ||||
|       "version": "0.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||||
|       "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" | ||||
|       "version": "0.1.12", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", | ||||
|       "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/express/node_modules/range-parser": { | ||||
|       "version": "1.2.1", | ||||
| @@ -6743,14 +6784,6 @@ | ||||
|       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", | ||||
|       "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" | ||||
|     }, | ||||
|     "node_modules/fast-url-parser": { | ||||
|       "version": "1.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", | ||||
|       "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", | ||||
|       "dependencies": { | ||||
|         "punycode": "^1.3.2" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/fastq": { | ||||
|       "version": "1.16.0", | ||||
|       "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", | ||||
| @@ -6878,12 +6911,13 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/finalhandler": { | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", | ||||
|       "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", | ||||
|       "version": "1.3.1", | ||||
|       "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", | ||||
|       "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "debug": "2.6.9", | ||||
|         "encodeurl": "~1.0.2", | ||||
|         "encodeurl": "~2.0.0", | ||||
|         "escape-html": "~1.0.3", | ||||
|         "on-finished": "2.4.1", | ||||
|         "parseurl": "~1.3.3", | ||||
| @@ -6898,6 +6932,7 @@ | ||||
|       "version": "2.6.9", | ||||
|       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||||
|       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "ms": "2.0.0" | ||||
|       } | ||||
| @@ -6905,7 +6940,8 @@ | ||||
|     "node_modules/finalhandler/node_modules/ms": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
|       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" | ||||
|       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/find-cache-dir": { | ||||
|       "version": "4.0.0", | ||||
| @@ -7125,6 +7161,7 @@ | ||||
|       "version": "0.5.2", | ||||
|       "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", | ||||
|       "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.6" | ||||
|       } | ||||
| @@ -7182,16 +7219,21 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/get-intrinsic": { | ||||
|       "version": "1.2.4", | ||||
|       "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", | ||||
|       "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", | ||||
|       "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bind-apply-helpers": "^1.0.2", | ||||
|         "es-define-property": "^1.0.1", | ||||
|         "es-errors": "^1.3.0", | ||||
|         "es-object-atoms": "^1.1.1", | ||||
|         "function-bind": "^1.1.2", | ||||
|         "has-proto": "^1.0.1", | ||||
|         "has-symbols": "^1.0.3", | ||||
|         "hasown": "^2.0.0" | ||||
|         "get-proto": "^1.0.1", | ||||
|         "gopd": "^1.2.0", | ||||
|         "has-symbols": "^1.1.0", | ||||
|         "hasown": "^2.0.2", | ||||
|         "math-intrinsics": "^1.1.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @@ -7205,6 +7247,19 @@ | ||||
|       "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", | ||||
|       "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" | ||||
|     }, | ||||
|     "node_modules/get-proto": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", | ||||
|       "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "dunder-proto": "^1.0.1", | ||||
|         "es-object-atoms": "^1.0.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/get-stream": { | ||||
|       "version": "6.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", | ||||
| @@ -7342,11 +7397,12 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/gopd": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", | ||||
|       "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", | ||||
|       "dependencies": { | ||||
|         "get-intrinsic": "^1.1.3" | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", | ||||
|       "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
| @@ -7465,21 +7521,11 @@ | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/has-proto": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", | ||||
|       "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/has-symbols": { | ||||
|       "version": "1.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", | ||||
|       "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", | ||||
|       "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       }, | ||||
| @@ -7499,9 +7545,10 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/hasown": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", | ||||
|       "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", | ||||
|       "version": "2.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", | ||||
|       "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "function-bind": "^1.1.2" | ||||
|       }, | ||||
| @@ -7912,6 +7959,7 @@ | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", | ||||
|       "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "depd": "2.0.0", | ||||
|         "inherits": "2.0.4", | ||||
| @@ -7942,9 +7990,10 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/http-proxy-middleware": { | ||||
|       "version": "2.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", | ||||
|       "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", | ||||
|       "version": "2.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", | ||||
|       "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@types/http-proxy": "^1.17.8", | ||||
|         "http-proxy": "^1.18.1", | ||||
| @@ -8562,6 +8611,31 @@ | ||||
|         "graceful-fs": "^4.1.6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/katex": { | ||||
|       "version": "0.16.21", | ||||
|       "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz", | ||||
|       "integrity": "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==", | ||||
|       "funding": [ | ||||
|         "https://opencollective.com/katex", | ||||
|         "https://github.com/sponsors/katex" | ||||
|       ], | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "commander": "^8.3.0" | ||||
|       }, | ||||
|       "bin": { | ||||
|         "katex": "cli.js" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/katex/node_modules/commander": { | ||||
|       "version": "8.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", | ||||
|       "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 12" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/keyv": { | ||||
|       "version": "4.5.4", | ||||
|       "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", | ||||
| @@ -8770,6 +8844,15 @@ | ||||
|         "url": "https://github.com/sponsors/wooorm" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/math-intrinsics": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", | ||||
|       "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/mdast-util-directive": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", | ||||
| @@ -9174,9 +9257,13 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/merge-descriptors": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", | ||||
|       "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" | ||||
|       "version": "1.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", | ||||
|       "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", | ||||
|       "license": "MIT", | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/sindresorhus" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/merge-stream": { | ||||
|       "version": "2.0.0", | ||||
| @@ -9192,22 +9279,23 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/mermaid": { | ||||
|       "version": "10.6.1", | ||||
|       "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.6.1.tgz", | ||||
|       "integrity": "sha512-Hky0/RpOw/1il9X8AvzOEChfJtVvmXm+y7JML5C//ePYMy0/9jCEmW1E1g86x9oDfW9+iVEdTV/i+M6KWRNs4A==", | ||||
|       "version": "10.9.3", | ||||
|       "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.3.tgz", | ||||
|       "integrity": "sha512-V80X1isSEvAewIL3xhmz/rVmc27CVljcsbWxkxlWJWY/1kQa4XOABqpDl2qQLGKzpKm6WbTfUEKImBlUfFYArw==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@braintree/sanitize-url": "^6.0.1", | ||||
|         "@types/d3-scale": "^4.0.3", | ||||
|         "@types/d3-scale-chromatic": "^3.0.0", | ||||
|         "cytoscape": "^3.23.0", | ||||
|         "cytoscape": "^3.28.1", | ||||
|         "cytoscape-cose-bilkent": "^4.1.0", | ||||
|         "cytoscape-fcose": "^2.1.0", | ||||
|         "d3": "^7.4.0", | ||||
|         "d3-sankey": "^0.12.3", | ||||
|         "dagre-d3-es": "7.0.10", | ||||
|         "dayjs": "^1.11.7", | ||||
|         "dompurify": "^3.0.5", | ||||
|         "elkjs": "^0.8.2", | ||||
|         "dompurify": "^3.0.5 <3.1.7", | ||||
|         "elkjs": "^0.9.0", | ||||
|         "katex": "^0.16.9", | ||||
|         "khroma": "^2.0.0", | ||||
|         "lodash-es": "^4.17.21", | ||||
|         "mdast-util-from-markdown": "^1.3.0", | ||||
| @@ -11354,6 +11442,7 @@ | ||||
|       "version": "1.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", | ||||
|       "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", | ||||
|       "license": "MIT", | ||||
|       "bin": { | ||||
|         "mime": "cli.js" | ||||
|       }, | ||||
| @@ -11475,15 +11564,16 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/nanoid": { | ||||
|       "version": "3.3.7", | ||||
|       "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", | ||||
|       "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", | ||||
|       "version": "3.3.9", | ||||
|       "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.9.tgz", | ||||
|       "integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==", | ||||
|       "funding": [ | ||||
|         { | ||||
|           "type": "github", | ||||
|           "url": "https://github.com/sponsors/ai" | ||||
|         } | ||||
|       ], | ||||
|       "license": "MIT", | ||||
|       "bin": { | ||||
|         "nanoid": "bin/nanoid.cjs" | ||||
|       }, | ||||
| @@ -11597,9 +11687,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/object-inspect": { | ||||
|       "version": "1.13.2", | ||||
|       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", | ||||
|       "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", | ||||
|       "version": "1.13.4", | ||||
|       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", | ||||
|       "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @@ -11642,6 +11732,7 @@ | ||||
|       "version": "2.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", | ||||
|       "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "ee-first": "1.1.1" | ||||
|       }, | ||||
| @@ -11931,9 +12022,10 @@ | ||||
|       "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" | ||||
|     }, | ||||
|     "node_modules/path-to-regexp": { | ||||
|       "version": "1.8.0", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", | ||||
|       "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", | ||||
|       "version": "1.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", | ||||
|       "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "isarray": "0.0.1" | ||||
|       } | ||||
| @@ -12719,11 +12811,6 @@ | ||||
|         "node": ">= 0.10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/punycode": { | ||||
|       "version": "1.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", | ||||
|       "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" | ||||
|     }, | ||||
|     "node_modules/pupa": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", | ||||
| @@ -12739,12 +12826,12 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/qs": { | ||||
|       "version": "6.11.0", | ||||
|       "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", | ||||
|       "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", | ||||
|       "version": "6.13.0", | ||||
|       "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", | ||||
|       "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", | ||||
|       "license": "BSD-3-Clause", | ||||
|       "dependencies": { | ||||
|         "side-channel": "^1.0.4" | ||||
|         "side-channel": "^1.0.6" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=0.6" | ||||
| @@ -13786,9 +13873,10 @@ | ||||
|       "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" | ||||
|     }, | ||||
|     "node_modules/send": { | ||||
|       "version": "0.18.0", | ||||
|       "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", | ||||
|       "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", | ||||
|       "version": "0.19.0", | ||||
|       "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", | ||||
|       "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "debug": "2.6.9", | ||||
|         "depd": "2.0.0", | ||||
| @@ -13812,6 +13900,7 @@ | ||||
|       "version": "2.6.9", | ||||
|       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||||
|       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "ms": "2.0.0" | ||||
|       } | ||||
| @@ -13819,48 +13908,62 @@ | ||||
|     "node_modules/send/node_modules/debug/node_modules/ms": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
|       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" | ||||
|       "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/send/node_modules/encodeurl": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | ||||
|       "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/send/node_modules/ms": { | ||||
|       "version": "2.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", | ||||
|       "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" | ||||
|       "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/send/node_modules/range-parser": { | ||||
|       "version": "1.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", | ||||
|       "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.6" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/serialize-javascript": { | ||||
|       "version": "6.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", | ||||
|       "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", | ||||
|       "version": "6.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", | ||||
|       "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", | ||||
|       "license": "BSD-3-Clause", | ||||
|       "dependencies": { | ||||
|         "randombytes": "^2.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/serve-handler": { | ||||
|       "version": "6.1.5", | ||||
|       "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", | ||||
|       "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", | ||||
|       "version": "6.1.6", | ||||
|       "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", | ||||
|       "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "bytes": "3.0.0", | ||||
|         "content-disposition": "0.5.2", | ||||
|         "fast-url-parser": "1.1.3", | ||||
|         "mime-types": "2.1.18", | ||||
|         "minimatch": "3.1.2", | ||||
|         "path-is-inside": "1.0.2", | ||||
|         "path-to-regexp": "2.2.1", | ||||
|         "path-to-regexp": "3.3.0", | ||||
|         "range-parser": "1.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/serve-handler/node_modules/path-to-regexp": { | ||||
|       "version": "2.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", | ||||
|       "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" | ||||
|       "version": "3.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", | ||||
|       "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/serve-index": { | ||||
|       "version": "1.9.1", | ||||
| @@ -13933,14 +14036,15 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/serve-static": { | ||||
|       "version": "1.15.0", | ||||
|       "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", | ||||
|       "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", | ||||
|       "version": "1.16.2", | ||||
|       "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", | ||||
|       "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "encodeurl": "~1.0.2", | ||||
|         "encodeurl": "~2.0.0", | ||||
|         "escape-html": "~1.0.3", | ||||
|         "parseurl": "~1.3.3", | ||||
|         "send": "0.18.0" | ||||
|         "send": "0.19.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.8.0" | ||||
| @@ -13966,7 +14070,8 @@ | ||||
|     "node_modules/setprototypeof": { | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", | ||||
|       "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" | ||||
|       "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", | ||||
|       "license": "ISC" | ||||
|     }, | ||||
|     "node_modules/shallow-clone": { | ||||
|       "version": "3.0.1", | ||||
| @@ -14028,15 +14133,69 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/side-channel": { | ||||
|       "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==", | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", | ||||
|       "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bind": "^1.0.7", | ||||
|         "es-errors": "^1.3.0", | ||||
|         "get-intrinsic": "^1.2.4", | ||||
|         "object-inspect": "^1.13.1" | ||||
|         "object-inspect": "^1.13.3", | ||||
|         "side-channel-list": "^1.0.0", | ||||
|         "side-channel-map": "^1.0.1", | ||||
|         "side-channel-weakmap": "^1.0.2" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/side-channel-list": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", | ||||
|       "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "es-errors": "^1.3.0", | ||||
|         "object-inspect": "^1.13.3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/side-channel-map": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", | ||||
|       "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bound": "^1.0.2", | ||||
|         "es-errors": "^1.3.0", | ||||
|         "get-intrinsic": "^1.2.5", | ||||
|         "object-inspect": "^1.13.3" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
|       }, | ||||
|       "funding": { | ||||
|         "url": "https://github.com/sponsors/ljharb" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/side-channel-weakmap": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", | ||||
|       "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "call-bound": "^1.0.2", | ||||
|         "es-errors": "^1.3.0", | ||||
|         "get-intrinsic": "^1.2.5", | ||||
|         "object-inspect": "^1.13.3", | ||||
|         "side-channel-map": "^1.0.1" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">= 0.4" | ||||
| @@ -14227,6 +14386,7 @@ | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", | ||||
|       "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.8" | ||||
|       } | ||||
| @@ -14616,6 +14776,7 @@ | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", | ||||
|       "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">=0.6" | ||||
|       } | ||||
| @@ -14906,6 +15067,7 @@ | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", | ||||
|       "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", | ||||
|       "license": "MIT", | ||||
|       "engines": { | ||||
|         "node": ">= 0.8" | ||||
|       } | ||||
|   | ||||
							
								
								
									
										92
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -13,8 +13,8 @@ | ||||
|     <packaging>jar</packaging> | ||||
|  | ||||
|     <properties> | ||||
|         <maven.compiler.source>11</maven.compiler.source> | ||||
|         <maven.compiler.target>11</maven.compiler.target> | ||||
|         <maven.compiler.release>11</maven.compiler.release> | ||||
|         <project.build.outputTimestamp>${git.commit.time}</project.build.outputTimestamp><!-- populated via git-commit-id-plugin --> | ||||
|         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
|         <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version> | ||||
|         <maven-failsafe-plugin.version>3.0.0-M5</maven-failsafe-plugin.version> | ||||
| @@ -49,7 +49,7 @@ | ||||
|             <plugin> | ||||
|                 <groupId>org.apache.maven.plugins</groupId> | ||||
|                 <artifactId>maven-source-plugin</artifactId> | ||||
|                 <version>3.3.0</version> | ||||
|                 <version>3.3.1</version> | ||||
|                 <executions> | ||||
|                     <execution> | ||||
|                         <id>attach-sources</id> | ||||
| @@ -62,7 +62,7 @@ | ||||
|             <plugin> | ||||
|                 <groupId>org.apache.maven.plugins</groupId> | ||||
|                 <artifactId>maven-javadoc-plugin</artifactId> | ||||
|                 <version>3.5.0</version> | ||||
|                 <version>3.11.2</version> | ||||
|                 <configuration> | ||||
|                     <!-- to disable the "missing" warnings. Remove the doclint to enable warnings--> | ||||
|                     <doclint>all,-missing</doclint> | ||||
| @@ -70,9 +70,13 @@ | ||||
|                 <executions> | ||||
|                     <execution> | ||||
|                         <id>attach-javadocs</id> | ||||
|                         <phase>package</phase> | ||||
|                         <goals> | ||||
|                             <goal>jar</goal> | ||||
|                         </goals> | ||||
|                         <configuration> | ||||
|                             <outputDirectory>${project.build.directory}</outputDirectory> | ||||
|                         </configuration> | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|             </plugin> | ||||
| @@ -114,7 +118,6 @@ | ||||
|                 </executions> | ||||
|             </plugin> | ||||
|  | ||||
|  | ||||
|             <plugin> | ||||
|                 <groupId>org.apache.maven.plugins</groupId> | ||||
|                 <artifactId>maven-gpg-plugin</artifactId> | ||||
| @@ -130,7 +133,36 @@ | ||||
|                 </executions> | ||||
|             </plugin> | ||||
|  | ||||
|             <plugin> | ||||
|                 <groupId>io.github.git-commit-id</groupId> | ||||
|                 <artifactId>git-commit-id-maven-plugin</artifactId> | ||||
|                 <version>9.0.1</version> | ||||
|                 <executions> | ||||
|                     <execution> | ||||
|                         <goals> | ||||
|                             <goal>revision</goal> | ||||
|                         </goals> | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|                 <configuration> | ||||
|                     <dateFormat>yyyy-MM-dd'T'HH:mm:ss'Z'</dateFormat> | ||||
| 		    <dateFormatTimeZone>Etc/UTC</dateFormatTimeZone> | ||||
|                 </configuration> | ||||
|             </plugin> | ||||
|         </plugins> | ||||
|  | ||||
|         <pluginManagement> | ||||
|             <plugins> | ||||
|                 <plugin> | ||||
|                     <artifactId>maven-compiler-plugin</artifactId> | ||||
|                     <version>3.14.0</version> | ||||
|                 </plugin> | ||||
|                 <plugin> | ||||
|                     <artifactId>maven-jar-plugin</artifactId> | ||||
|                     <version>3.4.2</version> | ||||
|                 </plugin> | ||||
|             </plugins> | ||||
|         </pluginManagement> | ||||
|     </build> | ||||
|  | ||||
|     <dependencies> | ||||
| @@ -184,6 +216,13 @@ | ||||
|             <version>20240205</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>org.testcontainers</groupId> | ||||
|             <artifactId>ollama</artifactId> | ||||
|             <version>1.20.2</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|     <distributionManagement> | ||||
| @@ -225,6 +264,7 @@ | ||||
|                 <test.env>unit</test.env> | ||||
|                 <skipUnitTests>false</skipUnitTests> | ||||
|                 <skipIntegrationTests>true</skipIntegrationTests> | ||||
|                 <skipGpgPluginDuringTests>true</skipGpgPluginDuringTests> | ||||
|             </properties> | ||||
|             <activation> | ||||
|                 <activeByDefault>false</activeByDefault> | ||||
| @@ -250,6 +290,23 @@ | ||||
|                             </execution> | ||||
|                         </executions> | ||||
|                     </plugin> | ||||
|                     <plugin> | ||||
|                         <groupId>org.apache.maven.plugins</groupId> | ||||
|                         <artifactId>maven-gpg-plugin</artifactId> | ||||
|                         <version>1.5</version> | ||||
|                         <executions> | ||||
|                             <execution> | ||||
|                                 <id>sign-artifacts</id> | ||||
|                                 <phase>verify</phase> | ||||
|                                 <goals> | ||||
|                                     <goal>sign</goal> | ||||
|                                 </goals> | ||||
|                                 <configuration> | ||||
|                                     <skip>${skipGpgPluginDuringTests}</skip> | ||||
|                                 </configuration> | ||||
|                             </execution> | ||||
|                         </executions> | ||||
|                     </plugin> | ||||
|                 </plugins> | ||||
|             </build> | ||||
|         </profile> | ||||
| @@ -259,7 +316,29 @@ | ||||
|                 <test.env>integration</test.env> | ||||
|                 <skipUnitTests>true</skipUnitTests> | ||||
|                 <skipIntegrationTests>false</skipIntegrationTests> | ||||
|                 <skipGpgPluginDuringTests>true</skipGpgPluginDuringTests> | ||||
|             </properties> | ||||
|             <build> | ||||
|                 <plugins> | ||||
|                     <plugin> | ||||
|                         <groupId>org.apache.maven.plugins</groupId> | ||||
|                         <artifactId>maven-gpg-plugin</artifactId> | ||||
|                         <version>1.5</version> | ||||
|                         <executions> | ||||
|                             <execution> | ||||
|                                 <id>sign-artifacts</id> | ||||
|                                 <phase>verify</phase> | ||||
|                                 <goals> | ||||
|                                     <goal>sign</goal> | ||||
|                                 </goals> | ||||
|                                 <configuration> | ||||
|                                     <skip>${skipGpgPluginDuringTests}</skip> | ||||
|                                 </configuration> | ||||
|                             </execution> | ||||
|                         </executions> | ||||
|                     </plugin> | ||||
|                 </plugins> | ||||
|             </build> | ||||
|         </profile> | ||||
|         <profile> | ||||
|             <id>ci-cd</id> | ||||
| @@ -303,7 +382,6 @@ | ||||
|                             <autoReleaseAfterClose>true</autoReleaseAfterClose> | ||||
|                         </configuration> | ||||
|                     </plugin> | ||||
|  | ||||
|                     <plugin> | ||||
|                         <groupId>org.jacoco</groupId> | ||||
|                         <artifactId>jacoco-maven-plugin</artifactId> | ||||
| @@ -328,4 +406,4 @@ | ||||
|         </profile> | ||||
|     </profiles> | ||||
|  | ||||
| </project> | ||||
| </project> | ||||
|   | ||||
| @@ -1,14 +1,17 @@ | ||||
| package io.github.ollama4j; | ||||
|  | ||||
| import com.fasterxml.jackson.core.JsonParseException; | ||||
| import com.fasterxml.jackson.databind.JsonNode; | ||||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||||
| import io.github.ollama4j.exceptions.OllamaBaseException; | ||||
| import io.github.ollama4j.exceptions.RoleNotFoundException; | ||||
| import io.github.ollama4j.exceptions.ToolInvocationException; | ||||
| import io.github.ollama4j.exceptions.ToolNotFoundException; | ||||
| import io.github.ollama4j.models.chat.*; | ||||
| import io.github.ollama4j.models.embeddings.OllamaEmbedRequestModel; | ||||
| import io.github.ollama4j.models.embeddings.OllamaEmbedResponseModel; | ||||
| import io.github.ollama4j.models.embeddings.OllamaEmbeddingResponseModel; | ||||
| import io.github.ollama4j.models.embeddings.OllamaEmbeddingsRequestModel; | ||||
| import io.github.ollama4j.models.embeddings.OllamaEmbedResponseModel; | ||||
| import io.github.ollama4j.models.generate.OllamaGenerateRequest; | ||||
| import io.github.ollama4j.models.generate.OllamaStreamHandler; | ||||
| import io.github.ollama4j.models.generate.OllamaTokenHandler; | ||||
| @@ -22,6 +25,12 @@ import io.github.ollama4j.tools.annotations.ToolSpec; | ||||
| import io.github.ollama4j.utils.Options; | ||||
| import io.github.ollama4j.utils.Utils; | ||||
| import lombok.Setter; | ||||
| import org.jsoup.Jsoup; | ||||
| import org.jsoup.nodes.Document; | ||||
| import org.jsoup.nodes.Element; | ||||
| import org.jsoup.select.Elements; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import java.io.*; | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| @@ -39,13 +48,6 @@ import java.time.Duration; | ||||
| import java.util.*; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.jsoup.Jsoup; | ||||
| import org.jsoup.nodes.Document; | ||||
| import org.jsoup.nodes.Element; | ||||
| import org.jsoup.select.Elements; | ||||
|  | ||||
| /** | ||||
|  * The base Ollama API class. | ||||
|  */ | ||||
| @@ -92,6 +94,9 @@ public class OllamaAPI { | ||||
|         } else { | ||||
|             this.host = host; | ||||
|         } | ||||
|         if (this.verbose) { | ||||
|             logger.info("Ollama API initialized with host: " + this.host); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -318,26 +323,58 @@ public class OllamaAPI { | ||||
|     public void pullModel(String modelName) throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { | ||||
|         String url = this.host + "/api/pull"; | ||||
|         String jsonData = new ModelRequest(modelName).toString(); | ||||
|         HttpRequest request = getRequestBuilderDefault(new URI(url)).POST(HttpRequest.BodyPublishers.ofString(jsonData)).header("Accept", "application/json").header("Content-type", "application/json").build(); | ||||
|         HttpRequest request = getRequestBuilderDefault(new URI(url)) | ||||
|                 .POST(HttpRequest.BodyPublishers.ofString(jsonData)) | ||||
|                 .header("Accept", "application/json") | ||||
|                 .header("Content-type", "application/json") | ||||
|                 .build(); | ||||
|         HttpClient client = HttpClient.newHttpClient(); | ||||
|         HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream()); | ||||
|         int statusCode = response.statusCode(); | ||||
|         InputStream responseBodyStream = response.body(); | ||||
|         String responseString = ""; | ||||
|         boolean success = false; // Flag to check the pull success. | ||||
|         try (BufferedReader reader = new BufferedReader(new InputStreamReader(responseBodyStream, StandardCharsets.UTF_8))) { | ||||
|             String line; | ||||
|             while ((line = reader.readLine()) != null) { | ||||
|                 ModelPullResponse modelPullResponse = Utils.getObjectMapper().readValue(line, ModelPullResponse.class); | ||||
|                 if (verbose) { | ||||
|                     logger.info(modelPullResponse.getStatus()); | ||||
|                 if (modelPullResponse != null && modelPullResponse.getStatus() != null) { | ||||
|                     if (verbose) { | ||||
|                         logger.info(modelName + ": " + modelPullResponse.getStatus()); | ||||
|                     } | ||||
|                     // Check if status is "success" and set success flag to true. | ||||
|                     if ("success".equalsIgnoreCase(modelPullResponse.getStatus())) { | ||||
|                         success = true; | ||||
|                     } | ||||
|                 } else { | ||||
|                     logger.error("Received null or invalid status for model pull."); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (!success) { | ||||
|             logger.error("Model pull failed or returned invalid status."); | ||||
|             throw new OllamaBaseException("Model pull failed or returned invalid status."); | ||||
|         } | ||||
|         if (statusCode != 200) { | ||||
|             throw new OllamaBaseException(statusCode + " - " + responseString); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public String getVersion() throws URISyntaxException, IOException, InterruptedException, OllamaBaseException { | ||||
|         String url = this.host + "/api/version"; | ||||
|         HttpClient httpClient = HttpClient.newHttpClient(); | ||||
|         HttpRequest httpRequest = getRequestBuilderDefault(new URI(url)).header("Accept", "application/json").header("Content-type", "application/json").GET().build(); | ||||
|         HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); | ||||
|         int statusCode = response.statusCode(); | ||||
|         String responseString = response.body(); | ||||
|         if (statusCode == 200) { | ||||
|             return Utils.getObjectMapper().readValue(responseString, OllamaVersion.class).getVersion(); | ||||
|         } else { | ||||
|             throw new OllamaBaseException(statusCode + " - " + responseString); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Pulls a model using the specified Ollama library model tag. | ||||
|      * The model is identified by a name and a tag, which are combined into a single identifier | ||||
| @@ -658,7 +695,22 @@ public class OllamaAPI { | ||||
|             toolsResponse = toolsResponse.replace("[TOOL_CALLS]", ""); | ||||
|         } | ||||
|  | ||||
|         List<ToolFunctionCallSpec> toolFunctionCallSpecs = Utils.getObjectMapper().readValue(toolsResponse, Utils.getObjectMapper().getTypeFactory().constructCollectionType(List.class, ToolFunctionCallSpec.class)); | ||||
|         List<ToolFunctionCallSpec> toolFunctionCallSpecs = new ArrayList<>(); | ||||
|         ObjectMapper objectMapper = Utils.getObjectMapper(); | ||||
|  | ||||
|         if (!toolsResponse.isEmpty()) { | ||||
|             try { | ||||
|                 // Try to parse the string to see if it's a valid JSON | ||||
|                 JsonNode jsonNode = objectMapper.readTree(toolsResponse); | ||||
|             } catch (JsonParseException e) { | ||||
|                 logger.warn("Response from model does not contain any tool calls. Returning the response as is."); | ||||
|                 return toolResult; | ||||
|             } | ||||
|             toolFunctionCallSpecs = objectMapper.readValue( | ||||
|                     toolsResponse, | ||||
|                     objectMapper.getTypeFactory().constructCollectionType(List.class, ToolFunctionCallSpec.class) | ||||
|             ); | ||||
|         } | ||||
|         for (ToolFunctionCallSpec toolFunctionCallSpec : toolFunctionCallSpecs) { | ||||
|             toolResults.put(toolFunctionCallSpec, invokeTool(toolFunctionCallSpec)); | ||||
|         } | ||||
| @@ -881,6 +933,9 @@ public class OllamaAPI { | ||||
|      */ | ||||
|     public void registerTool(Tools.ToolSpecification toolSpecification) { | ||||
|         toolRegistry.addTool(toolSpecification.getFunctionName(), toolSpecification); | ||||
|         if (this.verbose) { | ||||
|             logger.debug("Registered tool: {}", toolSpecification.getFunctionName()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -1093,7 +1148,7 @@ public class OllamaAPI { | ||||
|                 logger.debug("Invoking function {} with arguments {}", methodName, arguments); | ||||
|             } | ||||
|             if (function == null) { | ||||
|                 throw new ToolNotFoundException("No such tool: " + methodName); | ||||
|                 throw new ToolNotFoundException("No such tool: " + methodName + ". Please register the tool before invoking it."); | ||||
|             } | ||||
|             return function.apply(arguments); | ||||
|         } catch (Exception e) { | ||||
|   | ||||
| @@ -28,9 +28,9 @@ public class OllamaChatMessageRole { | ||||
|     } | ||||
|  | ||||
|     public static OllamaChatMessageRole newCustomRole(String roleName) { | ||||
|         OllamaChatMessageRole customRole = new OllamaChatMessageRole(roleName); | ||||
|         roles.add(customRole); | ||||
|         return customRole; | ||||
| //        OllamaChatMessageRole customRole = new OllamaChatMessageRole(roleName); | ||||
| //        roles.add(customRole); | ||||
|         return new OllamaChatMessageRole(roleName); | ||||
|     } | ||||
|  | ||||
|     public static List<OllamaChatMessageRole> getRoles() { | ||||
|   | ||||
| @@ -14,10 +14,9 @@ import static io.github.ollama4j.utils.Utils.getObjectMapper; | ||||
| @Getter | ||||
| public class OllamaChatResult { | ||||
|  | ||||
|     private final List<OllamaChatMessage> chatHistory; | ||||
|  | ||||
|     private List<OllamaChatMessage> chatHistory; | ||||
|  | ||||
|     private OllamaChatResponseModel responseModel; | ||||
|     private final OllamaChatResponseModel responseModel; | ||||
|  | ||||
|     public OllamaChatResult(OllamaChatResponseModel responseModel, List<OllamaChatMessage> chatHistory) { | ||||
|         this.chatHistory = chatHistory; | ||||
|   | ||||
| @@ -2,12 +2,14 @@ package io.github.ollama4j.models.response; | ||||
|  | ||||
| import java.time.OffsetDateTime; | ||||
|  | ||||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||||
| import io.github.ollama4j.utils.Utils; | ||||
| import lombok.Data; | ||||
|  | ||||
| @Data | ||||
| @JsonIgnoreProperties(ignoreUnknown = true) | ||||
| public class Model { | ||||
|  | ||||
|   private String name; | ||||
|   | ||||
| @@ -0,0 +1,10 @@ | ||||
| package io.github.ollama4j.models.response; | ||||
|  | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @Data | ||||
| public class OllamaVersion { | ||||
|     private String version; | ||||
| } | ||||
| @@ -1,5 +1,6 @@ | ||||
| package io.github.ollama4j.tools; | ||||
|  | ||||
| import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
| @@ -9,8 +10,9 @@ import java.util.Map; | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| @JsonIgnoreProperties(ignoreUnknown = true) | ||||
| public class OllamaToolCallsFunction | ||||
| { | ||||
|     private String name; | ||||
|     private Map<String,Object> arguments; | ||||
| } | ||||
| } | ||||
| @@ -18,6 +18,9 @@ public class OllamaToolsResult { | ||||
|  | ||||
|     public List<ToolResult> getToolResults() { | ||||
|         List<ToolResult> results = new ArrayList<>(); | ||||
|         if (this.toolResults == null) { | ||||
|             return results; | ||||
|         } | ||||
|         for (Map.Entry<ToolFunctionCallSpec, Object> r : this.toolResults.entrySet()) { | ||||
|             results.add(new ToolResult(r.getKey().getName(), r.getKey().getArguments(), r.getValue())); | ||||
|         } | ||||
|   | ||||
| @@ -0,0 +1,239 @@ | ||||
| package io.github.ollama4j.integrationtests; | ||||
|  | ||||
| import io.github.ollama4j.OllamaAPI; | ||||
| import io.github.ollama4j.exceptions.OllamaBaseException; | ||||
| import io.github.ollama4j.models.chat.OllamaChatMessageRole; | ||||
| import io.github.ollama4j.models.chat.OllamaChatRequest; | ||||
| import io.github.ollama4j.models.chat.OllamaChatRequestBuilder; | ||||
| import io.github.ollama4j.models.chat.OllamaChatResult; | ||||
| import io.github.ollama4j.models.embeddings.OllamaEmbedResponseModel; | ||||
| import io.github.ollama4j.models.response.LibraryModel; | ||||
| import io.github.ollama4j.models.response.Model; | ||||
| import io.github.ollama4j.models.response.ModelDetail; | ||||
| import io.github.ollama4j.models.response.OllamaResult; | ||||
| import io.github.ollama4j.utils.OptionsBuilder; | ||||
| import org.junit.jupiter.api.BeforeAll; | ||||
| import org.junit.jupiter.api.Order; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.testcontainers.ollama.OllamaContainer; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.net.ConnectException; | ||||
| import java.net.URISyntaxException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
|  | ||||
| import static org.junit.jupiter.api.Assertions.*; | ||||
|  | ||||
| @SuppressWarnings("HttpUrlsUsage") | ||||
| public class OllamaAPIIntegrationTest { | ||||
|  | ||||
|     private static OllamaContainer ollama; | ||||
|     private static OllamaAPI api; | ||||
|  | ||||
|     @BeforeAll | ||||
|     public static void setUp() { | ||||
|         String version = "0.5.13"; | ||||
|         int internalPort = 11434; | ||||
|         int mappedPort = 11435; | ||||
|         ollama = new OllamaContainer("ollama/ollama:" + version); | ||||
|         ollama.addExposedPort(internalPort); | ||||
|         List<String> portBindings = new ArrayList<>(); | ||||
|         portBindings.add(mappedPort + ":" + internalPort); | ||||
|         ollama.setPortBindings(portBindings); | ||||
|         ollama.start(); | ||||
|         api = new OllamaAPI("http://" + ollama.getHost() + ":" + ollama.getMappedPort(internalPort)); | ||||
|         api.setRequestTimeoutSeconds(60); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(1) | ||||
|     void testWrongEndpoint() { | ||||
|         OllamaAPI ollamaAPI = new OllamaAPI("http://wrong-host:11434"); | ||||
|         assertThrows(ConnectException.class, ollamaAPI::listModels); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(1) | ||||
|     public void testVersionAPI() throws URISyntaxException, IOException, OllamaBaseException, InterruptedException { | ||||
|         String expectedVersion = ollama.getDockerImageName().split(":")[1]; | ||||
|         String actualVersion = api.getVersion(); | ||||
|         assertEquals(expectedVersion, actualVersion, "Version should match the Docker image version"); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(2) | ||||
|     public void testListModelsAPI() throws URISyntaxException, IOException, OllamaBaseException, InterruptedException { | ||||
|         // Fetch the list of models | ||||
|         List<Model> models = api.listModels(); | ||||
|         // Assert that the models list is not null | ||||
|         assertNotNull(models, "Models should not be null"); | ||||
|         // Assert that models list is either empty or contains more than 0 models | ||||
|         assertTrue(models.size() >= 0, "Models list should be empty or contain elements"); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(2) | ||||
|     void testListModelsFromLibrary() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { | ||||
|         List<LibraryModel> models = api.listModelsFromLibrary(); | ||||
|         assertNotNull(models); | ||||
|         assertFalse(models.isEmpty()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(3) | ||||
|     public void testPullModelAPI() throws URISyntaxException, IOException, OllamaBaseException, InterruptedException { | ||||
|         api.pullModel("all-minilm"); | ||||
|         List<Model> models = api.listModels(); | ||||
|         assertNotNull(models, "Models should not be null"); | ||||
|         assertFalse(models.isEmpty(), "Models list should contain elements"); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(4) | ||||
|     void testListModelDetails() throws IOException, OllamaBaseException, URISyntaxException, InterruptedException { | ||||
|         String embeddingModelMinilm = "all-minilm"; | ||||
|         api.pullModel(embeddingModelMinilm); | ||||
|         ModelDetail modelDetails = api.getModelDetails("all-minilm"); | ||||
|         assertNotNull(modelDetails); | ||||
|         assertTrue(modelDetails.getModelFile().contains(embeddingModelMinilm)); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(5) | ||||
|     public void testGenerateEmbeddings() throws Exception { | ||||
|         String embeddingModelMinilm = "all-minilm"; | ||||
|         api.pullModel(embeddingModelMinilm); | ||||
|         OllamaEmbedResponseModel embeddings = api.embed(embeddingModelMinilm, Arrays.asList("Why is the sky blue?", "Why is the grass green?")); | ||||
|         assertNotNull(embeddings, "Embeddings should not be null"); | ||||
|         assertFalse(embeddings.getEmbeddings().isEmpty(), "Embeddings should not be empty"); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(6) | ||||
|     void testAskModelWithDefaultOptions() throws OllamaBaseException, IOException, InterruptedException, URISyntaxException { | ||||
|         String chatModel = "qwen2.5:0.5b"; | ||||
|         api.pullModel(chatModel); | ||||
|         OllamaResult result = | ||||
|                 api.generate( | ||||
|                         chatModel, | ||||
|                         "What is the capital of France? And what's France's connection with Mona Lisa?", | ||||
|                         false, | ||||
|                         new OptionsBuilder().build()); | ||||
|         assertNotNull(result); | ||||
|         assertNotNull(result.getResponse()); | ||||
|         assertFalse(result.getResponse().isEmpty()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(7) | ||||
|     void testAskModelWithDefaultOptionsStreamed() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { | ||||
|         String chatModel = "qwen2.5:0.5b"; | ||||
|         api.pullModel(chatModel); | ||||
|         StringBuffer sb = new StringBuffer(); | ||||
|         OllamaResult result = api.generate(chatModel, | ||||
|                 "What is the capital of France? And what's France's connection with Mona Lisa?", | ||||
|                 false, | ||||
|                 new OptionsBuilder().build(), (s) -> { | ||||
|                     System.out.println(s); | ||||
|                     String substring = s.substring(sb.toString().length(), s.length()); | ||||
|                     System.out.println(substring); | ||||
|                     sb.append(substring); | ||||
|                 }); | ||||
|  | ||||
|         assertNotNull(result); | ||||
|         assertNotNull(result.getResponse()); | ||||
|         assertFalse(result.getResponse().isEmpty()); | ||||
|         assertEquals(sb.toString().trim(), result.getResponse().trim()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(8) | ||||
|     void testAskModelWithOptions() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { | ||||
|         String chatModel = "qwen2.5:0.5b-instruct"; | ||||
|         api.pullModel(chatModel); | ||||
|  | ||||
|         OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(chatModel); | ||||
|         OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM, "You are a helpful assistant who can generate random person's first and last names in the format [First name, Last name].") | ||||
|                 .build(); | ||||
|         requestModel = builder.withMessages(requestModel.getMessages()) | ||||
|                 .withMessage(OllamaChatMessageRole.USER, "Give me a cool name") | ||||
|                 .withOptions(new OptionsBuilder().setTemperature(0.5f).build()).build(); | ||||
|         OllamaChatResult chatResult = api.chat(requestModel); | ||||
|  | ||||
|         assertNotNull(chatResult); | ||||
|         assertNotNull(chatResult.getResponseModel()); | ||||
|         assertFalse(chatResult.getResponseModel().getMessage().getContent().isEmpty()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(9) | ||||
|     void testChatWithSystemPrompt() throws OllamaBaseException, IOException, URISyntaxException, InterruptedException { | ||||
|         String chatModel = "llama3.2:1b"; | ||||
|         api.pullModel(chatModel); | ||||
|         OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(chatModel); | ||||
|         OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.SYSTEM, | ||||
|                         "You are a silent bot that only says 'Shush'. Do not say anything else under any circumstances!") | ||||
|                 .withMessage(OllamaChatMessageRole.USER, | ||||
|                         "What's something that's brown and sticky?") | ||||
|                 .withOptions(new OptionsBuilder().setTemperature(0.8f).build()) | ||||
|                 .build(); | ||||
|  | ||||
|         OllamaChatResult chatResult = api.chat(requestModel); | ||||
|         assertNotNull(chatResult); | ||||
|         assertNotNull(chatResult.getResponseModel()); | ||||
|         assertNotNull(chatResult.getResponseModel().getMessage()); | ||||
|         assertFalse(chatResult.getResponseModel().getMessage().getContent().isBlank()); | ||||
|         assertTrue(chatResult.getResponseModel().getMessage().getContent().contains("Shush")); | ||||
|         assertEquals(3, chatResult.getChatHistory().size()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     @Order(10) | ||||
|     public void testChat() throws Exception { | ||||
|         String chatModel = "qwen2.5:0.5b"; | ||||
|         api.pullModel(chatModel); | ||||
|         OllamaChatRequestBuilder builder = OllamaChatRequestBuilder.getInstance(chatModel); | ||||
|  | ||||
|         // Create the initial user question | ||||
|         OllamaChatRequest requestModel = builder.withMessage(OllamaChatMessageRole.USER, "What is the capital of France?") | ||||
|                 .build(); | ||||
|  | ||||
|         // Start conversation with model | ||||
|         OllamaChatResult chatResult = api.chat(requestModel); | ||||
|  | ||||
|         assertTrue( | ||||
|                 chatResult.getChatHistory().stream() | ||||
|                         .anyMatch(chat -> chat.getContent().contains("Paris")), | ||||
|                 "Expected chat history to contain 'Paris'" | ||||
|         ); | ||||
|  | ||||
|         // Create the next user question: second largest city | ||||
|         requestModel = builder.withMessages(chatResult.getChatHistory()) | ||||
|                 .withMessage(OllamaChatMessageRole.USER, "And what is its official language?") | ||||
|                 .build(); | ||||
|  | ||||
|         // Continue conversation with model | ||||
|         chatResult = api.chat(requestModel); | ||||
|  | ||||
|         assertTrue( | ||||
|                 chatResult.getChatHistory().stream() | ||||
|                         .anyMatch(chat -> chat.getContent().contains("French")), | ||||
|                 "Expected chat history to contain 'French'" | ||||
|         ); | ||||
|  | ||||
|         // Create the next user question: the third question | ||||
|         requestModel = builder.withMessages(chatResult.getChatHistory()) | ||||
|                 .withMessage(OllamaChatMessageRole.USER, "What is the largest river in France?") | ||||
|                 .build(); | ||||
|  | ||||
|         // Continue conversation with the model for the third question | ||||
|         chatResult = api.chat(requestModel); | ||||
|  | ||||
|         // verify the result | ||||
|         assertNotNull(chatResult, "Chat result should not be null"); | ||||
|         assertTrue(chatResult.getChatHistory().size() > 2, "Chat history should contain more than two messages"); | ||||
|         assertTrue(chatResult.getChatHistory().get(chatResult.getChatHistory().size() - 1).getContent().contains("river"), "Response should be related to river"); | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user