From cfe8fd1481f641b2225e55edabeee52bb635c302 Mon Sep 17 00:00:00 2001 From: dlqqq Date: Tue, 5 Sep 2023 19:48:11 +0000 Subject: [PATCH 1/4] Publish 2.2.0 SHA256 hashes: jupyter-ai-core-2.2.0.tgz: 52670d4700a319100858ac4ec7183673db3d7c19b1f98286dcd9c1c491aad90b jupyter_ai-2.2.0-py3-none-any.whl: 5c1bb671255f7ff6e871b223571f2e089307d0be4c25fec025731176d19198fe jupyter_ai-2.2.0.tar.gz: fadd9ed7a9123fc678572f324aae188b83645372c5d0308bfd431ae5883ad18c jupyter_ai_magics-2.2.0-py3-none-any.whl: df3408af64657115fe94a961bc9ece83a1a67bb74d61fe06d26ca515d699dabc jupyter_ai_magics-2.2.0.tar.gz: 63ceadfa459a88c761fa952524a19b0c38a957145618e062260779ba46875809 --- CHANGELOG.md | 34 +++++++++++++++++++++++-- lerna.json | 2 +- package.json | 2 +- packages/jupyter-ai-magics/package.json | 2 +- packages/jupyter-ai/package.json | 2 +- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e638f56c9..e7e78a97d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,38 @@ +## 2.2.0 + +([Full Changelog](https://github.com/jupyterlab/jupyter-ai/compare/@jupyter-ai/core@2.1.0...56c1f518afd09d0d09a43221f0767aa961e9430f)) + +### Enhancements made + +- Loads vector store index lazily [#374](https://github.com/jupyterlab/jupyter-ai/pull/374) ([@3coins](https://github.com/3coins)) +- Added alias for bedrock titan model [#368](https://github.com/jupyterlab/jupyter-ai/pull/368) ([@3coins](https://github.com/3coins)) +- Update README, docs [#347](https://github.com/jupyterlab/jupyter-ai/pull/347) ([@JasonWeill](https://github.com/JasonWeill)) + +### Bugs fixed + +- fix newline typo in improve_code [#364](https://github.com/jupyterlab/jupyter-ai/pull/364) ([@michaelchia](https://github.com/michaelchia)) + +### Maintenance and upkeep improvements + +- Upgrades LangChain to 0.0.277 [#375](https://github.com/jupyterlab/jupyter-ai/pull/375) ([@3coins](https://github.com/3coins)) +- relax pinning on importlib_metadata, typing_extensions [#363](https://github.com/jupyterlab/jupyter-ai/pull/363) ([@minrk](https://github.com/minrk)) + +### Documentation improvements + +- Remove front end unit tests from code and README.md [#371](https://github.com/jupyterlab/jupyter-ai/pull/371) ([@andrii-i](https://github.com/andrii-i)) +- Update README, docs [#347](https://github.com/jupyterlab/jupyter-ai/pull/347) ([@JasonWeill](https://github.com/JasonWeill)) + +### Contributors to this release + +([GitHub contributors page for this release](https://github.com/jupyterlab/jupyter-ai/graphs/contributors?from=2023-08-15&to=2023-09-05&type=c)) + +[@3coins](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3A3coins+updated%3A2023-08-15..2023-09-05&type=Issues) | [@andrii-i](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Aandrii-i+updated%3A2023-08-15..2023-09-05&type=Issues) | [@JasonWeill](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3AJasonWeill+updated%3A2023-08-15..2023-09-05&type=Issues) | [@krassowski](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Akrassowski+updated%3A2023-08-15..2023-09-05&type=Issues) | [@michaelchia](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Amichaelchia+updated%3A2023-08-15..2023-09-05&type=Issues) | [@minrk](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Aminrk+updated%3A2023-08-15..2023-09-05&type=Issues) | [@welcome](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Awelcome+updated%3A2023-08-15..2023-09-05&type=Issues) + + + ## 2.1.0 ([Full Changelog](https://github.com/jupyterlab/jupyter-ai/compare/@jupyter-ai/core@2.0.1...c689c6c0cce5212238943ec2ff1559f6ad2f63d5)) @@ -24,8 +56,6 @@ [@3coins](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3A3coins+updated%3A2023-08-08..2023-08-15&type=Issues) | [@anammari](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Aanammari+updated%3A2023-08-08..2023-08-15&type=Issues) | [@bjornjorgensen](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Abjornjorgensen+updated%3A2023-08-08..2023-08-15&type=Issues) | [@dlqqq](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Adlqqq+updated%3A2023-08-08..2023-08-15&type=Issues) | [@JasonWeill](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3AJasonWeill+updated%3A2023-08-08..2023-08-15&type=Issues) | [@krassowski](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Akrassowski+updated%3A2023-08-08..2023-08-15&type=Issues) | [@welcome](https://github.com/search?q=repo%3Ajupyterlab%2Fjupyter-ai+involves%3Awelcome+updated%3A2023-08-08..2023-08-15&type=Issues) - - ## 2.0.1 ([Full Changelog](https://github.com/jupyterlab/jupyter-ai/compare/@jupyter-ai/core@2.0.0...f38d7f4a5b38ae1583c97bc8a0bb58ab09cdabdd)) diff --git a/lerna.json b/lerna.json index e19e10b60..b3c956cad 100644 --- a/lerna.json +++ b/lerna.json @@ -1,7 +1,7 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useWorkspaces": true, - "version": "2.1.0", + "version": "2.2.0", "npmClient": "yarn", "useNx": true } diff --git a/package.json b/package.json index edbaccdd6..fdc0458ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jupyter-ai/monorepo", - "version": "2.1.0", + "version": "2.2.0", "description": "A generative AI extension for JupyterLab", "private": true, "keywords": [ diff --git a/packages/jupyter-ai-magics/package.json b/packages/jupyter-ai-magics/package.json index 3623e2113..fea5f845a 100644 --- a/packages/jupyter-ai-magics/package.json +++ b/packages/jupyter-ai-magics/package.json @@ -1,6 +1,6 @@ { "name": "@jupyter-ai/magics", - "version": "2.1.0", + "version": "2.2.0", "description": "Jupyter AI magics Python package. Not published on NPM.", "private": true, "homepage": "https://github.com/jupyterlab/jupyter-ai", diff --git a/packages/jupyter-ai/package.json b/packages/jupyter-ai/package.json index 36079fba6..721ebace4 100644 --- a/packages/jupyter-ai/package.json +++ b/packages/jupyter-ai/package.json @@ -1,6 +1,6 @@ { "name": "@jupyter-ai/core", - "version": "2.1.0", + "version": "2.2.0", "description": "A generative AI extension for JupyterLab", "keywords": [ "jupyter", From 94b8ef7cfe4508f32d595e617cd0249288b2b2c6 Mon Sep 17 00:00:00 2001 From: Jason Weill <93281816+JasonWeill@users.noreply.github.com> Date: Tue, 5 Sep 2023 17:06:11 -0700 Subject: [PATCH 2/4] jupyter_ai and jupyter_ai_magics version match (#367) --- docs/source/users/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/users/index.md b/docs/source/users/index.md index 2f640f579..83f91781d 100644 --- a/docs/source/users/index.md +++ b/docs/source/users/index.md @@ -42,6 +42,8 @@ conda install jupyterlab~=4.0 The `jupyter_ai_magics` package, which provides exclusively the IPython magics, does not depend on JupyterLab or `jupyter_ai`. You can install `jupyter_ai_magics` without installing `jupyterlab` or `jupyter_ai`. +If you have both `jupyter_ai_magics` and `jupyter_ai` installed, you should +have the same version of each, to avoid errors. ## Installation From fc711c7cc79388a867b6e9b8c983e7affe8ad8e4 Mon Sep 17 00:00:00 2001 From: david qiu Date: Thu, 7 Sep 2023 13:14:49 -0700 Subject: [PATCH 3/4] Config V2 (#353) * config manager initial draft * implement basic client for new config manager * implement JL4 unit testing (do not backport) * implement chat settings save * implement client API key deletion * greatly improve error banner handling in settings * implement API key edit and delete in settings UI * ensure API keys are not empty * reduce top and side padding in settings UI * pre-commit * fix integer field type error from rebase * fix api key edit/delete react bugs * improve UI error formatting * implement last_read check on settings form * fix local model ID not showing * remove outdated comment * ensure no empty field dictionaries in config * fix minor typo --- .../jupyter-ai/conftest.py => conftest.py | 0 package.json | 3 +- packages/jupyter-ai/.gitignore | 1 + packages/jupyter-ai/jest.config.js | 41 +- .../jupyter_ai/chat_handlers/base.py | 4 +- .../jupyter_ai/chat_handlers/learn.py | 5 +- .../jupyter_ai/config/config_schema.json | 42 + .../jupyter-ai/jupyter_ai/config_manager.py | 369 ++- packages/jupyter-ai/jupyter_ai/extension.py | 6 +- packages/jupyter-ai/jupyter_ai/handlers.py | 22 +- packages/jupyter-ai/jupyter_ai/models.py | 50 +- .../__snapshots__/test_config_manager.ambr | 12 + .../jupyter_ai/tests/test_config_manager.py | 247 ++ packages/jupyter-ai/package.json | 10 +- packages/jupyter-ai/pyproject.toml | 5 +- .../src/components/chat-settings.tsx | 460 ++- .../mui-extras/async-icon-button.tsx | 89 + .../mui-extras/contrasting-tooltip.tsx | 22 + .../components/mui-extras/stacking-alert.tsx | 100 + .../settings/__tests__/chat-settings.spec.ts | 63 + .../components/settings/existing-api-keys.tsx | 234 ++ .../src/components/settings/minify.ts | 56 + .../src/components/settings/model-fields.tsx | 37 +- .../components/settings/use-server-info.ts | 159 + .../src/components/settings/validator.ts | 8 + packages/jupyter-ai/src/handler.ts | 28 +- packages/jupyter-ai/tsconfig.test.json | 6 + yarn.lock | 2621 ++++------------- 28 files changed, 2262 insertions(+), 2438 deletions(-) rename packages/jupyter-ai/conftest.py => conftest.py (100%) create mode 100644 packages/jupyter-ai/jupyter_ai/config/config_schema.json create mode 100644 packages/jupyter-ai/jupyter_ai/tests/__snapshots__/test_config_manager.ambr create mode 100644 packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py create mode 100644 packages/jupyter-ai/src/components/mui-extras/async-icon-button.tsx create mode 100644 packages/jupyter-ai/src/components/mui-extras/contrasting-tooltip.tsx create mode 100644 packages/jupyter-ai/src/components/mui-extras/stacking-alert.tsx create mode 100644 packages/jupyter-ai/src/components/settings/__tests__/chat-settings.spec.ts create mode 100644 packages/jupyter-ai/src/components/settings/existing-api-keys.tsx create mode 100644 packages/jupyter-ai/src/components/settings/minify.ts create mode 100644 packages/jupyter-ai/src/components/settings/use-server-info.ts create mode 100644 packages/jupyter-ai/src/components/settings/validator.ts create mode 100644 packages/jupyter-ai/tsconfig.test.json diff --git a/packages/jupyter-ai/conftest.py b/conftest.py similarity index 100% rename from packages/jupyter-ai/conftest.py rename to conftest.py diff --git a/package.json b/package.json index fdc0458ec..09b89e11e 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "dev-uninstall": "lerna run dev-uninstall --stream", "lint": "jlpm && lerna run prettier && lerna run eslint", "lint:check": "lerna run prettier:check && lerna run eslint:check", - "watch": "lerna run watch --parallel --stream" + "watch": "lerna run watch --parallel --stream", + "test": "lerna run test" }, "devDependencies": { "@jupyterlab/builder": "^4", diff --git a/packages/jupyter-ai/.gitignore b/packages/jupyter-ai/.gitignore index 7c34e452b..7198a2ce0 100644 --- a/packages/jupyter-ai/.gitignore +++ b/packages/jupyter-ai/.gitignore @@ -124,3 +124,4 @@ dmypy.json # Coverage reports coverage/* +junit.xml diff --git a/packages/jupyter-ai/jest.config.js b/packages/jupyter-ai/jest.config.js index 4f1bf3dab..c289e813e 100644 --- a/packages/jupyter-ai/jest.config.js +++ b/packages/jupyter-ai/jest.config.js @@ -1,46 +1,29 @@ const jestJupyterLab = require('@jupyterlab/testutils/lib/jest-config'); const esModules = [ + '@codemirror', + '@jupyter/ydoc', '@jupyterlab/', 'lib0', - 'y\\-protocols', - 'y\\-websocket', + 'nanoid', + 'vscode-ws-jsonrpc', + 'y-protocols', + 'y-websocket', 'yjs' ].join('|'); -const jlabConfig = jestJupyterLab(__dirname); - -const { - moduleFileExtensions, - moduleNameMapper, - preset, - setupFilesAfterEnv, - setupFiles, - testPathIgnorePatterns, - transform -} = jlabConfig; +const baseConfig = jestJupyterLab(__dirname); module.exports = { - moduleFileExtensions, - moduleNameMapper, - preset, - setupFilesAfterEnv, - setupFiles, - testPathIgnorePatterns, - transform, + ...baseConfig, automock: false, collectCoverageFrom: [ - 'src/**/*.{ts,tsx}', - '!src/**/*.d.ts', - '!src/**/.ipynb_checkpoints/*' + // TODO: re-enable coverage reports when we have more comprehensive testing + // 'src/**/*.{ts,tsx}', + // '!src/**/*.d.ts', + // '!src/**/.ipynb_checkpoints/*' ], - coverageDirectory: 'coverage', coverageReporters: ['lcov', 'text'], - globals: { - 'ts-jest': { - tsconfig: 'tsconfig.json' - } - }, testRegex: 'src/.*/.*.spec.ts[x]?$', transformIgnorePatterns: [`/node_modules/(?!${esModules}).+`] }; diff --git a/packages/jupyter-ai/jupyter_ai/chat_handlers/base.py b/packages/jupyter-ai/jupyter_ai/chat_handlers/base.py index ebb2fc72d..87da6d214 100644 --- a/packages/jupyter-ai/jupyter_ai/chat_handlers/base.py +++ b/packages/jupyter-ai/jupyter_ai/chat_handlers/base.py @@ -61,8 +61,8 @@ def reply(self, response, human_msg: Optional[HumanChatMessage] = None): break def get_llm_chain(self): - lm_provider = self.config_manager.get_lm_provider() - lm_provider_params = self.config_manager.get_lm_provider_params() + lm_provider = self.config_manager.lm_provider + lm_provider_params = self.config_manager.lm_provider_params curr_lm_id = ( f'{self.llm.id}:{lm_provider_params["model_id"]}' if self.llm else None diff --git a/packages/jupyter-ai/jupyter_ai/chat_handlers/learn.py b/packages/jupyter-ai/jupyter_ai/chat_handlers/learn.py index 7d88beac2..712444f3c 100644 --- a/packages/jupyter-ai/jupyter_ai/chat_handlers/learn.py +++ b/packages/jupyter-ai/jupyter_ai/chat_handlers/learn.py @@ -278,10 +278,7 @@ async def aget_relevant_documents( return docs def get_embedding_provider(self): - em_provider_cls = self.config_manager.get_em_provider() - em_provider_args = self.config_manager.get_em_provider_params() - - return em_provider_cls, em_provider_args + return self.config_manager.em_provider, self.config_manager.em_provider_params def get_embedding_model(self): em_provider_cls, em_provider_args = self.get_embedding_provider() diff --git a/packages/jupyter-ai/jupyter_ai/config/config_schema.json b/packages/jupyter-ai/jupyter_ai/config/config_schema.json new file mode 100644 index 000000000..ff7c717c4 --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/config/config_schema.json @@ -0,0 +1,42 @@ +{ + "title": "Jupyter AI configuration", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$comment": "Default values are sourced from `config_manager.py`.", + "type": "object", + "properties": { + "model_provider_id": { + "$comment": "Language model global ID.", + "type": ["string", "null"], + "default": null, + "readOnly": false + }, + "embeddings_provider_id": { + "$comment": "Embedding model global ID.", + "type": ["string", "null"], + "default": null, + "readOnly": false + }, + "api_keys": { + "$comment": "Dictionary of API keys, mapping key names to key values.", + "type": "object", + "default": {} + }, + "send_with_shift_enter": { + "$comment": "Whether to send a message via Shift-Enter instead of Enter.", + "type": "boolean", + "default": false, + "readOnly": false + }, + "fields": { + "$comment": "Dictionary of model-specific fields, mapping LM GIDs to sub-dictionaries of field key-value pairs.", + "type": "object", + "default": {}, + "patternProperties": { + "^.*$": { + "anyOf": [{ "type": "object" }] + } + }, + "additionalProperties": false + } + } +} diff --git a/packages/jupyter-ai/jupyter_ai/config_manager.py b/packages/jupyter-ai/jupyter_ai/config_manager.py index 5fa8b8a72..f61e07bde 100644 --- a/packages/jupyter-ai/jupyter_ai/config_manager.py +++ b/packages/jupyter-ai/jupyter_ai/config_manager.py @@ -1,9 +1,13 @@ import json import logging import os -from typing import Any, Dict, Union +import shutil +import time +from typing import Optional, Union -from jupyter_ai.models import GlobalConfig +from deepmerge import always_merger as Merger +from jsonschema import Draft202012Validator as Validator +from jupyter_ai.models import DescribeConfigResponse, GlobalConfig, UpdateConfigRequest from jupyter_ai_magics.utils import ( AnyProvider, EmProvidersDict, @@ -12,120 +16,317 @@ get_lm_provider, ) from jupyter_core.paths import jupyter_data_dir +from traitlets import Integer, Unicode +from traitlets.config import Configurable Logger = Union[logging.Logger, logging.LoggerAdapter] +# default path to config +DEFAULT_CONFIG_PATH = os.path.join(jupyter_data_dir(), "jupyter_ai", "config.json") -class ConfigManager: +# default path to config JSON Schema +DEFAULT_SCHEMA_PATH = os.path.join( + jupyter_data_dir(), "jupyter_ai", "config_schema.json" +) + +# default no. of spaces to use when formatting config +DEFAULT_INDENTATION_DEPTH = 4 + +# path to the default schema defined in this project +# if a file does not exist at SCHEMA_PATH, this file is used as a default. +OUR_SCHEMA_PATH = os.path.join( + os.path.dirname(__file__), "config", "config_schema.json" +) + + +class AuthError(Exception): + pass + + +class WriteConflictError(Exception): + pass + + +class KeyInUseError(Exception): + pass + + +class KeyEmptyError(Exception): + pass + + +def _validate_provider_authn(config: GlobalConfig, provider: AnyProvider): + # TODO: handle non-env auth strategies + if not provider.auth_strategy or provider.auth_strategy.type != "env": + return + + if provider.auth_strategy.name not in config.api_keys: + raise AuthError( + f"Missing API key for '{provider.auth_strategy.name}' in the config." + ) + + +class ConfigManager(Configurable): """Provides model and embedding provider id along with the credentials to authenticate providers. """ + config_path = Unicode( + default_value=DEFAULT_CONFIG_PATH, + help="Path to the configuration file.", + allow_none=False, + config=True, + ) + + schema_path = Unicode( + default_value=DEFAULT_SCHEMA_PATH, + help="Path to the configuration's corresponding JSON Schema file.", + allow_none=False, + config=True, + ) + + indentation_depth = Integer( + default_value=DEFAULT_INDENTATION_DEPTH, + help="Indentation depth, in number of spaces per level.", + allow_none=False, + config=True, + ) + def __init__( - self, log: Logger, lm_providers: LmProvidersDict, em_providers: EmProvidersDict + self, + log: Logger, + lm_providers: LmProvidersDict, + em_providers: EmProvidersDict, + *args, + **kwargs, ): + super().__init__(*args, **kwargs) self.log = log - self.save_dir = os.path.join(jupyter_data_dir(), "jupyter_ai") - self.save_path = os.path.join(self.save_dir, "config.json") - self.config = None - self.lm_providers = lm_providers - self.em_providers = em_providers - self.lm_provider = None - self.lm_provider_params = {} - self.em_provider = None - self.em_provider_params = {} - self._load() - - def update(self, config: GlobalConfig, save_to_disk: bool = True): - self._update_lm_provider(config) - self._update_em_provider(config) - if save_to_disk: - self._save(config) - self.config = config + """List of LM providers.""" + self._lm_providers = lm_providers + """List of EM providers.""" + self._em_providers = em_providers - def get_config(self): - return self.config + """When the server last read the config file. If the file was not + modified after this time, then we can return the cached + `self._config`.""" + self._last_read: Optional[int] = None - def get_lm_provider(self): - return self.lm_provider + """In-memory cache of the `GlobalConfig` object parsed from the config + file.""" + self._config: Optional[GlobalConfig] = None - def get_lm_provider_params(self): - return self.lm_provider_params + self._init_config_schema() + self._init_validator() + self._init_config() - def get_em_provider(self): - return self.em_provider + def _init_config_schema(self): + if not os.path.exists(self.schema_path): + os.makedirs(os.path.dirname(self.schema_path), exist_ok=True) + shutil.copy(OUR_SCHEMA_PATH, self.schema_path) - def get_em_provider_params(self): - return self.em_provider_params + def _init_validator(self) -> Validator: + with open(OUR_SCHEMA_PATH, encoding="utf-8") as f: + schema = json.loads(f.read()) + Validator.check_schema(schema) + self.validator = Validator(schema) - def _authenticate_provider( - self, - provider: AnyProvider, - provider_params: Dict[str, Any], - config: GlobalConfig, - ): - auth_strategy = provider.auth_strategy - if auth_strategy and auth_strategy.type == "env": - api_keys = config.api_keys - name = auth_strategy.name - if name not in api_keys: + def _init_config(self): + if os.path.exists(self.config_path): + with open(self.config_path, encoding="utf-8") as f: + config = GlobalConfig(**json.loads(f.read())) + # re-write to the file to validate the config and apply any + # updates to the config file immediately + self._write_config(config) + return + + properties = self.validator.schema.get("properties", {}) + field_list = GlobalConfig.__fields__.keys() + field_dict = { + field: properties.get(field).get("default") for field in field_list + } + default_config = GlobalConfig(**field_dict) + self._write_config(default_config) + + def _read_config(self) -> GlobalConfig: + """Returns the user's current configuration as a GlobalConfig object. + This should never be sent to the client as it includes API keys. Prefer + self.get_config() for sending the config to the client.""" + if self._config and self._last_read: + last_write = os.stat(self.config_path).st_mtime_ns + if last_write <= self._last_read: + return self._config + + with open(self.config_path, encoding="utf-8") as f: + self._last_read = time.time_ns() + raw_config = json.loads(f.read()) + config = GlobalConfig(**raw_config) + self._validate_config(config) + return config + + def _validate_config(self, config: GlobalConfig): + """Method used to validate the configuration. This is called after every + read and before every write to the config file. Guarantees that the + config file conforms to the JSON Schema, and that the language and + embedding models have authn credentials if specified.""" + self.validator.validate(config.dict()) + + # validate language model config + if config.model_provider_id: + _, lm_provider = get_lm_provider( + config.model_provider_id, self._lm_providers + ) + if not lm_provider: raise ValueError( - f"Missing value for '{auth_strategy.name}' in the config." + f"No language model is associated with '{config.model_provider_id}'." ) - provider_params[name.lower()] = api_keys[name] + _validate_provider_authn(config, lm_provider) - def _update_lm_provider(self, config: GlobalConfig): - model_id = config.model_provider_id + # validate embedding model config + if config.embeddings_provider_id: + _, em_provider = get_em_provider( + config.embeddings_provider_id, self._em_providers + ) + if not em_provider: + raise ValueError( + f"No embedding model is associated with '{config.embeddings_provider_id}'." + ) + _validate_provider_authn(config, em_provider) - if not model_id: - self.lm_provider = None - self.lm_provider_params = None - return + def _write_config(self, new_config: GlobalConfig): + """Updates configuration and persists it to disk. This accepts a + complete `GlobalConfig` object, and should not be called publicly.""" + # remove any empty field dictionaries + new_config.fields = {k: v for k, v in new_config.fields.items() if v} - local_model_id, provider = get_lm_provider(model_id, self.lm_providers) + self._validate_config(new_config) + with open(self.config_path, "w") as f: + json.dump(new_config.dict(), f, indent=self.indentation_depth) - if not provider: - raise ValueError(f"No provider and model found with '{model_id}'") + def delete_api_key(self, key_name: str): + config_dict = self._read_config().dict() + lm_provider = self.lm_provider + em_provider = self.em_provider + required_keys = [] + if ( + lm_provider + and lm_provider.auth_strategy + and lm_provider.auth_strategy.type == "env" + ): + required_keys.append(lm_provider.auth_strategy.name) + if ( + em_provider + and em_provider.auth_strategy + and em_provider.auth_strategy.type == "env" + ): + required_keys.append(self.em_provider.auth_strategy.name) - fields = config.fields.get(model_id, {}) - provider_params = {"model_id": local_model_id, **fields} + if key_name in required_keys: + raise KeyInUseError( + "This API key is currently in use by the language or embedding model. Please change the model before deleting the corresponding API key." + ) - self._authenticate_provider(provider, provider_params, config) - self.lm_provider = provider - self.lm_provider_params = provider_params + config_dict["api_keys"].pop(key_name, None) + self._write_config(GlobalConfig(**config_dict)) - def _update_em_provider(self, config: GlobalConfig): - model_id = config.embeddings_provider_id + def update_config(self, config_update: UpdateConfigRequest): + last_write = os.stat(self.config_path).st_mtime_ns + if config_update.last_read and config_update.last_read < last_write: + raise WriteConflictError( + "Configuration was modified after it was read from disk." + ) - if not model_id: - self.em_provider = None - self.em_provider_params - return + if config_update.api_keys: + for api_key_value in config_update.api_keys.values(): + if not api_key_value: + raise KeyEmptyError("API key value cannot be empty.") - local_model_id, provider = get_em_provider(model_id, self.em_providers) + config_dict = self._read_config().dict() + Merger.merge(config_dict, config_update.dict(exclude_unset=True)) + self._write_config(GlobalConfig(**config_dict)) - if not provider: - raise ValueError(f"No provider and model found with '{model_id}'") + # this cannot be a property, as the parent Configurable already defines the + # self.config attr. + def get_config(self): + config = self._read_config() + config_dict = config.dict(exclude_unset=True) + api_key_names = list(config_dict.pop("api_keys").keys()) + return DescribeConfigResponse( + **config_dict, api_keys=api_key_names, last_read=self._last_read + ) - provider_params = {"model_id": local_model_id} + @property + def lm_gid(self): + config = self._read_config() + return config.model_provider_id - self._authenticate_provider(provider, provider_params, config) - self.em_provider = provider - self.em_provider_params = provider_params + @property + def em_gid(self): + config = self._read_config() + return config.embeddings_provider_id - def _save(self, config: GlobalConfig): - if not os.path.exists(self.save_dir): - os.makedirs(self.save_dir) + @property + def lm_provider(self): + config = self._read_config() + lm_gid = config.model_provider_id + if lm_gid is None: + return None - with open(self.save_path, "w") as f: - f.write(config.json()) + _, Provider = get_lm_provider(config.model_provider_id, self._lm_providers) + return Provider - def _load(self): - if os.path.exists(self.save_path): - with open(self.save_path, encoding="utf-8") as f: - config = GlobalConfig(**json.loads(f.read())) - self.update(config, False) - return + @property + def em_provider(self): + config = self._read_config() + em_gid = config.embeddings_provider_id + if em_gid is None: + return None + + _, Provider = get_em_provider(em_gid, self._em_providers) + return Provider + + @property + def lm_provider_params(self): + # get generic fields + config = self._read_config() + lm_gid = config.model_provider_id + if not lm_gid: + return None + + lm_lid = lm_gid.split(":", 1)[1] + fields = config.fields.get(lm_gid, {}) + + # get authn fields + _, Provider = get_lm_provider(lm_gid, self._lm_providers) + authn_fields = {} + if Provider.auth_strategy and Provider.auth_strategy.type == "env": + key_name = Provider.auth_strategy.name + authn_fields[key_name.lower()] = config.api_keys[key_name] + + return { + "model_id": lm_lid, + **fields, + **authn_fields, + } + + @property + def em_provider_params(self): + # get generic fields + config = self._read_config() + em_gid = config.embeddings_provider_id + if not em_gid: + return None + + em_lid = em_gid.split(":", 1)[1] + + # get authn fields + _, Provider = get_em_provider(em_gid, self._em_providers) + authn_fields = {} + if Provider.auth_strategy and Provider.auth_strategy.type == "env": + key_name = Provider.auth_strategy.name + authn_fields[key_name.lower()] = config.api_keys[key_name] - # otherwise, create a new empty config file - self.update(GlobalConfig(), True) + return { + "model_id": em_lid, + **authn_fields, + } diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index a6564679b..7b6d07b31 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -16,6 +16,7 @@ from .chat_handlers.help import HelpMessage from .config_manager import ConfigManager from .handlers import ( + ApiKeysHandler, ChatHistoryHandler, EmbeddingsModelProviderHandler, GlobalConfigHandler, @@ -27,7 +28,8 @@ class AiExtension(ExtensionApp): name = "jupyter_ai" handlers = [ - ("api/ai/config", GlobalConfigHandler), + (r"api/ai/api_keys/(?P\w+)", ApiKeysHandler), + (r"api/ai/config/?", GlobalConfigHandler), (r"api/ai/chats/?", RootChatHandler), (r"api/ai/chats/history?", ChatHistoryHandler), (r"api/ai/providers?", ModelProviderHandler), @@ -41,6 +43,8 @@ def initialize_settings(self): self.settings["em_providers"] = get_em_providers(log=self.log) self.settings["jai_config_manager"] = ConfigManager( + # traitlets configuration, not JAI configuration. + config=self.config, log=self.log, lm_providers=self.settings["lm_providers"], em_providers=self.settings["em_providers"], diff --git a/packages/jupyter-ai/jupyter_ai/handlers.py b/packages/jupyter-ai/jupyter_ai/handlers.py index 95db5198a..965da598c 100644 --- a/packages/jupyter-ai/jupyter_ai/handlers.py +++ b/packages/jupyter-ai/jupyter_ai/handlers.py @@ -8,6 +8,7 @@ import tornado from jupyter_ai.chat_handlers import BaseChatHandler +from jupyter_ai.config_manager import ConfigManager, KeyEmptyError, WriteConflictError from jupyter_server.base.handlers import APIHandler as BaseAPIHandler from jupyter_server.base.handlers import JupyterHandler from pydantic import ValidationError @@ -22,11 +23,11 @@ ChatRequest, ChatUser, ConnectionMessage, - GlobalConfig, HumanChatMessage, ListProvidersEntry, ListProvidersResponse, Message, + UpdateConfigRequest, ) if TYPE_CHECKING: @@ -320,11 +321,11 @@ def get(self): @web.authenticated def post(self): try: - config = GlobalConfig(**self.get_json_body()) - self.config_manager.update(config) + config = UpdateConfigRequest(**self.get_json_body()) + self.config_manager.update_config(config) self.set_status(204) self.finish() - except ValidationError as e: + except (ValidationError, WriteConflictError, KeyEmptyError) as e: self.log.exception(e) raise HTTPError(500, str(e)) from e except ValueError as e: @@ -335,3 +336,16 @@ def post(self): raise HTTPError( 500, "Unexpected error occurred while updating the config." ) from e + + +class ApiKeysHandler(BaseAPIHandler): + @property + def config_manager(self) -> ConfigManager: + return self.settings["jai_config_manager"] + + @web.authenticated + def delete(self, api_key_name: str): + try: + self.config_manager.delete_api_key(api_key_name) + except Exception as e: + raise HTTPError(500, str(e)) diff --git a/packages/jupyter-ai/jupyter_ai/models.py b/packages/jupyter-ai/jupyter_ai/models.py index ca2030881..8e4e992aa 100644 --- a/packages/jupyter-ai/jupyter_ai/models.py +++ b/packages/jupyter-ai/jupyter_ai/models.py @@ -1,7 +1,7 @@ from typing import Any, Dict, List, Literal, Optional, Union from jupyter_ai_magics.providers import AuthStrategy, Field -from pydantic import BaseModel +from pydantic import BaseModel, validator DEFAULT_CHUNK_SIZE = 2000 DEFAULT_CHUNK_OVERLAP = 100 @@ -98,9 +98,47 @@ class IndexMetadata(BaseModel): dirs: List[IndexedDir] +class DescribeConfigResponse(BaseModel): + model_provider_id: Optional[str] + embeddings_provider_id: Optional[str] + send_with_shift_enter: bool + fields: Dict[str, Dict[str, Any]] + # when sending config over REST API, do not include values of the API keys, + # just the names. + api_keys: List[str] + # timestamp indicating when the configuration file was last read. should be + # passed to the subsequent UpdateConfig request. + last_read: int + + +def forbid_none(cls, v): + assert v is not None, "size may not be None" + return v + + +class UpdateConfigRequest(BaseModel): + model_provider_id: Optional[str] + embeddings_provider_id: Optional[str] + send_with_shift_enter: Optional[bool] + api_keys: Optional[Dict[str, str]] + fields: Optional[Dict[str, Dict[str, Any]]] + # if passed, this will raise an Error if the config was written to after the + # time specified by `last_read` to prevent write-write conflicts. + last_read: Optional[int] + + _validate_send_wse = validator("send_with_shift_enter", allow_reuse=True)( + forbid_none + ) + _validate_api_keys = validator("api_keys", allow_reuse=True)(forbid_none) + _validate_fields = validator("fields", allow_reuse=True)(forbid_none) + + class GlobalConfig(BaseModel): - model_provider_id: Optional[str] = None - embeddings_provider_id: Optional[str] = None - api_keys: Dict[str, str] = {} - send_with_shift_enter: Optional[bool] = None - fields: Dict[str, Dict[str, Any]] = {} + """Model used to represent the config by ConfigManager. This is exclusive to + the backend and should never be sent to the client.""" + + model_provider_id: Optional[str] + embeddings_provider_id: Optional[str] + send_with_shift_enter: bool + fields: Dict[str, Dict[str, Any]] + api_keys: Dict[str, str] diff --git a/packages/jupyter-ai/jupyter_ai/tests/__snapshots__/test_config_manager.ambr b/packages/jupyter-ai/jupyter_ai/tests/__snapshots__/test_config_manager.ambr new file mode 100644 index 000000000..cd254bedc --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/tests/__snapshots__/test_config_manager.ambr @@ -0,0 +1,12 @@ +# serializer version: 1 +# name: test_snapshot_default_config + dict({ + 'api_keys': list([ + ]), + 'embeddings_provider_id': None, + 'fields': dict({ + }), + 'model_provider_id': None, + 'send_with_shift_enter': False, + }) +# --- diff --git a/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py new file mode 100644 index 000000000..f7afbd29a --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/tests/test_config_manager.py @@ -0,0 +1,247 @@ +import json +import logging +import os + +import pytest +from jupyter_ai.config_manager import ( + AuthError, + ConfigManager, + KeyInUseError, + WriteConflictError, +) +from jupyter_ai.models import DescribeConfigResponse, UpdateConfigRequest +from jupyter_ai_magics.utils import get_em_providers, get_lm_providers +from pydantic import ValidationError + + +@pytest.fixture +def config_path(jp_data_dir): + return str(jp_data_dir / "config.json") + + +@pytest.fixture +def schema_path(jp_data_dir): + return str(jp_data_dir / "config_schema.json") + + +@pytest.fixture +def common_cm_kwargs(config_path, schema_path): + """Kwargs that are commonly used when initializing the CM.""" + log = logging.getLogger() + lm_providers = get_lm_providers() + em_providers = get_em_providers() + return { + "log": log, + "lm_providers": lm_providers, + "em_providers": em_providers, + "config_path": config_path, + "schema_path": schema_path, + } + + +@pytest.fixture +def cm(common_cm_kwargs): + """The default ConfigManager instance, with an empty config and config schema.""" + return ConfigManager(**common_cm_kwargs) + + +@pytest.fixture(autouse=True) +def reset(config_path, schema_path): + """Fixture that deletes the config and config schema after each test.""" + yield + try: + os.remove(config_path) + except OSError: + pass + try: + os.remove(schema_path) + except OSError: + pass + + +def configure_to_cohere(cm: ConfigManager): + """Configures the ConfigManager to use Cohere language and embedding models + with the API key set. Returns a 3-tuple of the keyword arguments used.""" + LM_GID = "cohere:xlarge" + EM_GID = "cohere:large" + API_KEYS = {"COHERE_API_KEY": "foobar"} + # the params use lowercase key names + LM_LID = "xlarge" + EM_LID = "large" + API_PARAMS = {"cohere_api_key": "foobar"} + req = UpdateConfigRequest( + model_provider_id=LM_GID, embeddings_provider_id=EM_GID, api_keys=API_KEYS + ) + cm.update_config(req) + return LM_GID, EM_GID, LM_LID, EM_LID, API_PARAMS + + +def configure_to_openai(cm: ConfigManager): + """Configures the ConfigManager to use OpenAI language and embedding models + with the API key set. Returns a 3-tuple of the keyword arguments used.""" + LM_GID = "openai-chat-new:gpt-3.5-turbo" + EM_GID = "openai:text-embedding-ada-002" + API_KEYS = {"OPENAI_API_KEY": "foobar"} + LM_LID = "gpt-3.5-turbo" + EM_LID = "text-embedding-ada-002" + API_PARAMS = {"openai_api_key": "foobar"} + req = UpdateConfigRequest( + model_provider_id=LM_GID, embeddings_provider_id=EM_GID, api_keys=API_KEYS + ) + cm.update_config(req) + return LM_GID, EM_GID, LM_LID, EM_LID, API_PARAMS + + +def test_snapshot_default_config(cm: ConfigManager, snapshot): + config_from_cm: DescribeConfigResponse = cm.get_config() + assert config_from_cm == snapshot(exclude=lambda prop, path: prop == "last_read") + + +def test_init_with_existing_config( + cm: ConfigManager, config_path: str, schema_path: str +): + configure_to_cohere(cm) + del cm + + log = logging.getLogger() + lm_providers = get_lm_providers() + em_providers = get_em_providers() + ConfigManager( + log=log, + lm_providers=lm_providers, + em_providers=em_providers, + config_path=config_path, + schema_path=schema_path, + ) + + +def test_property_access_on_default_config(cm: ConfigManager): + """Asserts that the CM behaves well with an empty, default + configuration.""" + assert cm.lm_gid == None + assert cm.em_gid == None + assert cm.lm_provider == None + assert cm.lm_provider_params == None + assert cm.em_provider == None + assert cm.em_provider_params == None + + +def test_indentation_depth(common_cm_kwargs, config_path): + """Asserts that the CM indents the configuration and respects the + `indentation_depth` trait when specified.""" + INDENT_DEPTH = 7 + ConfigManager(**common_cm_kwargs, indentation_depth=INDENT_DEPTH) + with open(config_path) as f: + config_file = f.read() + config_lines = config_file.split("\n") + lm_gid_line = next( + line for line in config_lines if '"model_provider_id":' in line + ) + assert lm_gid_line.startswith(" " * INDENT_DEPTH) + assert not lm_gid_line.startswith(" " * (INDENT_DEPTH + 1)) + + +def test_describe(cm: ConfigManager): + LM_GID, EM_GID, LM_LID, EM_LID, API_PARAMS = configure_to_cohere(cm) + + config_desc = cm.get_config() + assert config_desc.model_provider_id == LM_GID + assert config_desc.embeddings_provider_id == EM_GID + assert config_desc.api_keys == ["COHERE_API_KEY"] + assert cm.lm_provider_params == {**API_PARAMS, "model_id": LM_LID} + assert cm.em_provider_params == {**API_PARAMS, "model_id": EM_LID} + + +def test_update(cm: ConfigManager): + LM_GID, EM_GID, LM_LID, EM_LID, API_PARAMS = configure_to_cohere(cm) + + new_config = cm.get_config() + assert new_config.model_provider_id == LM_GID + assert new_config.embeddings_provider_id == EM_GID + assert new_config.api_keys == ["COHERE_API_KEY"] + assert cm.lm_provider_params == {**API_PARAMS, "model_id": LM_LID} + assert cm.em_provider_params == {**API_PARAMS, "model_id": EM_LID} + + +def test_update_no_empty_field_dicts(cm: ConfigManager, config_path): + LM_GID, _, _, _, _ = configure_to_cohere(cm) + cm.update_config(UpdateConfigRequest(fields={LM_GID: {}})) + + with open(config_path) as f: + raw_config = json.loads(f.read()) + assert raw_config["fields"] == {} + + +def test_update_fails_with_invalid_req(): + with pytest.raises(ValidationError): + UpdateConfigRequest(send_with_shift_enter=None) + with pytest.raises(ValidationError): + UpdateConfigRequest(fields=None) + with pytest.raises(ValidationError): + UpdateConfigRequest(api_keys=None) + + +def test_update_fails_without_auth(cm: ConfigManager): + LM_GID = "cohere:xlarge" + EM_GID = "cohere:large" + req = UpdateConfigRequest(model_provider_id=LM_GID, embeddings_provider_id=EM_GID) + with pytest.raises(AuthError): + cm.update_config(req) + + +def test_update_after_describe(cm: ConfigManager): + configure_to_cohere(cm) + last_read = cm.get_config().last_read + cm.update_config( + UpdateConfigRequest(model_provider_id="cohere:medium", last_read=last_read) + ) + + new_config = cm.get_config() + assert new_config.model_provider_id == "cohere:medium" + + +def test_forbid_write_write_conflict(cm: ConfigManager): + configure_to_openai(cm) + # call DescribeConfig + last_read = cm.get_config().last_read + + # call UpdateConfig separately after DescribeConfig with `last_read` unset + # to force a write + cm.update_config(UpdateConfigRequest(model_provider_id="openai-chat-new:gpt-4")) + + # this update should fail, as this generates a write-write conflict (where + # the second update clobbers the first update). + with pytest.raises(WriteConflictError): + cm.update_config( + UpdateConfigRequest( + model_provider_id="openai-chat-new:gpt-4-32k", last_read=last_read + ) + ) + + +def test_update_api_key(cm: ConfigManager): + """Asserts that updates via direct edits to the config file are immediately + reflected by the ConfigManager.""" + LM_GID, EM_GID, LM_LID, EM_LID, _ = configure_to_cohere(cm) + cm.update_config(UpdateConfigRequest(api_keys={"COHERE_API_KEY": "barfoo"})) + + config_desc = cm.get_config() + assert config_desc.api_keys == ["COHERE_API_KEY"] + assert cm.lm_provider_params == {"cohere_api_key": "barfoo", "model_id": LM_LID} + assert cm.em_provider_params == {"cohere_api_key": "barfoo", "model_id": EM_LID} + + +def test_delete_api_key(cm: ConfigManager): + configure_to_cohere(cm) + cm.update_config(UpdateConfigRequest(api_keys={"OPENAI_API_KEY": "asdf"})) + assert cm.get_config().api_keys == ["COHERE_API_KEY", "OPENAI_API_KEY"] + + cm.delete_api_key("OPENAI_API_KEY") + assert cm.get_config().api_keys == ["COHERE_API_KEY"] + + +def test_forbid_deleting_key_in_use(cm: ConfigManager): + configure_to_cohere(cm) + + with pytest.raises(KeyInUseError): + cm.delete_api_key("COHERE_API_KEY") diff --git a/packages/jupyter-ai/package.json b/packages/jupyter-ai/package.json index 721ebace4..268f0753a 100644 --- a/packages/jupyter-ai/package.json +++ b/packages/jupyter-ai/package.json @@ -54,7 +54,7 @@ "watch": "run-p watch:src watch:labextension", "watch:src": "tsc -w", "watch:labextension": "jupyter labextension watch .", - "dev-install": "pip install -e \".[dev,all]\" && jupyter labextension develop . --overwrite && jupyter server extension enable jupyter_ai", + "dev-install": "pip install -e \".[dev,all,test]\" && jupyter labextension develop . --overwrite && jupyter server extension enable jupyter_ai", "dev-uninstall": "pip uninstall jupyter_ai -y" }, "dependencies": { @@ -85,14 +85,14 @@ "@babel/preset-env": "^7.0.0", "@jupyterlab/builder": "^4", "@jupyterlab/testutils": "^4", - "@types/jest": "^26.0.0", + "@types/jest": "^29", "@types/react-syntax-highlighter": "^15.5.6", "@typescript-eslint/eslint-plugin": "^4.8.1", "@typescript-eslint/parser": "^4.8.1", "eslint": "^7.14.0", "eslint-config-prettier": "^6.15.0", "eslint-plugin-prettier": "^3.1.4", - "jest": "^26.0.0", + "jest": "^29", "mkdirp": "^1.0.3", "npm-run-all": "^4.1.5", "prettier": "^2.1.1", @@ -102,8 +102,8 @@ "stylelint-config-recommended": "^6.0.0", "stylelint-config-standard": "~24.0.0", "stylelint-prettier": "^2.0.0", - "ts-jest": "^26.0.0", - "typescript": "~4.1.3", + "ts-jest": "^29", + "typescript": "~4.3.0", "y-protocols": "^1.0.5" }, "sideEffects": [ diff --git a/packages/jupyter-ai/pyproject.toml b/packages/jupyter-ai/pyproject.toml index 71ae54ff4..6735f9c2e 100644 --- a/packages/jupyter-ai/pyproject.toml +++ b/packages/jupyter-ai/pyproject.toml @@ -34,6 +34,8 @@ dependencies = [ "dask[distributed]", "faiss-cpu", # Not distributed by official repo "typing_extensions>=4.5.0", + "traitlets>=5.0", + "deepmerge>=1.0" ] dynamic = ["version", "description", "authors", "urls", "keywords"] @@ -48,7 +50,8 @@ test = [ "pytest", "pytest-asyncio", "pytest-cov", - "pytest-tornasync" + "pytest-tornasync", + "syrupy~=4.0.8" ] dev = [ diff --git a/packages/jupyter-ai/src/components/chat-settings.tsx b/packages/jupyter-ai/src/components/chat-settings.tsx index deb013118..773e519b4 100644 --- a/packages/jupyter-ai/src/components/chat-settings.tsx +++ b/packages/jupyter-ai/src/components/chat-settings.tsx @@ -16,234 +16,164 @@ import { import { Select } from './select'; import { AiService } from '../handler'; import { ModelFields } from './settings/model-fields'; - -enum ChatSettingsState { - // chat settings is making initial fetches - Loading, - // chat settings is ready (happy path) - Ready, - // chat settings failed to make initial fetches - FetchError, - // chat settings failed to submit the save request - SubmitError, - // chat settings successfully submitted the save request - Success -} - -function getProviderId(globalModelId: string | null) { - if (!globalModelId) { - return null; - } - - return globalModelId.split(':')[0]; -} - -function getLocalModelId(globalModelId: string | null) { - if (!globalModelId) { - return null; - } - - const components = globalModelId.split(':'); - return components[components.length - 1]; -} - -function getProvider( - globalModelId: string | null, - providers: AiService.ListProvidersResponse -) { - const providerId = getProviderId(globalModelId); - const provider = providers.providers.find(p => p.id === providerId); - return provider; -} - -function fromRegistryProvider( - globalModelId: string | null, - providers: AiService.ListProvidersResponse -) { - return getProvider(globalModelId, providers)?.registry ?? false; -} +import { ServerInfoState, useServerInfo } from './settings/use-server-info'; +import { ExistingApiKeys } from './settings/existing-api-keys'; +import { minifyUpdate } from './settings/minify'; +import { useStackingAlert } from './mui-extras/stacking-alert'; /** * Component that returns the settings view in the chat panel. - * - * Implementation notes: - * - `config` is the configuration last fetched from the backend. `inputConfig` - * is the editable copy of that object that stores all user input state. - * - * - `inputConfig.model_provider_id` reflects the global model ID only if the - * provider is not a registry provider. Otherwise, it is set to - * `:*`. */ export function ChatSettings(): JSX.Element { - const [state, setState] = useState( - ChatSettingsState.Loading - ); - // error message from initial fetch - const [fetchEmsg, setFetchEmsg] = useState(); - // state fetched on initial render - const [config, setConfig] = useState(); - const [lmProviders, setLmProviders] = - useState(); - const [emProviders, setEmProviders] = - useState(); - - // user inputs - const [inputConfig, setInputConfig] = useState({ - model_provider_id: null, - embeddings_provider_id: null, - api_keys: {}, - send_with_shift_enter: null, - fields: {} - }); + const server = useServerInfo(); - // whether the form is currently saving - const [saving, setSaving] = useState(false); - // error message from submission - const [saveEmsg, setSaveEmsg] = useState(); + // initialize alert helper + const alert = useStackingAlert(); + const apiKeysAlert = useStackingAlert(); - // whether to show the language model's local model ID input + // user inputs + const [lmProvider, setLmProvider] = + useState(null); const [showLmLocalId, setShowLmLocalId] = useState(false); - const [lmLocalId, setLmLocalId] = useState('*'); - - // provider of the currently selected language model - const lmProvider = useMemo(() => { - if (!inputConfig.model_provider_id || !lmProviders) { - return; + const [lmLocalId, setLmLocalId] = useState(''); + const lmGlobalId = useMemo(() => { + if (!lmProvider) { + return null; } - return getProvider(inputConfig.model_provider_id, lmProviders); - }, [inputConfig.model_provider_id, lmProviders]); + return lmProvider.id + ':' + lmLocalId; + }, [lmProvider, lmLocalId]); - // global model ID of the currently selected language model - const lmGlobalId = useMemo(() => { - if (!inputConfig.model_provider_id || !lmProvider) { + const [emGlobalId, setEmGlobalId] = useState(null); + const emProvider = useMemo(() => { + if (emGlobalId === null || server.state !== ServerInfoState.Ready) { return null; } - return lmProvider?.registry - ? `${lmProvider.id}:${lmLocalId}` - : inputConfig.model_provider_id; - }, [inputConfig.model_provider_id, lmProvider, lmProviders, lmLocalId]); + return getProvider(emGlobalId, server.emProviders); + }, [emGlobalId, server]); + + const [apiKeys, setApiKeys] = useState>({}); + const [sendWse, setSendWse] = useState(false); + const [fields, setFields] = useState>({}); + + // whether the form is currently saving + const [saving, setSaving] = useState(false); /** - * Effect: call APIs on initial render + * Effect: initialize inputs after fetching server info. */ useEffect(() => { - async function getConfig() { - try { - const [config, lmProviders, emProviders] = await Promise.all([ - AiService.getConfig(), - AiService.listLmProviders(), - AiService.listEmProviders() - ]); - setConfig(config); - setLmProviders(lmProviders); - setEmProviders(emProviders); - - // if a model from a registry provider was previously selected, store - // the local model ID in a separate text field. - if (fromRegistryProvider(config.model_provider_id, lmProviders)) { - setShowLmLocalId(true); - const lmPid = getProviderId(config.model_provider_id); - setLmLocalId(getLocalModelId(config.model_provider_id) as string); - setInputConfig({ - ...config, - model_provider_id: `${lmPid}:*` - }); - } else { - setInputConfig(config); - } + if (server.state !== ServerInfoState.Ready) { + return; + } - setState(ChatSettingsState.Ready); - } catch (e) { - console.error(e); - if (e instanceof Error) { - setFetchEmsg(e.message); - } - setState(ChatSettingsState.FetchError); - } + setLmLocalId(server.lmLocalId); + setEmGlobalId(server.config.embeddings_provider_id); + setSendWse(server.config.send_with_shift_enter); + if (server.lmProvider?.registry) { + setShowLmLocalId(true); } - getConfig(); - }, []); + setLmProvider(server.lmProvider); + }, [server]); /** - * Effect: re-initialize API keys object whenever the selected LM/EM changes. + * Effect: re-initialize apiKeys object whenever the selected LM/EM changes. + * Properties with a value of '' indicate necessary user input. */ useEffect(() => { - const selectedLmpId = getProviderId(inputConfig.model_provider_id); - const selectedEmpId = getProviderId(inputConfig.embeddings_provider_id); - const lmp = lmProviders?.providers.find( - provider => provider.id === selectedLmpId - ); - const emp = emProviders?.providers.find( - provider => provider.id === selectedEmpId - ); - const newApiKeys: Record = {}; + if (server.state !== ServerInfoState.Ready) { + return; + } - if (lmp?.auth_strategy && lmp.auth_strategy.type === 'env') { - newApiKeys[lmp.auth_strategy.name] = - config?.api_keys[lmp.auth_strategy.name] || ''; + const newApiKeys: Record = {}; + const lmAuth = lmProvider?.auth_strategy; + const emAuth = emProvider?.auth_strategy; + if ( + lmAuth?.type === 'env' && + !server.config.api_keys.includes(lmAuth.name) + ) { + newApiKeys[lmAuth.name] = ''; } - if (emp?.auth_strategy && emp.auth_strategy.type === 'env') { - newApiKeys[emp.auth_strategy.name] = - config?.api_keys[emp.auth_strategy.name] || ''; + if ( + emAuth?.type === 'env' && + !server.config.api_keys.includes(emAuth.name) + ) { + newApiKeys[emAuth.name] = ''; } - setInputConfig(inputConfig => ({ - ...inputConfig, - api_keys: { ...config?.api_keys, ...newApiKeys } - })); - }, [inputConfig.model_provider_id, inputConfig.embeddings_provider_id]); + setApiKeys(newApiKeys); + }, [lmProvider, emProvider, server]); - const handleSave = async () => { - const inputConfigCopy: AiService.Config = { - ...inputConfig, - model_provider_id: lmGlobalId, - api_keys: { ...inputConfig.api_keys }, - send_with_shift_enter: inputConfig.send_with_shift_enter ?? true - }; - - // delete any empty api keys - for (const apiKey in inputConfigCopy.api_keys) { - if (inputConfigCopy.api_keys[apiKey] === '') { - delete inputConfigCopy.api_keys[apiKey]; - } + /** + * Effect: re-initialize fields object whenever the selected LM changes. + */ + useEffect(() => { + if (server.state !== ServerInfoState.Ready || !lmGlobalId) { + return; } + const currFields: Record = + server.config.fields?.[lmGlobalId] ?? {}; + setFields(currFields); + }, [server, lmProvider]); + + const handleSave = async () => { // compress fields with JSON values - for (const gmid in inputConfigCopy.fields) { - for (const fieldKey in inputConfigCopy.fields[gmid]) { - const fieldVal = inputConfigCopy.fields[gmid][fieldKey]; - if (typeof fieldVal !== 'string') { - continue; - } + if (server.state !== ServerInfoState.Ready) { + return; + } - try { - const parsedFieldVal = JSON.parse(fieldVal); - const compressedFieldVal = JSON.stringify(parsedFieldVal); - inputConfigCopy.fields[gmid][fieldKey] = compressedFieldVal; - } catch (e) { - continue; - } + for (const fieldKey in fields) { + const fieldVal = fields[fieldKey]; + if (typeof fieldVal !== 'string' || !fieldVal.trim().startsWith('{')) { + continue; + } + + try { + const parsedFieldVal = JSON.parse(fieldVal); + const compressedFieldVal = JSON.stringify(parsedFieldVal); + fields[fieldKey] = compressedFieldVal; + } catch (e) { + continue; } } + let updateRequest: AiService.UpdateConfigRequest = { + model_provider_id: lmGlobalId, + embeddings_provider_id: emGlobalId, + api_keys: apiKeys, + ...(lmGlobalId && { + fields: { + [lmGlobalId]: fields + } + }), + send_with_shift_enter: sendWse + }; + updateRequest = minifyUpdate(server.config, updateRequest); + updateRequest.last_read = server.config.last_read; + setSaving(true); try { - await AiService.updateConfig(inputConfigCopy); + await apiKeysAlert.clear(); + await AiService.updateConfig(updateRequest); } catch (e) { console.error(e); - if (e instanceof Error) { - setSaveEmsg(e.message); - } - setState(ChatSettingsState.SubmitError); + const msg = + e instanceof Error || typeof e === 'string' + ? e.toString() + : 'An unknown error occurred. Check the console for more details.'; + alert.show('error', msg); + return; + } finally { + setSaving(false); } - setState(ChatSettingsState.Success); - setSaving(false); + await server.refetchAll(); + alert.show('success', 'Settings saved successfully.'); }; - if (state === ChatSettingsState.Loading) { + if (server.state === ServerInfoState.Loading) { return ( - {fetchEmsg - ? `An error occurred. Error details:\n\n${fetchEmsg}` - : 'An unknown error occurred. Check the console for more details.'} + {server.error || + 'An unknown error occurred. Check the console for more details.'} ); @@ -287,48 +211,44 @@ export function ChatSettings(): JSX.Element { return ( .MuiAlert-root': { marginBottom: 2 }, + '& .MuiAlert-root': { + marginTop: 2 + }, overflowY: 'auto' }} > - {state === ChatSettingsState.SubmitError && ( - - {saveEmsg - ? `An error occurred. Error details:\n\n${saveEmsg}` - : 'An unknown error occurred. Check the console for more details.'} - - )} - {state === ChatSettingsState.Success && ( - Settings saved successfully. - )} - {/* Language model section */}

Language model

- setInputConfig(inputConfig => ({ - ...inputConfig, - embeddings_provider_id: e.target.value - })) - } + onChange={e => { + const emGid = e.target.value === 'null' ? null : e.target.value; + setEmGlobalId(emGid); + }} MenuProps={{ sx: { maxHeight: '50%', minHeight: 400 } }} > None - {emProviders.providers.map(emp => + {server.emProviders.providers.map(emp => emp.models .filter(em => em !== '*') // TODO: support registry providers .map(em => ( @@ -380,26 +297,28 @@ export function ChatSettings(): JSX.Element { {/* API Keys section */}

API Keys

- {Object.entries(inputConfig.api_keys).map( - ([apiKey, apiKeyValue], idx) => ( - - setInputConfig(inputConfig => ({ - ...inputConfig, - api_keys: { - ...inputConfig.api_keys, - [apiKey]: e.target.value - } - })) - } - /> - ) - )} + {/* API key inputs for newly-used providers */} + {Object.entries(apiKeys).map(([apiKeyName, apiKeyValue], idx) => ( + + setApiKeys(apiKeys => ({ + ...apiKeys, + [apiKeyName]: e.target.value + })) + } + /> + ))} + {/* Pre-existing API keys */} + {/* Input */}

Input

@@ -409,19 +328,11 @@ export function ChatSettings(): JSX.Element { - setInputConfig(inputConfig => { - return { - ...inputConfig, - send_with_shift_enter: - (e.target as HTMLInputElement).value === 'newline' - }; - }) - } + onChange={e => { + setSendWse(e.target.value === 'newline'); + }} >
+ {alert.jsx} ); } + +function getProviderId(globalModelId: string) { + if (!globalModelId) { + return null; + } + + return globalModelId.split(':')[0]; +} + +function getModelLocalId(globalModelId: string) { + if (!globalModelId) { + return null; + } + + const components = globalModelId.split(':'); + return components[components.length - 1]; +} + +function getProvider( + globalModelId: string, + providers: AiService.ListProvidersResponse +): AiService.ListProvidersEntry | null { + const providerId = getProviderId(globalModelId); + const provider = providers.providers.find(p => p.id === providerId); + return provider ?? null; +} diff --git a/packages/jupyter-ai/src/components/mui-extras/async-icon-button.tsx b/packages/jupyter-ai/src/components/mui-extras/async-icon-button.tsx new file mode 100644 index 000000000..5de6b3913 --- /dev/null +++ b/packages/jupyter-ai/src/components/mui-extras/async-icon-button.tsx @@ -0,0 +1,89 @@ +import React, { useMemo, useState } from 'react'; +import { Box, CircularProgress, IconButton } from '@mui/material'; +import { ContrastingTooltip } from './contrasting-tooltip'; + +type AsyncIconButtonProps = { + onClick: () => Promise; + onError: (emsg: string) => unknown; + onSuccess: () => unknown; + children: JSX.Element; + onMouseDown?: React.MouseEventHandler; + /** + * Whether this component should require confirmation from the user before + * calling `props.onClick()`. This is only read on initial render. + */ + confirm?: boolean; +}; + +/** + * A MUI IconButton that indicates whether the click handler is resolving via a + * circular spinner around the IconButton. Requests user confirmation when + * `confirm` is set to `true`. + */ +export function AsyncIconButton(props: AsyncIconButtonProps): JSX.Element { + const [loading, setLoading] = useState(false); + const [showConfirm, setShowConfirm] = useState(false); + const shouldConfirm = useMemo(() => !!props.confirm, []); + + async function handleClick() { + if (shouldConfirm && !showConfirm) { + setShowConfirm(true); + return; + } + + setLoading(true); + let thrown = false; + try { + await props.onClick(); + } catch (e: unknown) { + thrown = true; + if (e instanceof Error) { + props.onError(e.toString()); + } else { + // this should never happen. + // if this happens, it means the thrown value was not of type `Error`. + props.onError('Unknown error occurred.'); + } + } + setLoading(false); + if (!thrown) { + props.onSuccess(); + } + } + + return ( + + setShowConfirm(false)} + arrow + placement="top" + > + + {props.children} + + + {loading && ( + + )} + + ); +} diff --git a/packages/jupyter-ai/src/components/mui-extras/contrasting-tooltip.tsx b/packages/jupyter-ai/src/components/mui-extras/contrasting-tooltip.tsx new file mode 100644 index 000000000..21f5a86d6 --- /dev/null +++ b/packages/jupyter-ai/src/components/mui-extras/contrasting-tooltip.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { styled, Tooltip, TooltipProps, tooltipClasses } from '@mui/material'; + +/** + * A restyled MUI tooltip component that is dark by default to improve contrast + * against JupyterLab's default light theme. TODO: support dark themes. + */ +export const ContrastingTooltip = styled( + ({ className, ...props }: TooltipProps) => ( + + ) +)(({ theme }) => ({ + [`& .${tooltipClasses.tooltip}`]: { + backgroundColor: theme.palette.common.black, + color: theme.palette.common.white, + boxShadow: theme.shadows[1], + fontSize: 11 + }, + [`& .${tooltipClasses.arrow}`]: { + color: theme.palette.common.black + } +})); diff --git a/packages/jupyter-ai/src/components/mui-extras/stacking-alert.tsx b/packages/jupyter-ai/src/components/mui-extras/stacking-alert.tsx new file mode 100644 index 000000000..2fe438d12 --- /dev/null +++ b/packages/jupyter-ai/src/components/mui-extras/stacking-alert.tsx @@ -0,0 +1,100 @@ +import React, { useState, useMemo, useCallback } from 'react'; +import { Alert, AlertColor, Collapse } from '@mui/material'; + +export type StackingAlert = { + /** + * A function that triggers an alert. Successive alerts are indicated in the + * JSX element. + * @param alertType Type of alert. + * @param msg Message contained within the alert. + * @returns + */ + show: (alertType: AlertColor, msg: string | Error) => void; + /** + * The Alert JSX element that should be rendered by the consumer. + * This will be `null` if no alerts were triggered. + */ + jsx: JSX.Element | null; + /** + * An async function that closes the alert, and returns a Promise that + * resolves when the onClose animation is completed. + */ + clear: () => void | Promise; +}; + +/** + * Hook that returns a function to trigger an alert, and a corresponding alert + * JSX element for the consumer to render. The number of successive identical + * alerts `X` is indicated in the element via the suffix "(X)". + */ +export function useStackingAlert(): StackingAlert { + const [type, setType] = useState(null); + const [msg, setMsg] = useState(''); + const [repeatCount, setRepeatCount] = useState(0); + const [expand, setExpand] = useState(false); + const [exitPromise, setExitPromise] = useState>(); + const [exitPromiseResolver, setExitPromiseResolver] = useState<() => void>(); + + const showAlert = useCallback( + (nextType: AlertColor, _nextMsg: string | Error) => { + // if the alert is identical to the previous alert, increment the + // `repeatCount` indicator. + const nextMsg = _nextMsg.toString(); + if (nextType === type && nextMsg === msg) { + setRepeatCount(currCount => currCount + 1); + return; + } + + if (type === null) { + // if this alert is being shown for the first time, initialize the + // exitPromise so we can await it on `clear()`. + setExitPromise( + new Promise(res => { + setExitPromiseResolver(() => res); + }) + ); + } + + setType(nextType); + setMsg(nextMsg); + setRepeatCount(0); + setExpand(true); + }, + [msg, type] + ); + + const alertJsx = useMemo( + () => ( + { + exitPromiseResolver?.(); + // only clear the alert after the Collapse exits, otherwise the alert + // disappears without any animation. + setType(null); + setMsg(''); + setRepeatCount(0); + }} + timeout={200} + > + {type !== null && ( + + {msg + (repeatCount ? ` (${repeatCount})` : '')} + + )} + + ), + [msg, repeatCount, type, expand, exitPromiseResolver] + ); + + const clearAlert = useCallback(() => { + setExpand(false); + return exitPromise; + }, [expand, exitPromise]); + + return { + show: showAlert, + jsx: alertJsx, + clear: clearAlert + }; +} diff --git a/packages/jupyter-ai/src/components/settings/__tests__/chat-settings.spec.ts b/packages/jupyter-ai/src/components/settings/__tests__/chat-settings.spec.ts new file mode 100644 index 000000000..edb2d3332 --- /dev/null +++ b/packages/jupyter-ai/src/components/settings/__tests__/chat-settings.spec.ts @@ -0,0 +1,63 @@ +import { minifyPatchObject } from '../minify'; + +const COMPLEX_OBJECT = { + primitive: 0, + array: ['a'], + object: { nested: { field: 0 } } +}; + +describe('minifyPatchObject', () => { + test('returns empty object if patch is identical', () => { + const obj = COMPLEX_OBJECT; + const patch = JSON.parse(JSON.stringify(obj)); + + expect(minifyPatchObject(obj, patch)).toEqual({}); + }); + + test('returns empty object if patch is empty', () => { + expect(minifyPatchObject(COMPLEX_OBJECT, {})).toEqual({}); + }); + + test('returns patch if object is empty', () => { + expect(minifyPatchObject({}, COMPLEX_OBJECT)).toEqual(COMPLEX_OBJECT); + }); + + test('should remove unchanged props from patch', () => { + const obj = { + unchanged: 'foo', + changed: 'bar', + nested: { + unchanged: 'foo', + changed: 'bar' + } + }; + const patch = { + unchanged: 'foo', + changed: 'baz', + nested: { + unchanged: 'foo', + changed: 'baz' + } + }; + + expect(minifyPatchObject(obj, patch)).toEqual({ + changed: 'baz', + nested: { + changed: 'baz' + } + }); + }); + + test('defers to patch object when property types mismatch', () => { + const obj = { + api_keys: ['ANTHROPIC_API_KEY'] + }; + const patch = { + api_keys: { + OPENAI_API_KEY: 'foobar' + } + }; + + expect(minifyPatchObject(obj, patch)).toEqual(patch); + }); +}); diff --git a/packages/jupyter-ai/src/components/settings/existing-api-keys.tsx b/packages/jupyter-ai/src/components/settings/existing-api-keys.tsx new file mode 100644 index 000000000..468f26796 --- /dev/null +++ b/packages/jupyter-ai/src/components/settings/existing-api-keys.tsx @@ -0,0 +1,234 @@ +import React, { useEffect, useCallback, useRef, useState } from 'react'; +import { + Box, + IconButton, + Typography, + TextField, + InputAdornment +} from '@mui/material'; +import { + Edit, + DeleteOutline, + Cancel, + Check, + Visibility, + VisibilityOff +} from '@mui/icons-material'; +import { AsyncIconButton } from '../mui-extras/async-icon-button'; + +import { AiService } from '../../handler'; +import { StackingAlert } from '../mui-extras/stacking-alert'; + +export type ExistingApiKeysProps = { + alert: StackingAlert; + apiKeys: string[]; + onSuccess: () => unknown; +}; + +/** + * Component that renders a list of existing API keys. Each API key is rendered + * by a unique `ExistingApiKey` component. + */ +export function ExistingApiKeys(props: ExistingApiKeysProps): JSX.Element { + // current editable API key name, if any. + const [editableApiKey, setEditableApiKey] = useState(null); + + return ( + .MuiBox-root:not(:first-child)': { + marginTop: -2 + } + }} + > + {props.apiKeys.map(apiKey => ( + + ))} + {props.alert.jsx} + + ); +} + +type ExistingApiKeyProps = { + alert: StackingAlert; + apiKey: string; + editable: boolean; + setEditable: React.Dispatch>; + onSuccess: () => unknown; +}; + +/** + * Component that renders a single existing API key specified by `props.apiKey`. + * Includes actions for editing and deleting the API key. + */ +function ExistingApiKey(props: ExistingApiKeyProps) { + const [input, setInput] = useState(''); + const [inputVisible, setInputVisible] = useState(false); + const [error, setError] = useState(false); + const inputRef = useRef(); + + /** + * Effect: Select the input after `editable` is set to `true`. This needs to + * be done in an effect because the TextField needs to be rendered with + * `disabled=false` first. When `editable` is set to `false`, reset any + * input-related state. + */ + useEffect(() => { + if (props.editable) { + inputRef.current?.focus(); + } else { + setInput(''); + setInputVisible(false); + setError(false); + } + }, [props.editable]); + + const onEditIntent = useCallback(() => { + props.setEditable(props.apiKey); + }, []); + + const onDelete = useCallback(() => { + return AiService.deleteApiKey(props.apiKey); + }, []); + + const toggleInputVisibility = useCallback(() => { + setInputVisible(visible => !visible); + }, []); + + const onEditCancel = useCallback(() => { + props.setEditable(null); + }, []); + + const onEditSubmit = useCallback(() => { + return AiService.updateConfig({ + api_keys: { [props.apiKey]: input } + }); + }, [input]); + + const onError = useCallback( + emsg => { + props.alert.show('error', emsg); + }, + [props.alert] + ); + + const validateInput = useCallback(() => { + if (!props.editable) { + return; + } + + setError(!input); + }, [props.editable, input]); + + const onEditSuccess = useCallback(() => { + props.setEditable(null); + props.alert.show('success', 'API key updated successfully.'); + props.onSuccess(); + }, [props.alert, props.onSuccess]); + + const onDeleteSuccess = useCallback(() => { + props.alert.show('success', 'API key deleted successfully.'); + props.onSuccess(); + }, [props.alert, props.onSuccess]); + + return ( + + setInput(e.target.value)} + disabled={!props.editable} + inputRef={inputRef} + // validation props + onBlur={validateInput} + error={error} + helperText={'API key value must not be empty'} + FormHelperTextProps={{ + sx: { + visibility: error ? 'unset' : 'hidden', + margin: 0, + whiteSpace: 'nowrap' + } + }} + // style props + size="small" + variant="standard" + type={inputVisible ? 'text' : 'password'} + label={ + +
{props.apiKey}
+
+ } + InputProps={{ + endAdornment: props.editable && ( + + e.preventDefault()} + > + {inputVisible ? : } + + + ) + }} + sx={{ + flexGrow: 1, + margin: 0, + '& .MuiInputBase-input': { + padding: 0, + paddingBottom: 1 + } + }} + /> + + {props.editable ? ( + // 16px margin top - 5px padding + <> + e.preventDefault()} + > + + + e.preventDefault()} + confirm={true} + > + + + + ) : ( + <> + + + + + + + + )} + +
+ ); +} diff --git a/packages/jupyter-ai/src/components/settings/minify.ts b/packages/jupyter-ai/src/components/settings/minify.ts new file mode 100644 index 000000000..3de096ec0 --- /dev/null +++ b/packages/jupyter-ai/src/components/settings/minify.ts @@ -0,0 +1,56 @@ +import { AiService } from '../../handler'; + +/** + * Function that minimizes the `UpdateConfigRequest` object prior to submission. + * Removes properties with values identical to those specified in the server + * configuration. + */ +export function minifyUpdate( + config: AiService.DescribeConfigResponse, + update: AiService.UpdateConfigRequest +): AiService.UpdateConfigRequest { + return minifyPatchObject(config, update) as AiService.UpdateConfigRequest; +} + +/** + * Function that removes all properties from `patch` that have identical values + * to `obj` recursively. + */ +export function minifyPatchObject( + obj: Record, + patch: Record +): Record { + const diffObj: Record = {}; + for (const key in patch) { + if (!(key in obj) || typeof obj[key] !== typeof patch[key]) { + // if key is not present in oldObj, or if the value types do not match, + // use the value of `patch`. + diffObj[key] = patch[key]; + continue; + } + + const objVal = obj[key]; + const patchVal = patch[key]; + if (Array.isArray(objVal) && Array.isArray(patchVal)) { + // if objects are both arrays but are not equal, then use the value + const areNotEqual = + objVal.length !== patchVal.length || + !objVal.every((objVal_i, i) => objVal_i === patchVal[i]); + if (areNotEqual) { + diffObj[key] = patchVal; + } + } else if (typeof patchVal === 'object') { + // if the value is an object, run `diffObjects` recursively. + const childPatch = minifyPatchObject(objVal, patchVal); + const isNonEmpty = !!Object.keys(childPatch)?.length; + if (isNonEmpty) { + diffObj[key] = childPatch; + } + } else if (objVal !== patchVal) { + // otherwise, use the value of `patch` only if it differs. + diffObj[key] = patchVal; + } + } + + return diffObj; +} diff --git a/packages/jupyter-ai/src/components/settings/model-fields.tsx b/packages/jupyter-ai/src/components/settings/model-fields.tsx index bc71c3d96..aa580d1f4 100644 --- a/packages/jupyter-ai/src/components/settings/model-fields.tsx +++ b/packages/jupyter-ai/src/components/settings/model-fields.tsx @@ -3,17 +3,14 @@ import { AiService } from '../../handler'; import { TextField } from '@mui/material'; export type ModelFieldProps = { - /** - * The global model ID to which these fields belong. - */ - gmid: string; field: AiService.Field; - config: AiService.Config; - setConfig: (newConfig: AiService.Config) => unknown; + values: Record; + onChange: (newValues: Record) => unknown; }; export function ModelField(props: ModelFieldProps): JSX.Element { const [errorMessage, setErrorMessage] = useState(null); + const value = props.values?.[props.field.key]; function handleChange( e: React.ChangeEvent @@ -41,15 +38,9 @@ export function ModelField(props: ModelFieldProps): JSX.Element { break; } - props.setConfig({ - ...props.config, - fields: { - ...props.config.fields, - [props.gmid]: { - ...props.config.fields[props.gmid], - [props.field.key]: e.target.value - } - } + props.onChange({ + ...props.values, + [props.field.key]: e.target.value }); } @@ -57,7 +48,7 @@ export function ModelField(props: ModelFieldProps): JSX.Element { return ( & { fields?: AiService.Field[]; + values: Record; + onChange: (newValues: Record) => unknown; }; export function ModelFields(props: ModelFieldsProps): JSX.Element | null { @@ -108,7 +101,13 @@ export function ModelFields(props: ModelFieldsProps): JSX.Element | null { return ( <> {props.fields.map((field, idx) => ( - + ))} ); diff --git a/packages/jupyter-ai/src/components/settings/use-server-info.ts b/packages/jupyter-ai/src/components/settings/use-server-info.ts new file mode 100644 index 000000000..87c54c474 --- /dev/null +++ b/packages/jupyter-ai/src/components/settings/use-server-info.ts @@ -0,0 +1,159 @@ +import { useState, useEffect, useMemo, useCallback } from 'react'; +import { AiService } from '../../handler'; + +type ServerInfoProperties = { + config: AiService.DescribeConfigResponse; + lmProviders: AiService.ListProvidersResponse; + emProviders: AiService.ListProvidersResponse; + lmProvider: AiService.ListProvidersEntry | null; + emProvider: AiService.ListProvidersEntry | null; + lmLocalId: string; +}; + +type ServerInfoMethods = { + refetchAll: () => Promise; + refetchApiKeys: () => Promise; +}; + +export enum ServerInfoState { + /** + * Server info is being fetched. + */ + Loading, + /** + * Unable to retrieve server info. + */ + Error, + /** + * Server info was loaded successfully. + */ + Ready +} + +type ServerInfoLoading = { state: ServerInfoState.Loading }; +type ServerInfoError = { + state: ServerInfoState.Error; + error: string; +}; +type ServerInfoReady = { state: ServerInfoState.Ready } & ServerInfoProperties & + ServerInfoMethods; + +type ServerInfo = ServerInfoLoading | ServerInfoError | ServerInfoReady; + +/** + * A hook that fetches the current configuration and provider lists from the + * server. Returns a `ServerInfo` object that includes methods. + */ +export function useServerInfo(): ServerInfo { + const [state, setState] = useState(ServerInfoState.Loading); + const [serverInfoProps, setServerInfoProps] = + useState(); + const [error, setError] = useState(''); + + const fetchServerInfo = useCallback(async () => { + try { + const [config, lmProviders, emProviders] = await Promise.all([ + AiService.getConfig(), + AiService.listLmProviders(), + AiService.listEmProviders() + ]); + const lmGid = config.model_provider_id; + const emGid = config.embeddings_provider_id; + const lmProvider = + lmGid === null ? null : getProvider(lmGid, lmProviders); + const emProvider = + emGid === null ? null : getProvider(emGid, emProviders); + const lmLocalId = lmGid === null ? '' : getLocalId(lmGid); + setServerInfoProps({ + config, + lmProviders, + emProviders, + lmProvider, + emProvider, + lmLocalId + }); + + setState(ServerInfoState.Ready); + } catch (e) { + console.error(e); + if (e instanceof Error) { + setError(e.toString()); + } else { + setError('An unknown error occurred.'); + } + setState(ServerInfoState.Error); + } + }, []); + + const refetchApiKeys = useCallback(async () => { + if (!serverInfoProps) { + // this should never happen. + return; + } + + const config = await AiService.getConfig(); + setServerInfoProps({ + ...serverInfoProps, + config: { + ...serverInfoProps.config, + api_keys: config.api_keys, + last_read: config.last_read + } + }); + }, [serverInfoProps]); + + /** + * Effect: fetch server info on initial render + */ + useEffect(() => { + fetchServerInfo(); + }, []); + + return useMemo(() => { + if (state === ServerInfoState.Loading) { + return { state }; + } + + if (state === ServerInfoState.Error || !serverInfoProps) { + return { state: ServerInfoState.Error, error }; + } + + return { + state, + ...serverInfoProps, + refetchAll: fetchServerInfo, + refetchApiKeys + }; + }, [state, serverInfoProps, error, refetchApiKeys]); +} + +function getProvider( + gid: string, + providers: AiService.ListProvidersResponse +): AiService.ListProvidersEntry | null { + const providerId = getProviderId(gid); + const provider = providers.providers.find(p => p.id === providerId); + return provider ?? null; +} + +function getProviderId(gid: string) { + if (!gid) { + return null; + } + + const components = gid.split(':'); + if (components.length < 2) { + return null; + } + + return components[0]; +} + +function getLocalId(gid: string) { + const components = gid.split(':'); + if (components.length < 2) { + return ''; + } + + return components[1]; +} diff --git a/packages/jupyter-ai/src/components/settings/validator.ts b/packages/jupyter-ai/src/components/settings/validator.ts new file mode 100644 index 000000000..3d420f5c1 --- /dev/null +++ b/packages/jupyter-ai/src/components/settings/validator.ts @@ -0,0 +1,8 @@ +import { AiService } from '../../handler'; + +export class SettingsValidator { + constructor( + protected lmProviders: AiService.ListProvidersResponse, + protected emProviders: AiService.ListProvidersResponse + ) {} +} diff --git a/packages/jupyter-ai/src/handler.ts b/packages/jupyter-ai/src/handler.ts index 9f18b40d1..bbd703a5c 100644 --- a/packages/jupyter-ai/src/handler.ts +++ b/packages/jupyter-ai/src/handler.ts @@ -104,20 +104,26 @@ export namespace AiService { messages: ChatMessage[]; }; - export type Config = { + export type DescribeConfigResponse = { model_provider_id: string | null; embeddings_provider_id: string | null; - api_keys: Record; - send_with_shift_enter: boolean | null; + api_keys: string[]; + send_with_shift_enter: boolean; fields: Record>; + last_read: number; }; - export type GetConfigResponse = Config; - - export type UpdateConfigRequest = Config; + export type UpdateConfigRequest = { + model_provider_id?: string | null; + embeddings_provider_id?: string | null; + api_keys?: Record; + send_with_shift_enter?: boolean; + fields?: Record>; + last_read?: number; + }; - export async function getConfig(): Promise { - return requestAPI('config'); + export async function getConfig(): Promise { + return requestAPI('config'); } export type EnvAuthStrategy = { @@ -183,4 +189,10 @@ export namespace AiService { body: JSON.stringify(config) }); } + + export async function deleteApiKey(keyName: string): Promise { + return requestAPI(`api_keys/${keyName}`, { + method: 'DELETE' + }); + } } diff --git a/packages/jupyter-ai/tsconfig.test.json b/packages/jupyter-ai/tsconfig.test.json new file mode 100644 index 000000000..063b5f10c --- /dev/null +++ b/packages/jupyter-ai/tsconfig.test.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "noUnusedLocals": false + } +} diff --git a/yarn.lock b/yarn.lock index 9eada2fb9..435bbde51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -47,7 +47,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.0.0, @babel/core@npm:^7.1.0, @babel/core@npm:^7.10.2, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.7.5": +"@babel/core@npm:^7.0.0, @babel/core@npm:^7.10.2, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3": version: 7.22.9 resolution: "@babel/core@npm:7.22.9" dependencies: @@ -1342,7 +1342,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.1.0, @babel/traverse@npm:^7.22.6, @babel/traverse@npm:^7.22.8": +"@babel/traverse@npm:^7.22.6, @babel/traverse@npm:^7.22.8": version: 7.22.8 resolution: "@babel/traverse@npm:7.22.8" dependencies: @@ -1437,18 +1437,6 @@ __metadata: languageName: node linkType: hard -"@cnakazawa/watch@npm:^1.0.3": - version: 1.0.4 - resolution: "@cnakazawa/watch@npm:1.0.4" - dependencies: - exec-sh: ^0.3.2 - minimist: ^1.2.0 - bin: - watch: cli.js - checksum: 88f395ca0af2f3c0665b8ce7bb29e83647ec5d141e8735712aeeee4117081555436712966b6957aa1c461f6f826a4d23b0034e379c443a10e919f81c8748bf29 - languageName: node - linkType: hard - "@codemirror/autocomplete@npm:^6.0.0, @codemirror/autocomplete@npm:^6.3.2, @codemirror/autocomplete@npm:^6.5.1, @codemirror/autocomplete@npm:^6.7.1": version: 6.9.0 resolution: "@codemirror/autocomplete@npm:6.9.0" @@ -1974,20 +1962,6 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/console@npm:26.6.2" - dependencies: - "@jest/types": ^26.6.2 - "@types/node": "*" - chalk: ^4.0.0 - jest-message-util: ^26.6.2 - jest-util: ^26.6.2 - slash: ^3.0.0 - checksum: 69a9ca6ba357d7634fd537e3b87c64369865ffb59f57fe6661223088bd62273d0c1d660fefce3625a427f42a37d32590f6b291e1295ea6d6b7cb31ddae36a737 - languageName: node - linkType: hard - "@jest/console@npm:^29.6.1": version: 29.6.1 resolution: "@jest/console@npm:29.6.1" @@ -2002,39 +1976,17 @@ __metadata: languageName: node linkType: hard -"@jest/core@npm:^26.6.3": - version: 26.6.3 - resolution: "@jest/core@npm:26.6.3" +"@jest/console@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/console@npm:29.6.2" dependencies: - "@jest/console": ^26.6.2 - "@jest/reporters": ^26.6.2 - "@jest/test-result": ^26.6.2 - "@jest/transform": ^26.6.2 - "@jest/types": ^26.6.2 + "@jest/types": ^29.6.1 "@types/node": "*" - ansi-escapes: ^4.2.1 chalk: ^4.0.0 - exit: ^0.1.2 - graceful-fs: ^4.2.4 - jest-changed-files: ^26.6.2 - jest-config: ^26.6.3 - jest-haste-map: ^26.6.2 - jest-message-util: ^26.6.2 - jest-regex-util: ^26.0.0 - jest-resolve: ^26.6.2 - jest-resolve-dependencies: ^26.6.3 - jest-runner: ^26.6.3 - jest-runtime: ^26.6.3 - jest-snapshot: ^26.6.2 - jest-util: ^26.6.2 - jest-validate: ^26.6.2 - jest-watcher: ^26.6.2 - micromatch: ^4.0.2 - p-each-series: ^2.1.0 - rimraf: ^3.0.0 + jest-message-util: ^29.6.2 + jest-util: ^29.6.2 slash: ^3.0.0 - strip-ansi: ^6.0.0 - checksum: f52b26ffe9b923ed67b3ff30e170b3a434d4263990f78d96cd43acbd0aa8ad36aecad2f1822f376da3a80228714fd6b7f7acd51744133cfcd2780ba0e3da537b + checksum: 1198667bda0430770c3e9b92681c0ee9f8346394574071c633f306192ac5f08e12972d6a5fdf03eb0d441051c8439bce0f6f9f355dc60d98777a35328331ba2e languageName: node linkType: hard @@ -2079,15 +2031,44 @@ __metadata: languageName: node linkType: hard -"@jest/environment@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/environment@npm:26.6.2" +"@jest/core@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/core@npm:29.6.2" dependencies: - "@jest/fake-timers": ^26.6.2 - "@jest/types": ^26.6.2 + "@jest/console": ^29.6.2 + "@jest/reporters": ^29.6.2 + "@jest/test-result": ^29.6.2 + "@jest/transform": ^29.6.2 + "@jest/types": ^29.6.1 "@types/node": "*" - jest-mock: ^26.6.2 - checksum: 7748081b2a758161785aff161780b05084dccaff908c8ed82c04f7da5d5e5439e77b5eb667306d5c4e1422653c7a67ed2955f26704f48c65c404195e1e21780a + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + ci-info: ^3.2.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + jest-changed-files: ^29.5.0 + jest-config: ^29.6.2 + jest-haste-map: ^29.6.2 + jest-message-util: ^29.6.2 + jest-regex-util: ^29.4.3 + jest-resolve: ^29.6.2 + jest-resolve-dependencies: ^29.6.2 + jest-runner: ^29.6.2 + jest-runtime: ^29.6.2 + jest-snapshot: ^29.6.2 + jest-util: ^29.6.2 + jest-validate: ^29.6.2 + jest-watcher: ^29.6.2 + micromatch: ^4.0.4 + pretty-format: ^29.6.2 + slash: ^3.0.0 + strip-ansi: ^6.0.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 6bbb3886430248c0092f275b1b946a701406732f7442c04e63e4ee2297c2ec02d8ceeec508a202e08128197699b2bcddbae2c2f74adb2cf30f2f0d7d94a7c2dc languageName: node linkType: hard @@ -2103,6 +2084,18 @@ __metadata: languageName: node linkType: hard +"@jest/environment@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/environment@npm:29.6.2" + dependencies: + "@jest/fake-timers": ^29.6.2 + "@jest/types": ^29.6.1 + "@types/node": "*" + jest-mock: ^29.6.2 + checksum: c7de0e4c0d9166e02d0eb166574e05ec460e1db3b69d6476e63244edd52d7c917e6876af55fe723ff3086f52c0b1869dec60654054735a7a48c9d4ac43af2a25 + languageName: node + linkType: hard + "@jest/expect-utils@npm:^29.6.1": version: 29.6.1 resolution: "@jest/expect-utils@npm:29.6.1" @@ -2112,6 +2105,15 @@ __metadata: languageName: node linkType: hard +"@jest/expect-utils@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/expect-utils@npm:29.6.2" + dependencies: + jest-get-type: ^29.4.3 + checksum: 0decf2009aa3735f9df469e78ce1721c2815e4278439887e0cf0321ca8979541a22515d114a59b2445a6cd70a074b09dc9c00b5e7b3b3feac5174b9c4a78b2e1 + languageName: node + linkType: hard + "@jest/expect@npm:^29.6.1": version: 29.6.1 resolution: "@jest/expect@npm:29.6.1" @@ -2122,17 +2124,13 @@ __metadata: languageName: node linkType: hard -"@jest/fake-timers@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/fake-timers@npm:26.6.2" +"@jest/expect@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/expect@npm:29.6.2" dependencies: - "@jest/types": ^26.6.2 - "@sinonjs/fake-timers": ^6.0.1 - "@types/node": "*" - jest-message-util: ^26.6.2 - jest-mock: ^26.6.2 - jest-util: ^26.6.2 - checksum: c732658fac4014a424e6629495296c3b2e8697787518df34c74539ec139625e7141ad792b8a4d3c8392b47954ad01be9846b7c57cc8c631490969e7cafa84e6a + expect: ^29.6.2 + jest-snapshot: ^29.6.2 + checksum: bd2d88a4e7c5420079c239afef341ec53dc7e353816cd13acbb42631a31fd321fe58677bb43a4dba851028f4c7e31da7980314e9094cd5b348896cb6cd3d42b2 languageName: node linkType: hard @@ -2150,14 +2148,17 @@ __metadata: languageName: node linkType: hard -"@jest/globals@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/globals@npm:26.6.2" +"@jest/fake-timers@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/fake-timers@npm:29.6.2" dependencies: - "@jest/environment": ^26.6.2 - "@jest/types": ^26.6.2 - expect: ^26.6.2 - checksum: 49b28d0cc7e99898eeaf23e6899e3c9ee25a2a4831caa3eb930ec1722de2e92a0e8a6a6f649438fdd20ff0c0d5e522dd78cb719466a57f011a88d60419b903c5 + "@jest/types": ^29.6.1 + "@sinonjs/fake-timers": ^10.0.2 + "@types/node": "*" + jest-message-util: ^29.6.2 + jest-mock: ^29.6.2 + jest-util: ^29.6.2 + checksum: 1abcda02f22d2ba32e178b7ab80a9180235a6c75ec9faef33324627b19a70dad64889a9ea49b8f07230e14a6e683b9120542c6d1d6b2ecaf937f4efde32dad88 languageName: node linkType: hard @@ -2173,50 +2174,63 @@ __metadata: languageName: node linkType: hard -"@jest/reporters@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/reporters@npm:26.6.2" +"@jest/globals@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/globals@npm:29.6.2" + dependencies: + "@jest/environment": ^29.6.2 + "@jest/expect": ^29.6.2 + "@jest/types": ^29.6.1 + jest-mock: ^29.6.2 + checksum: aa4a54f19cc025205bc696546940e1fe9c752c2d4d825852088aa76d44677ebba1ec66fabb78e615480cff23a06a70b5a3f893ab5163d901cdfa0d2267870b10 + languageName: node + linkType: hard + +"@jest/reporters@npm:^29.6.1": + version: 29.6.1 + resolution: "@jest/reporters@npm:29.6.1" dependencies: "@bcoe/v8-coverage": ^0.2.3 - "@jest/console": ^26.6.2 - "@jest/test-result": ^26.6.2 - "@jest/transform": ^26.6.2 - "@jest/types": ^26.6.2 + "@jest/console": ^29.6.1 + "@jest/test-result": ^29.6.1 + "@jest/transform": ^29.6.1 + "@jest/types": ^29.6.1 + "@jridgewell/trace-mapping": ^0.3.18 + "@types/node": "*" chalk: ^4.0.0 collect-v8-coverage: ^1.0.0 exit: ^0.1.2 - glob: ^7.1.2 - graceful-fs: ^4.2.4 + glob: ^7.1.3 + graceful-fs: ^4.2.9 istanbul-lib-coverage: ^3.0.0 - istanbul-lib-instrument: ^4.0.3 + istanbul-lib-instrument: ^5.1.0 istanbul-lib-report: ^3.0.0 istanbul-lib-source-maps: ^4.0.0 - istanbul-reports: ^3.0.2 - jest-haste-map: ^26.6.2 - jest-resolve: ^26.6.2 - jest-util: ^26.6.2 - jest-worker: ^26.6.2 - node-notifier: ^8.0.0 + istanbul-reports: ^3.1.3 + jest-message-util: ^29.6.1 + jest-util: ^29.6.1 + jest-worker: ^29.6.1 slash: ^3.0.0 - source-map: ^0.6.0 string-length: ^4.0.1 - terminal-link: ^2.0.0 - v8-to-istanbul: ^7.0.0 - dependenciesMeta: + strip-ansi: ^6.0.0 + v8-to-istanbul: ^9.0.1 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: node-notifier: optional: true - checksum: 53c7a697c562becb7682a9a6248ea553013bf7048c08ddce5bf9fb53b975fc9f799ca163f7494e0be6c4d3cf181c8bc392976268da52b7de8ce4470b971ed84e + checksum: b7dae415f3f6342b4db2671261bbee29af20a829f42135316c3dd548b9ef85290c9bb64a0e3aec4a55486596be1257ac8216a0f8d9794acd43f8b8fb686fc7e3 languageName: node linkType: hard -"@jest/reporters@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/reporters@npm:29.6.1" +"@jest/reporters@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/reporters@npm:29.6.2" dependencies: "@bcoe/v8-coverage": ^0.2.3 - "@jest/console": ^29.6.1 - "@jest/test-result": ^29.6.1 - "@jest/transform": ^29.6.1 + "@jest/console": ^29.6.2 + "@jest/test-result": ^29.6.2 + "@jest/transform": ^29.6.2 "@jest/types": ^29.6.1 "@jridgewell/trace-mapping": ^0.3.18 "@types/node": "*" @@ -2230,9 +2244,9 @@ __metadata: istanbul-lib-report: ^3.0.0 istanbul-lib-source-maps: ^4.0.0 istanbul-reports: ^3.1.3 - jest-message-util: ^29.6.1 - jest-util: ^29.6.1 - jest-worker: ^29.6.1 + jest-message-util: ^29.6.2 + jest-util: ^29.6.2 + jest-worker: ^29.6.2 slash: ^3.0.0 string-length: ^4.0.1 strip-ansi: ^6.0.0 @@ -2242,7 +2256,7 @@ __metadata: peerDependenciesMeta: node-notifier: optional: true - checksum: b7dae415f3f6342b4db2671261bbee29af20a829f42135316c3dd548b9ef85290c9bb64a0e3aec4a55486596be1257ac8216a0f8d9794acd43f8b8fb686fc7e3 + checksum: 7cf880d0730cee7d24ee96928003ef6946bf93423b0ae9a2edb53cae2c231b8ac50ec264f48a73744e3f11ca319cd414edacf99b2e7bf37cd72fe0b362090dd1 languageName: node linkType: hard @@ -2255,17 +2269,6 @@ __metadata: languageName: node linkType: hard -"@jest/source-map@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/source-map@npm:26.6.2" - dependencies: - callsites: ^3.0.0 - graceful-fs: ^4.2.4 - source-map: ^0.6.0 - checksum: b171cef442738887dda85527ab78229996db5946c6435ddb56d442c2851889ba493729a9de73100f1a31b9a31a91207b55bc75656ae7df9843d65078b925385e - languageName: node - linkType: hard - "@jest/source-map@npm:^29.6.0": version: 29.6.0 resolution: "@jest/source-map@npm:29.6.0" @@ -2277,18 +2280,6 @@ __metadata: languageName: node linkType: hard -"@jest/test-result@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/test-result@npm:26.6.2" - dependencies: - "@jest/console": ^26.6.2 - "@jest/types": ^26.6.2 - "@types/istanbul-lib-coverage": ^2.0.0 - collect-v8-coverage: ^1.0.0 - checksum: dcb6175825231e9377e43546aed4edd6acc22f1788d5f099bbba36bb55b9115a92f760e88426c076bcdeff5a50d8f697327a920db0cd1fb339781fc3713fa8c7 - languageName: node - linkType: hard - "@jest/test-result@npm:^29.6.1": version: 29.6.1 resolution: "@jest/test-result@npm:29.6.1" @@ -2301,16 +2292,15 @@ __metadata: languageName: node linkType: hard -"@jest/test-sequencer@npm:^26.6.3": - version: 26.6.3 - resolution: "@jest/test-sequencer@npm:26.6.3" +"@jest/test-result@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/test-result@npm:29.6.2" dependencies: - "@jest/test-result": ^26.6.2 - graceful-fs: ^4.2.4 - jest-haste-map: ^26.6.2 - jest-runner: ^26.6.3 - jest-runtime: ^26.6.3 - checksum: a3450b3d7057f74da1828bb7b3658f228a7c049dc4082c5c49b8bafbd8f69d102a8a99007b7ed5d43464712f7823f53fe3564fda17787f178c219cccf329a461 + "@jest/console": ^29.6.2 + "@jest/types": ^29.6.1 + "@types/istanbul-lib-coverage": ^2.0.0 + collect-v8-coverage: ^1.0.0 + checksum: 8aff37f18c8d2df4d9f453d57ec018a6479eb697fabcf74b1ca06e34553da1d7a2b85580a290408ba0b02e58543263244a2cb065c7c7180c8d8180cc78444fbd languageName: node linkType: hard @@ -2326,26 +2316,15 @@ __metadata: languageName: node linkType: hard -"@jest/transform@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/transform@npm:26.6.2" +"@jest/test-sequencer@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/test-sequencer@npm:29.6.2" dependencies: - "@babel/core": ^7.1.0 - "@jest/types": ^26.6.2 - babel-plugin-istanbul: ^6.0.0 - chalk: ^4.0.0 - convert-source-map: ^1.4.0 - fast-json-stable-stringify: ^2.0.0 - graceful-fs: ^4.2.4 - jest-haste-map: ^26.6.2 - jest-regex-util: ^26.0.0 - jest-util: ^26.6.2 - micromatch: ^4.0.2 - pirates: ^4.0.1 + "@jest/test-result": ^29.6.2 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.2 slash: ^3.0.0 - source-map: ^0.6.1 - write-file-atomic: ^3.0.0 - checksum: 31667b925a2f3b310d854495da0ab67be8f5da24df76ecfc51162e75f1140aed5d18069ba190cb5e0c7e492b04272c8c79076ddf5bbcff530ee80a16a02c4545 + checksum: 12dc2577e45eeb98b85d1769846b7d6effa536907986ad3c4cbd014df9e24431a564cc8cd94603332e4b1f9bfb421371883efc6a5085b361a52425ffc2a52dc6 languageName: node linkType: hard @@ -2372,16 +2351,26 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^26.6.2": - version: 26.6.2 - resolution: "@jest/types@npm:26.6.2" +"@jest/transform@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/transform@npm:29.6.2" dependencies: - "@types/istanbul-lib-coverage": ^2.0.0 - "@types/istanbul-reports": ^3.0.0 - "@types/node": "*" - "@types/yargs": ^15.0.0 + "@babel/core": ^7.11.6 + "@jest/types": ^29.6.1 + "@jridgewell/trace-mapping": ^0.3.18 + babel-plugin-istanbul: ^6.1.1 chalk: ^4.0.0 - checksum: a0bd3d2f22f26ddb23f41fddf6e6a30bf4fab2ce79ec1cb6ce6fdfaf90a72e00f4c71da91ec61e13db3b10c41de22cf49d07c57ff2b59171d64b29f909c1d8d6 + convert-source-map: ^2.0.0 + fast-json-stable-stringify: ^2.1.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.2 + jest-regex-util: ^29.4.3 + jest-util: ^29.6.2 + micromatch: ^4.0.4 + pirates: ^4.0.4 + slash: ^3.0.0 + write-file-atomic: ^4.0.2 + checksum: ffb8c3c344cd48bedadec295d9c436737eccc39c1f0868aa9753b76397b33b2e5b121058af6f287ba6f2036181137e37df1212334bfa9d9a712986a4518cdc18 languageName: node linkType: hard @@ -2488,14 +2477,14 @@ __metadata: "@jupyterlab/ui-components": ^4 "@mui/icons-material": ^5.11.0 "@mui/material": ^5.11.0 - "@types/jest": ^26.0.0 + "@types/jest": ^29 "@types/react-syntax-highlighter": ^15.5.6 "@typescript-eslint/eslint-plugin": ^4.8.1 "@typescript-eslint/parser": ^4.8.1 eslint: ^7.14.0 eslint-config-prettier: ^6.15.0 eslint-plugin-prettier: ^3.1.4 - jest: ^26.0.0 + jest: ^29 mkdirp: ^1.0.3 npm-run-all: ^4.1.5 prettier: ^2.1.1 @@ -2511,8 +2500,8 @@ __metadata: stylelint-config-recommended: ^6.0.0 stylelint-config-standard: ~24.0.0 stylelint-prettier: ^2.0.0 - ts-jest: ^26.0.0 - typescript: ~4.1.3 + ts-jest: ^29 + typescript: ~4.3.0 y-protocols: ^1.0.5 languageName: unknown linkType: soft @@ -4724,15 +4713,6 @@ __metadata: languageName: node linkType: hard -"@sinonjs/commons@npm:^1.7.0": - version: 1.8.6 - resolution: "@sinonjs/commons@npm:1.8.6" - dependencies: - type-detect: 4.0.8 - checksum: 7d3f8c1e85f30cd4e83594fc19b7a657f14d49eb8d95a30095631ce15e906c869e0eff96c5b93dffea7490c00418b07f54582ba49c6560feb2a8c34c0b16832d - languageName: node - linkType: hard - "@sinonjs/commons@npm:^3.0.0": version: 3.0.0 resolution: "@sinonjs/commons@npm:3.0.0" @@ -4751,22 +4731,6 @@ __metadata: languageName: node linkType: hard -"@sinonjs/fake-timers@npm:^6.0.1": - version: 6.0.1 - resolution: "@sinonjs/fake-timers@npm:6.0.1" - dependencies: - "@sinonjs/commons": ^1.7.0 - checksum: 8e331aa1412d905ecc8efd63550f58a6f77dcb510f878172004e53be63eb82650623618763001a918fc5e21257b86c45041e4e97c454ed6a2d187de084abbd11 - languageName: node - linkType: hard - -"@tootallnate/once@npm:1": - version: 1.1.2 - resolution: "@tootallnate/once@npm:1.1.2" - checksum: e1fb1bbbc12089a0cb9433dc290f97bddd062deadb6178ce9bcb93bb7c1aecde5e60184bc7065aec42fe1663622a213493c48bbd4972d931aae48315f18e1be9 - languageName: node - linkType: hard - "@tootallnate/once@npm:2": version: 2.0.0 resolution: "@tootallnate/once@npm:2.0.0" @@ -4791,7 +4755,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.1.7": +"@types/babel__core@npm:^7.1.14": version: 7.20.1 resolution: "@types/babel__core@npm:7.20.1" dependencies: @@ -4823,7 +4787,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.4, @types/babel__traverse@npm:^7.0.6": +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": version: 7.20.1 resolution: "@types/babel__traverse@npm:7.20.1" dependencies: @@ -4875,7 +4839,7 @@ __metadata: languageName: node linkType: hard -"@types/graceful-fs@npm:^4.1.2, @types/graceful-fs@npm:^4.1.3": +"@types/graceful-fs@npm:^4.1.3": version: 4.1.6 resolution: "@types/graceful-fs@npm:4.1.6" dependencies: @@ -4918,13 +4882,13 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:^26.0.0": - version: 26.0.24 - resolution: "@types/jest@npm:26.0.24" +"@types/jest@npm:^29": + version: 29.5.3 + resolution: "@types/jest@npm:29.5.3" dependencies: - jest-diff: ^26.0.0 - pretty-format: ^26.0.0 - checksum: ae39675412f08d884926254e9b12bfd2b5a4e4d204c94d3148cb942174a474930d0c60540133c968f22241d4712b7940c96cbc883096eb326a4d5b206fb78bd0 + expect: ^29.0.0 + pretty-format: ^29.0.0 + checksum: e36bb92e0b9e5ea7d6f8832baa42f087fc1697f6cd30ec309a07ea4c268e06ec460f1f0cfd2581daf5eff5763475190ec1ad8ac6520c49ccfe4f5c0a48bfa676 languageName: node linkType: hard @@ -5011,7 +4975,7 @@ __metadata: languageName: node linkType: hard -"@types/prettier@npm:^2.0.0, @types/prettier@npm:^2.1.5": +"@types/prettier@npm:^2.1.5": version: 2.7.3 resolution: "@types/prettier@npm:2.7.3" checksum: 705384209cea6d1433ff6c187c80dcc0b95d99d5c5ce21a46a9a58060c527973506822e428789d842761e0280d25e3359300f017fbe77b9755bc772ab3dc2f83 @@ -5127,15 +5091,6 @@ __metadata: languageName: node linkType: hard -"@types/yargs@npm:^15.0.0": - version: 15.0.15 - resolution: "@types/yargs@npm:15.0.15" - dependencies: - "@types/yargs-parser": "*" - checksum: 3420f6bcc508a895ef91858f8e6de975c710e4498cf6ed293f1174d3f1ad56edb4ab8481219bf6190f64a3d4115fab1d13ab3edc90acd54fba7983144040e446 - languageName: node - linkType: hard - "@types/yargs@npm:^17.0.8": version: 17.0.24 resolution: "@types/yargs@npm:17.0.24" @@ -5483,7 +5438,7 @@ __metadata: languageName: node linkType: hard -"abab@npm:^2.0.3, abab@npm:^2.0.5, abab@npm:^2.0.6": +"abab@npm:^2.0.3, abab@npm:^2.0.6": version: 2.0.6 resolution: "abab@npm:2.0.6" checksum: 6ffc1af4ff315066c62600123990d87551ceb0aafa01e6539da77b0f5987ac7019466780bf480f1787576d4385e3690c81ccc37cfda12819bf510b8ab47e5a3e @@ -5539,16 +5494,6 @@ __metadata: languageName: node linkType: hard -"acorn-globals@npm:^6.0.0": - version: 6.0.0 - resolution: "acorn-globals@npm:6.0.0" - dependencies: - acorn: ^7.1.1 - acorn-walk: ^7.1.1 - checksum: 72d95e5b5e585f9acd019b993ab8bbba68bb3cbc9d9b5c1ebb3c2f1fe5981f11deababfb4949f48e6262f9c57878837f5958c0cca396f81023814680ca878042 - languageName: node - linkType: hard - "acorn-globals@npm:^7.0.0": version: 7.0.1 resolution: "acorn-globals@npm:7.0.1" @@ -5577,13 +5522,6 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^7.1.1": - version: 7.2.0 - resolution: "acorn-walk@npm:7.2.0" - checksum: 9252158a79b9d92f1bc0dd6acc0fcfb87a67339e84bcc301bb33d6078936d27e35d606b4d35626d2962cd43c256d6f27717e70cbe15c04fff999ab0b2260b21f - languageName: node - linkType: hard - "acorn-walk@npm:^8.0.2": version: 8.2.0 resolution: "acorn-walk@npm:8.2.0" @@ -5591,7 +5529,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^7.1.1, acorn@npm:^7.4.0": +"acorn@npm:^7.4.0": version: 7.4.1 resolution: "acorn@npm:7.4.1" bin: @@ -5600,7 +5538,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.1.0, acorn@npm:^8.2.4, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2": +"acorn@npm:^8.1.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2": version: 8.10.0 resolution: "acorn@npm:8.10.0" bin: @@ -5720,7 +5658,7 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^5.0.0, ansi-regex@npm:^5.0.1": +"ansi-regex@npm:^5.0.1": version: 5.0.1 resolution: "ansi-regex@npm:5.0.1" checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b @@ -5766,16 +5704,6 @@ __metadata: languageName: node linkType: hard -"anymatch@npm:^2.0.0": - version: 2.0.0 - resolution: "anymatch@npm:2.0.0" - dependencies: - micromatch: ^3.1.4 - normalize-path: ^2.1.1 - checksum: f7bb1929842b4585cdc28edbb385767d499ce7d673f96a8f11348d2b2904592ffffc594fe9229b9a1e9e4dccb9329b7692f9f45e6a11dcefbb76ecdc9ab740f6 - languageName: node - linkType: hard - "anymatch@npm:^3.0.3": version: 3.1.3 resolution: "anymatch@npm:3.1.3" @@ -5829,27 +5757,6 @@ __metadata: languageName: node linkType: hard -"arr-diff@npm:^4.0.0": - version: 4.0.0 - resolution: "arr-diff@npm:4.0.0" - checksum: ea7c8834842ad3869297f7915689bef3494fd5b102ac678c13ffccab672d3d1f35802b79e90c4cfec2f424af3392e44112d1ccf65da34562ed75e049597276a0 - languageName: node - linkType: hard - -"arr-flatten@npm:^1.1.0": - version: 1.1.0 - resolution: "arr-flatten@npm:1.1.0" - checksum: 963fe12564fca2f72c055f3f6c206b9e031f7c433a0c66ca9858b484821f248c5b1e5d53c8e4989d80d764cd776cf6d9b160ad05f47bdc63022bfd63b5455e22 - languageName: node - linkType: hard - -"arr-union@npm:^3.1.0": - version: 3.1.0 - resolution: "arr-union@npm:3.1.0" - checksum: b5b0408c6eb7591143c394f3be082fee690ddd21f0fdde0a0a01106799e847f67fcae1b7e56b0a0c173290e29c6aca9562e82b300708a268bc8f88f3d6613cb9 - languageName: node - linkType: hard - "array-buffer-byte-length@npm:^1.0.0": version: 1.0.0 resolution: "array-buffer-byte-length@npm:1.0.0" @@ -5881,13 +5788,6 @@ __metadata: languageName: node linkType: hard -"array-unique@npm:^0.3.2": - version: 0.3.2 - resolution: "array-unique@npm:0.3.2" - checksum: da344b89cfa6b0a5c221f965c21638bfb76b57b45184a01135382186924f55973cd9b171d4dad6bf606c6d9d36b0d721d091afdc9791535ead97ccbe78f8a888 - languageName: node - linkType: hard - "arraybuffer.prototype.slice@npm:^1.0.1": version: 1.0.1 resolution: "arraybuffer.prototype.slice@npm:1.0.1" @@ -5916,13 +5816,6 @@ __metadata: languageName: node linkType: hard -"assign-symbols@npm:^1.0.0": - version: 1.0.0 - resolution: "assign-symbols@npm:1.0.0" - checksum: c0eb895911d05b6b2d245154f70461c5e42c107457972e5ebba38d48967870dee53bcdf6c7047990586daa80fab8dab3cc6300800fbd47b454247fdedd859a2c - languageName: node - linkType: hard - "astral-regex@npm:^2.0.0": version: 2.0.0 resolution: "astral-regex@npm:2.0.0" @@ -5958,15 +5851,6 @@ __metadata: languageName: node linkType: hard -"atob@npm:^2.1.2": - version: 2.1.2 - resolution: "atob@npm:2.1.2" - bin: - atob: bin/atob.js - checksum: dfeeeb70090c5ebea7be4b9f787f866686c645d9f39a0d184c817252d0cf08455ed25267d79c03254d3be1f03ac399992a792edcd5ffb9c91e097ab5ef42833a - languageName: node - linkType: hard - "available-typed-arrays@npm:^1.0.5": version: 1.0.5 resolution: "available-typed-arrays@npm:1.0.5" @@ -5985,29 +5869,28 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:^26.6.3": - version: 26.6.3 - resolution: "babel-jest@npm:26.6.3" +"babel-jest@npm:^29.6.1": + version: 29.6.1 + resolution: "babel-jest@npm:29.6.1" dependencies: - "@jest/transform": ^26.6.2 - "@jest/types": ^26.6.2 - "@types/babel__core": ^7.1.7 - babel-plugin-istanbul: ^6.0.0 - babel-preset-jest: ^26.6.2 + "@jest/transform": ^29.6.1 + "@types/babel__core": ^7.1.14 + babel-plugin-istanbul: ^6.1.1 + babel-preset-jest: ^29.5.0 chalk: ^4.0.0 - graceful-fs: ^4.2.4 + graceful-fs: ^4.2.9 slash: ^3.0.0 peerDependencies: - "@babel/core": ^7.0.0 - checksum: 5917233f0d381e719e195b69b81e46da90293432d10288d79f8f59b8f3f9ac030e14701f3d9f90893fb739481df1d132446f1b983d841e65e2623775db100897 + "@babel/core": ^7.8.0 + checksum: bc46cfba468edde91f34a8292501d4448a39fab72d80d7d95f4349feb114fa21becb01def007d6166de7933ab9633bf5b5e1b72ba6ffeaa991f7abf014a2f61d languageName: node linkType: hard -"babel-jest@npm:^29.6.1": - version: 29.6.1 - resolution: "babel-jest@npm:29.6.1" +"babel-jest@npm:^29.6.2": + version: 29.6.2 + resolution: "babel-jest@npm:29.6.2" dependencies: - "@jest/transform": ^29.6.1 + "@jest/transform": ^29.6.2 "@types/babel__core": ^7.1.14 babel-plugin-istanbul: ^6.1.1 babel-preset-jest: ^29.5.0 @@ -6016,11 +5899,11 @@ __metadata: slash: ^3.0.0 peerDependencies: "@babel/core": ^7.8.0 - checksum: bc46cfba468edde91f34a8292501d4448a39fab72d80d7d95f4349feb114fa21becb01def007d6166de7933ab9633bf5b5e1b72ba6ffeaa991f7abf014a2f61d + checksum: 3936b5d6ed6f08670c830ed919e38a4a593d0643b8e30fdeb16f4588b262ea5255fb96fd1849c02fba0b082ecfa4e788ce9a128ad1b9e654d46aac09c3a55504 languageName: node linkType: hard -"babel-plugin-istanbul@npm:^6.0.0, babel-plugin-istanbul@npm:^6.1.1": +"babel-plugin-istanbul@npm:^6.1.1": version: 6.1.1 resolution: "babel-plugin-istanbul@npm:6.1.1" dependencies: @@ -6033,18 +5916,6 @@ __metadata: languageName: node linkType: hard -"babel-plugin-jest-hoist@npm:^26.6.2": - version: 26.6.2 - resolution: "babel-plugin-jest-hoist@npm:26.6.2" - dependencies: - "@babel/template": ^7.3.3 - "@babel/types": ^7.3.3 - "@types/babel__core": ^7.0.0 - "@types/babel__traverse": ^7.0.6 - checksum: abe3732fdf20f96e91cbf788a54d776b30bd7a6054cb002a744d7071c656813e26e77a780dc2a6f6b197472897e220836cd907bda3fadb9d0481126bfd6c3783 - languageName: node - linkType: hard - "babel-plugin-jest-hoist@npm:^29.5.0": version: 29.5.0 resolution: "babel-plugin-jest-hoist@npm:29.5.0" @@ -6126,18 +5997,6 @@ __metadata: languageName: node linkType: hard -"babel-preset-jest@npm:^26.6.2": - version: 26.6.2 - resolution: "babel-preset-jest@npm:26.6.2" - dependencies: - babel-plugin-jest-hoist: ^26.6.2 - babel-preset-current-node-syntax: ^1.0.0 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 1d9bef3a7ac6751a09d29ceb84be8b1998abd210fafa12223689c744db4f2a63ab90cba7986a71f3154d9aceda9dbeca563178731d21cbaf793b4096ed3a4d01 - languageName: node - linkType: hard - "babel-preset-jest@npm:^29.5.0": version: 29.5.0 resolution: "babel-preset-jest@npm:29.5.0" @@ -6178,21 +6037,6 @@ __metadata: languageName: node linkType: hard -"base@npm:^0.11.1": - version: 0.11.2 - resolution: "base@npm:0.11.2" - dependencies: - cache-base: ^1.0.1 - class-utils: ^0.3.5 - component-emitter: ^1.2.1 - define-property: ^1.0.0 - isobject: ^3.0.1 - mixin-deep: ^1.2.0 - pascalcase: ^0.1.1 - checksum: a4a146b912e27eea8f66d09cb0c9eab666f32ce27859a7dfd50f38cd069a2557b39f16dba1bc2aecb3b44bf096738dd207b7970d99b0318423285ab1b1994edd - languageName: node - linkType: hard - "before-after-hook@npm:^2.2.0": version: 2.2.3 resolution: "before-after-hook@npm:2.2.3" @@ -6249,24 +6093,6 @@ __metadata: languageName: node linkType: hard -"braces@npm:^2.3.1": - version: 2.3.2 - resolution: "braces@npm:2.3.2" - dependencies: - arr-flatten: ^1.1.0 - array-unique: ^0.3.2 - extend-shallow: ^2.0.1 - fill-range: ^4.0.0 - isobject: ^3.0.1 - repeat-element: ^1.1.2 - snapdragon: ^0.8.1 - snapdragon-node: ^2.0.1 - split-string: ^3.0.2 - to-regex: ^3.0.1 - checksum: e30dcb6aaf4a31c8df17d848aa283a65699782f75ad61ae93ec25c9729c66cf58e66f0000a9fec84e4add1135bb7da40f7cb9601b36bebcfa9ca58e8d5c07de0 - languageName: node - linkType: hard - "braces@npm:^3.0.2": version: 3.0.2 resolution: "braces@npm:3.0.2" @@ -6276,13 +6102,6 @@ __metadata: languageName: node linkType: hard -"browser-process-hrtime@npm:^1.0.0": - version: 1.0.0 - resolution: "browser-process-hrtime@npm:1.0.0" - checksum: e30f868cdb770b1201afb714ad1575dd86366b6e861900884665fb627109b3cc757c40067d3bfee1ff2a29c835257ea30725a8018a9afd02ac1c24b408b1e45f - languageName: node - linkType: hard - "browserslist@npm:^4.14.5, browserslist@npm:^4.21.9": version: 4.21.9 resolution: "browserslist@npm:4.21.9" @@ -6315,7 +6134,7 @@ __metadata: languageName: node linkType: hard -"buffer-from@npm:1.x, buffer-from@npm:^1.0.0": +"buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2" checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb @@ -6411,23 +6230,6 @@ __metadata: languageName: node linkType: hard -"cache-base@npm:^1.0.1": - version: 1.0.1 - resolution: "cache-base@npm:1.0.1" - dependencies: - collection-visit: ^1.0.0 - component-emitter: ^1.2.1 - get-value: ^2.0.6 - has-value: ^1.0.0 - isobject: ^3.0.1 - set-value: ^2.0.0 - to-object-path: ^0.3.0 - union-value: ^1.0.0 - unset-value: ^1.0.0 - checksum: 9114b8654fe2366eedc390bad0bcf534e2f01b239a888894e2928cb58cdc1e6ea23a73c6f3450dcfd2058aa73a8a981e723cd1e7c670c047bf11afdc65880107 - languageName: node - linkType: hard - "call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": version: 1.0.2 resolution: "call-bind@npm:1.0.2" @@ -6456,14 +6258,14 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": +"camelcase@npm:^5.3.1": version: 5.3.1 resolution: "camelcase@npm:5.3.1" checksum: e6effce26b9404e3c0f301498184f243811c30dfe6d0b9051863bd8e4034d09c8c2923794f280d6827e5aa055f6c434115ff97864a16a963366fb35fd673024b languageName: node linkType: hard -"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": +"camelcase@npm:^6.2.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d @@ -6477,15 +6279,6 @@ __metadata: languageName: node linkType: hard -"capture-exit@npm:^2.0.0": - version: 2.0.0 - resolution: "capture-exit@npm:2.0.0" - dependencies: - rsvp: ^4.8.4 - checksum: 0b9f10daca09e521da9599f34c8e7af14ad879c336e2bdeb19955b375398ae1c5bcc91ac9f2429944343057ee9ed028b1b2fb28816c384e0e55d70c439b226f4 - languageName: node - linkType: hard - "chalk@npm:4.1.0": version: 4.1.0 resolution: "chalk@npm:4.1.0" @@ -6594,13 +6387,6 @@ __metadata: languageName: node linkType: hard -"cjs-module-lexer@npm:^0.6.0": - version: 0.6.0 - resolution: "cjs-module-lexer@npm:0.6.0" - checksum: 445b039607efd74561d7db8d0867031c8b6a69f25e83fdd861b0fa1fbc11f12de057ba1db80637f3c9016774354092af5325eebb90505d65ccc5389cae09d1fd - languageName: node - linkType: hard - "cjs-module-lexer@npm:^1.0.0": version: 1.2.3 resolution: "cjs-module-lexer@npm:1.2.3" @@ -6608,18 +6394,6 @@ __metadata: languageName: node linkType: hard -"class-utils@npm:^0.3.5": - version: 0.3.6 - resolution: "class-utils@npm:0.3.6" - dependencies: - arr-union: ^3.1.0 - define-property: ^0.2.5 - isobject: ^3.0.0 - static-extend: ^0.1.1 - checksum: be108900801e639e50f96a7e4bfa8867c753a7750a7603879f3981f8b0a89cba657497a2d5f40cd4ea557ff15d535a100818bb486baf6e26fe5d7872e75f1078 - languageName: node - linkType: hard - "classnames@npm:^2.2": version: 2.3.2 resolution: "classnames@npm:2.3.2" @@ -6664,25 +6438,14 @@ __metadata: languageName: node linkType: hard -"cliui@npm:^6.0.0": - version: 6.0.0 - resolution: "cliui@npm:6.0.0" +"cliui@npm:^7.0.2": + version: 7.0.4 + resolution: "cliui@npm:7.0.4" dependencies: string-width: ^4.2.0 strip-ansi: ^6.0.0 - wrap-ansi: ^6.2.0 - checksum: 4fcfd26d292c9f00238117f39fc797608292ae36bac2168cfee4c85923817d0607fe21b3329a8621e01aedf512c99b7eaa60e363a671ffd378df6649fb48ae42 - languageName: node - linkType: hard - -"cliui@npm:^7.0.2": - version: 7.0.4 - resolution: "cliui@npm:7.0.4" - dependencies: - string-width: ^4.2.0 - strip-ansi: ^6.0.0 - wrap-ansi: ^7.0.0 - checksum: ce2e8f578a4813806788ac399b9e866297740eecd4ad1823c27fd344d78b22c5f8597d548adbcc46f0573e43e21e751f39446c5a5e804a12aace402b7a315d7f + wrap-ansi: ^7.0.0 + checksum: ce2e8f578a4813806788ac399b9e866297740eecd4ad1823c27fd344d78b22c5f8597d548adbcc46f0573e43e21e751f39446c5a5e804a12aace402b7a315d7f languageName: node linkType: hard @@ -6752,16 +6515,6 @@ __metadata: languageName: node linkType: hard -"collection-visit@npm:^1.0.0": - version: 1.0.0 - resolution: "collection-visit@npm:1.0.0" - dependencies: - map-visit: ^1.0.0 - object-visit: ^1.0.0 - checksum: 15d9658fe6eb23594728346adad5433b86bb7a04fd51bbab337755158722f9313a5376ef479de5b35fbc54140764d0d39de89c339f5d25b959ed221466981da9 - languageName: node - linkType: hard - "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -6895,13 +6648,6 @@ __metadata: languageName: node linkType: hard -"component-emitter@npm:^1.2.1": - version: 1.3.0 - resolution: "component-emitter@npm:1.3.0" - checksum: b3c46de38ffd35c57d1c02488355be9f218e582aec72d72d1b8bbec95a3ac1b38c96cd6e03ff015577e68f550fbb361a3bfdbd9bb248be9390b7b3745691be6b - languageName: node - linkType: hard - "compute-gcd@npm:^1.2.1": version: 1.2.1 resolution: "compute-gcd@npm:1.2.1" @@ -7063,7 +6809,7 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": +"convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": version: 1.9.0 resolution: "convert-source-map@npm:1.9.0" checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 @@ -7077,13 +6823,6 @@ __metadata: languageName: node linkType: hard -"copy-descriptor@npm:^0.1.0": - version: 0.1.1 - resolution: "copy-descriptor@npm:0.1.1" - checksum: d4b7b57b14f1d256bb9aa0b479241048afd7f5bcf22035fc7b94e8af757adeae247ea23c1a774fe44869fd5694efba4a969b88d966766c5245fdee59837fe45b - languageName: node - linkType: hard - "core-js-compat@npm:^3.31.0": version: 3.31.1 resolution: "core-js-compat@npm:3.31.1" @@ -7140,7 +6879,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^6.0.0, cross-spawn@npm:^6.0.5": +"cross-spawn@npm:^6.0.5": version: 6.0.5 resolution: "cross-spawn@npm:6.0.5" dependencies: @@ -7205,13 +6944,6 @@ __metadata: languageName: node linkType: hard -"cssom@npm:^0.4.4": - version: 0.4.4 - resolution: "cssom@npm:0.4.4" - checksum: e3bc1076e7ee4213d4fef05e7ae03bfa83dc05f32611d8edc341f4ecc3d9647b89c8245474c7dd2cdcdb797a27c462e99da7ad00a34399694559f763478ff53f - languageName: node - linkType: hard - "cssom@npm:^0.5.0": version: 0.5.0 resolution: "cssom@npm:0.5.0" @@ -7297,15 +7029,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:^2.2.0, debug@npm:^2.3.3": - version: 2.6.9 - resolution: "debug@npm:2.6.9" - dependencies: - ms: 2.0.0 - checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 - languageName: node - linkType: hard - "decamelize-keys@npm:^1.1.0": version: 1.1.1 resolution: "decamelize-keys@npm:1.1.1" @@ -7323,7 +7046,7 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.2.1, decimal.js@npm:^10.4.2": +"decimal.js@npm:^10.4.2": version: 10.4.3 resolution: "decimal.js@npm:10.4.3" checksum: 796404dcfa9d1dbfdc48870229d57f788b48c21c603c3f6554a1c17c10195fc1024de338b0cf9e1efe0c7c167eeb18f04548979bcc5fdfabebb7cc0ae3287bae @@ -7339,13 +7062,6 @@ __metadata: languageName: node linkType: hard -"decode-uri-component@npm:^0.2.0": - version: 0.2.2 - resolution: "decode-uri-component@npm:0.2.2" - checksum: 95476a7d28f267292ce745eac3524a9079058bbb35767b76e3ee87d42e34cd0275d2eb19d9d08c3e167f97556e8a2872747f5e65cbebcac8b0c98d83e285f139 - languageName: node - linkType: hard - "dedent@npm:0.7.0, dedent@npm:^0.7.0": version: 0.7.0 resolution: "dedent@npm:0.7.0" @@ -7353,6 +7069,18 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^1.0.0": + version: 1.5.1 + resolution: "dedent@npm:1.5.1" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: c3c300a14edf1bdf5a873f9e4b22e839d62490bc5c8d6169c1f15858a1a76733d06a9a56930e963d677a2ceeca4b6b0894cc5ea2f501aa382ca5b92af3413c2a + languageName: node + linkType: hard + "deep-equal@npm:^1.1.1": version: 1.1.1 resolution: "deep-equal@npm:1.1.1" @@ -7417,34 +7145,6 @@ __metadata: languageName: node linkType: hard -"define-property@npm:^0.2.5": - version: 0.2.5 - resolution: "define-property@npm:0.2.5" - dependencies: - is-descriptor: ^0.1.0 - checksum: 85af107072b04973b13f9e4128ab74ddfda48ec7ad2e54b193c0ffb57067c4ce5b7786a7b4ae1f24bd03e87c5d18766b094571810b314d7540f86d4354dbd394 - languageName: node - linkType: hard - -"define-property@npm:^1.0.0": - version: 1.0.0 - resolution: "define-property@npm:1.0.0" - dependencies: - is-descriptor: ^1.0.0 - checksum: 5fbed11dace44dd22914035ba9ae83ad06008532ca814d7936a53a09e897838acdad5b108dd0688cc8d2a7cf0681acbe00ee4136cf36743f680d10517379350a - languageName: node - linkType: hard - -"define-property@npm:^2.0.2": - version: 2.0.2 - resolution: "define-property@npm:2.0.2" - dependencies: - is-descriptor: ^1.0.2 - isobject: ^3.0.1 - checksum: 3217ed53fc9eed06ba8da6f4d33e28c68a82e2f2a8ab4d562c4920d8169a166fe7271453675e6c69301466f36a65d7f47edf0cf7f474b9aa52a5ead9c1b13c99 - languageName: node - linkType: hard - "del@npm:^6.0.0": version: 6.1.1 resolution: "del@npm:6.1.1" @@ -7510,13 +7210,6 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^26.6.2": - version: 26.6.2 - resolution: "diff-sequences@npm:26.6.2" - checksum: 79af871776ef149a7ff3345d6b1bf37fe6e81f68632aa5542787851f6f60fba19b0be22fdd1e06046f56ae7382763ccfe94a982c39ee72bd107aef435ecbc0cf - languageName: node - linkType: hard - "diff-sequences@npm:^29.4.3": version: 29.4.3 resolution: "diff-sequences@npm:29.4.3" @@ -7593,15 +7286,6 @@ __metadata: languageName: node linkType: hard -"domexception@npm:^2.0.1": - version: 2.0.1 - resolution: "domexception@npm:2.0.1" - dependencies: - webidl-conversions: ^5.0.0 - checksum: d638e9cb05c52999f1b2eb87c374b03311ea5b1d69c2f875bc92da73e17db60c12142b45c950228642ff7f845c536b65305483350d080df59003a653da80b691 - languageName: node - linkType: hard - "domexception@npm:^4.0.0": version: 4.0.0 resolution: "domexception@npm:4.0.0" @@ -7707,13 +7391,6 @@ __metadata: languageName: node linkType: hard -"emittery@npm:^0.7.1": - version: 0.7.2 - resolution: "emittery@npm:0.7.2" - checksum: 908cd933d48a9bcb58ddf39e9a7d4ba1e049de392ccbef010102539a636e03cea2b28218331b7ede41de8165d9ed7f148851c5112ebd2e943117c0f61eff5f10 - languageName: node - linkType: hard - "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -7756,7 +7433,7 @@ __metadata: languageName: node linkType: hard -"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": +"end-of-stream@npm:^1.4.1": version: 1.4.4 resolution: "end-of-stream@npm:1.4.4" dependencies: @@ -8166,13 +7843,6 @@ __metadata: languageName: node linkType: hard -"exec-sh@npm:^0.3.2": - version: 0.3.6 - resolution: "exec-sh@npm:0.3.6" - checksum: 0be4f06929c8e4834ea4812f29fe59e2dfcc1bc3fc4b4bb71acb38a500c3b394628a05ef7ba432520bc6c5ec4fadab00cc9c513c4ff6a32104965af302e998e0 - languageName: node - linkType: hard - "execa@npm:5.0.0": version: 5.0.0 resolution: "execa@npm:5.0.0" @@ -8190,38 +7860,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^1.0.0": - version: 1.0.0 - resolution: "execa@npm:1.0.0" - dependencies: - cross-spawn: ^6.0.0 - get-stream: ^4.0.0 - is-stream: ^1.1.0 - npm-run-path: ^2.0.0 - p-finally: ^1.0.0 - signal-exit: ^3.0.0 - strip-eof: ^1.0.0 - checksum: ddf1342c1c7d02dd93b41364cd847640f6163350d9439071abf70bf4ceb1b9b2b2e37f54babb1d8dc1df8e0d8def32d0e81e74a2e62c3e1d70c303eb4c306bc4 - languageName: node - linkType: hard - -"execa@npm:^4.0.0": - version: 4.1.0 - resolution: "execa@npm:4.1.0" - dependencies: - cross-spawn: ^7.0.0 - get-stream: ^5.0.0 - human-signals: ^1.1.1 - is-stream: ^2.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^4.0.0 - onetime: ^5.1.0 - signal-exit: ^3.0.2 - strip-final-newline: ^2.0.0 - checksum: e30d298934d9c52f90f3847704fd8224e849a081ab2b517bbc02f5f7732c24e56a21f14cb96a08256deffeb2d12b2b7cb7e2b014a12fb36f8d3357e06417ed55 - languageName: node - linkType: hard - "execa@npm:^5.0.0": version: 5.1.1 resolution: "execa@npm:5.1.1" @@ -8246,32 +7884,17 @@ __metadata: languageName: node linkType: hard -"expand-brackets@npm:^2.1.4": - version: 2.1.4 - resolution: "expand-brackets@npm:2.1.4" +"expect@npm:^29.0.0, expect@npm:^29.6.2": + version: 29.6.2 + resolution: "expect@npm:29.6.2" dependencies: - debug: ^2.3.3 - define-property: ^0.2.5 - extend-shallow: ^2.0.1 - posix-character-classes: ^0.1.0 - regex-not: ^1.0.0 - snapdragon: ^0.8.1 - to-regex: ^3.0.1 - checksum: 1781d422e7edfa20009e2abda673cadb040a6037f0bd30fcd7357304f4f0c284afd420d7622722ca4a016f39b6d091841ab57b401c1f7e2e5131ac65b9f14fa1 - languageName: node - linkType: hard - -"expect@npm:^26.6.2": - version: 26.6.2 - resolution: "expect@npm:26.6.2" - dependencies: - "@jest/types": ^26.6.2 - ansi-styles: ^4.0.0 - jest-get-type: ^26.3.0 - jest-matcher-utils: ^26.6.2 - jest-message-util: ^26.6.2 - jest-regex-util: ^26.0.0 - checksum: 79a9b888c5c6d37d11f2cb76def6cf1dc8ff098d38662ee20c9f2ee0da67e9a93435f2327854b2e7554732153870621843e7f83e8cefb1250447ee2bc39883a4 + "@jest/expect-utils": ^29.6.2 + "@types/node": "*" + jest-get-type: ^29.4.3 + jest-matcher-utils: ^29.6.2 + jest-message-util: ^29.6.2 + jest-util: ^29.6.2 + checksum: 71f7b0c560e58bf6d27e0fded261d4bdb7ef81552a6bb4bd1ee09ce7a1f7dca67fbf83cf9b07a6645a88ef52e65085a0dcbe17f6c063b53ff7c2f0f3ea4ef69e languageName: node linkType: hard @@ -8296,25 +7919,6 @@ __metadata: languageName: node linkType: hard -"extend-shallow@npm:^2.0.1": - version: 2.0.1 - resolution: "extend-shallow@npm:2.0.1" - dependencies: - is-extendable: ^0.1.0 - checksum: 8fb58d9d7a511f4baf78d383e637bd7d2e80843bd9cd0853649108ea835208fb614da502a553acc30208e1325240bb7cc4a68473021612496bb89725483656d8 - languageName: node - linkType: hard - -"extend-shallow@npm:^3.0.0, extend-shallow@npm:^3.0.2": - version: 3.0.2 - resolution: "extend-shallow@npm:3.0.2" - dependencies: - assign-symbols: ^1.0.0 - is-extendable: ^1.0.1 - checksum: a920b0cd5838a9995ace31dfd11ab5e79bf6e295aa566910ce53dff19f4b1c0fda2ef21f26b28586c7a2450ca2b42d97bd8c0f5cec9351a819222bf861e02461 - languageName: node - linkType: hard - "extend@npm:^3.0.0": version: 3.0.2 resolution: "extend@npm:3.0.2" @@ -8333,22 +7937,6 @@ __metadata: languageName: node linkType: hard -"extglob@npm:^2.0.4": - version: 2.0.4 - resolution: "extglob@npm:2.0.4" - dependencies: - array-unique: ^0.3.2 - define-property: ^1.0.0 - expand-brackets: ^2.1.4 - extend-shallow: ^2.0.1 - fragment-cache: ^0.2.1 - regex-not: ^1.0.0 - snapdragon: ^0.8.1 - to-regex: ^3.0.1 - checksum: a41531b8934735b684cef5e8c5a01d0f298d7d384500ceca38793a9ce098125aab04ee73e2d75d5b2901bc5dddd2b64e1b5e3bf19139ea48bac52af4a92f1d00 - languageName: node - linkType: hard - "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -8471,18 +8059,6 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^4.0.0": - version: 4.0.0 - resolution: "fill-range@npm:4.0.0" - dependencies: - extend-shallow: ^2.0.1 - is-number: ^3.0.0 - repeat-string: ^1.6.1 - to-regex-range: ^2.1.0 - checksum: dbb5102467786ab42bc7a3ec7380ae5d6bfd1b5177b2216de89e4a541193f8ba599a6db84651bd2c58c8921db41b8cc3d699ea83b477342d3ce404020f73c298 - languageName: node - linkType: hard - "fill-range@npm:^7.0.1": version: 7.0.1 resolution: "fill-range@npm:7.0.1" @@ -8573,13 +8149,6 @@ __metadata: languageName: node linkType: hard -"for-in@npm:^1.0.2": - version: 1.0.2 - resolution: "for-in@npm:1.0.2" - checksum: 09f4ae93ce785d253ac963d94c7f3432d89398bf25ac7a24ed034ca393bf74380bdeccc40e0f2d721a895e54211b07c8fad7132e8157827f6f7f059b70b4043d - languageName: node - linkType: hard - "foreground-child@npm:^3.1.0": version: 3.1.1 resolution: "foreground-child@npm:3.1.1" @@ -8590,17 +8159,6 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^3.0.0": - version: 3.0.1 - resolution: "form-data@npm:3.0.1" - dependencies: - asynckit: ^0.4.0 - combined-stream: ^1.0.8 - mime-types: ^2.1.12 - checksum: b019e8d35c8afc14a2bd8a7a92fa4f525a4726b6d5a9740e8d2623c30e308fbb58dc8469f90415a856698933c8479b01646a9dff33c87cc4e76d72aedbbf860d - languageName: node - linkType: hard - "form-data@npm:^4.0.0": version: 4.0.0 resolution: "form-data@npm:4.0.0" @@ -8619,15 +8177,6 @@ __metadata: languageName: node linkType: hard -"fragment-cache@npm:^0.2.1": - version: 0.2.1 - resolution: "fragment-cache@npm:0.2.1" - dependencies: - map-cache: ^0.2.2 - checksum: 1cbbd0b0116b67d5790175de0038a11df23c1cd2e8dcdbade58ebba5594c2d641dade6b4f126d82a7b4a6ffc2ea12e3d387dbb64ea2ae97cf02847d436f60fdc - languageName: node - linkType: hard - "free-style@npm:3.1.0": version: 3.1.0 resolution: "free-style@npm:3.1.0" @@ -8701,7 +8250,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.1.2, fsevents@npm:^2.3.2": +"fsevents@npm:^2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" dependencies: @@ -8711,7 +8260,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@^2.1.2#~builtin, fsevents@patch:fsevents@^2.3.2#~builtin": +"fsevents@patch:fsevents@^2.3.2#~builtin": version: 2.3.2 resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" dependencies: @@ -8792,7 +8341,7 @@ __metadata: languageName: node linkType: hard -"get-caller-file@npm:^2.0.1, get-caller-file@npm:^2.0.5": +"get-caller-file@npm:^2.0.5": version: 2.0.5 resolution: "get-caller-file@npm:2.0.5" checksum: b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9 @@ -8853,24 +8402,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^4.0.0": - version: 4.1.0 - resolution: "get-stream@npm:4.1.0" - dependencies: - pump: ^3.0.0 - checksum: 443e1914170c15bd52ff8ea6eff6dfc6d712b031303e36302d2778e3de2506af9ee964d6124010f7818736dcfde05c04ba7ca6cc26883106e084357a17ae7d73 - languageName: node - linkType: hard - -"get-stream@npm:^5.0.0": - version: 5.2.0 - resolution: "get-stream@npm:5.2.0" - dependencies: - pump: ^3.0.0 - checksum: 8bc1a23174a06b2b4ce600df38d6c98d2ef6d84e020c1ddad632ad75bac4e092eeb40e4c09e0761c35fc2dbc5e7fff5dab5e763a383582c4a167dd69a905bd12 - languageName: node - linkType: hard - "get-stream@npm:^6.0.0": version: 6.0.1 resolution: "get-stream@npm:6.0.1" @@ -8888,13 +8419,6 @@ __metadata: languageName: node linkType: hard -"get-value@npm:^2.0.3, get-value@npm:^2.0.6": - version: 2.0.6 - resolution: "get-value@npm:2.0.6" - checksum: 5c3b99cb5398ea8016bf46ff17afc5d1d286874d2ad38ca5edb6e87d75c0965b0094cb9a9dddef2c59c23d250702323539a7fbdd870620db38c7e7d7ec87c1eb - languageName: node - linkType: hard - "git-raw-commits@npm:^2.0.8": version: 2.0.11 resolution: "git-raw-commits@npm:2.0.11" @@ -9005,7 +8529,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4": +"glob@npm:^7.1.3, glob@npm:^7.1.4": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -9147,13 +8671,6 @@ __metadata: languageName: node linkType: hard -"growly@npm:^1.3.0": - version: 1.3.0 - resolution: "growly@npm:1.3.0" - checksum: 53cdecd4c16d7d9154a9061a9ccb87d602e957502ca69b529d7d1b2436c2c0b700ec544fc6b3e4cd115d59b81e62e44ce86bd0521403b579d3a2a97d7ce72a44 - languageName: node - linkType: hard - "gud@npm:^1.0.0": version: 1.0.0 resolution: "gud@npm:1.0.0" @@ -9253,45 +8770,6 @@ __metadata: languageName: node linkType: hard -"has-value@npm:^0.3.1": - version: 0.3.1 - resolution: "has-value@npm:0.3.1" - dependencies: - get-value: ^2.0.3 - has-values: ^0.1.4 - isobject: ^2.0.0 - checksum: 29e2a1e6571dad83451b769c7ce032fce6009f65bccace07c2962d3ad4d5530b6743d8f3229e4ecf3ea8e905d23a752c5f7089100c1f3162039fa6dc3976558f - languageName: node - linkType: hard - -"has-value@npm:^1.0.0": - version: 1.0.0 - resolution: "has-value@npm:1.0.0" - dependencies: - get-value: ^2.0.6 - has-values: ^1.0.0 - isobject: ^3.0.0 - checksum: b9421d354e44f03d3272ac39fd49f804f19bc1e4fa3ceef7745df43d6b402053f828445c03226b21d7d934a21ac9cf4bc569396dc312f496ddff873197bbd847 - languageName: node - linkType: hard - -"has-values@npm:^0.1.4": - version: 0.1.4 - resolution: "has-values@npm:0.1.4" - checksum: ab1c4bcaf811ccd1856c11cfe90e62fca9e2b026ebe474233a3d282d8d67e3b59ed85b622c7673bac3db198cb98bd1da2b39300a2f98e453729b115350af49bc - languageName: node - linkType: hard - -"has-values@npm:^1.0.0": - version: 1.0.0 - resolution: "has-values@npm:1.0.0" - dependencies: - is-number: ^3.0.0 - kind-of: ^4.0.0 - checksum: 77e6693f732b5e4cf6c38dfe85fdcefad0fab011af74995c3e83863fabf5e3a836f406d83565816baa0bc0a523c9410db8b990fe977074d61aeb6d8f4fcffa11 - languageName: node - linkType: hard - "has@npm:^1.0.3": version: 1.0.3 resolution: "has@npm:1.0.3" @@ -9481,15 +8959,6 @@ __metadata: languageName: node linkType: hard -"html-encoding-sniffer@npm:^2.0.1": - version: 2.0.1 - resolution: "html-encoding-sniffer@npm:2.0.1" - dependencies: - whatwg-encoding: ^1.0.5 - checksum: bf30cce461015ed7e365736fcd6a3063c7bc016a91f74398ef6158886970a96333938f7c02417ab3c12aa82e3e53b40822145facccb9ddfbcdc15a879ae4d7ba - languageName: node - linkType: hard - "html-encoding-sniffer@npm:^3.0.0": version: 3.0.0 resolution: "html-encoding-sniffer@npm:3.0.0" @@ -9532,17 +9001,6 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^4.0.1": - version: 4.0.1 - resolution: "http-proxy-agent@npm:4.0.1" - dependencies: - "@tootallnate/once": 1 - agent-base: 6 - debug: 4 - checksum: c6a5da5a1929416b6bbdf77b1aca13888013fe7eb9d59fc292e25d18e041bb154a8dfada58e223fc7b76b9b2d155a87e92e608235201f77d34aa258707963a82 - languageName: node - linkType: hard - "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" @@ -9564,13 +9022,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^1.1.1": - version: 1.1.1 - resolution: "human-signals@npm:1.1.1" - checksum: d587647c9e8ec24e02821b6be7de5a0fc37f591f6c4e319b3054b43fd4c35a70a94c46fc74d8c1a43c47fde157d23acd7421f375e1c1365b09a16835b8300205 - languageName: node - linkType: hard - "human-signals@npm:^2.1.0": version: 2.1.0 resolution: "human-signals@npm:2.1.0" @@ -9587,15 +9038,6 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.4.24, iconv-lite@npm:^0.4.24": - version: 0.4.24 - resolution: "iconv-lite@npm:0.4.24" - dependencies: - safer-buffer: ">= 2.1.2 < 3" - checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 - languageName: node - linkType: hard - "iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" @@ -9605,6 +9047,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:^0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: ">= 2.1.2 < 3" + checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 + languageName: node + linkType: hard + "icss-utils@npm:^5.0.0, icss-utils@npm:^5.1.0": version: 5.1.0 resolution: "icss-utils@npm:5.1.0" @@ -9836,24 +9287,6 @@ __metadata: languageName: node linkType: hard -"is-accessor-descriptor@npm:^0.1.6": - version: 0.1.6 - resolution: "is-accessor-descriptor@npm:0.1.6" - dependencies: - kind-of: ^3.0.2 - checksum: 3d629a086a9585bc16a83a8e8a3416f400023301855cafb7ccc9a1d63145b7480f0ad28877dcc2cce09492c4ec1c39ef4c071996f24ee6ac626be4217b8ffc8a - languageName: node - linkType: hard - -"is-accessor-descriptor@npm:^1.0.0": - version: 1.0.0 - resolution: "is-accessor-descriptor@npm:1.0.0" - dependencies: - kind-of: ^6.0.0 - checksum: 8e475968e9b22f9849343c25854fa24492dbe8ba0dea1a818978f9f1b887339190b022c9300d08c47fe36f1b913d70ce8cbaca00369c55a56705fdb7caed37fe - languageName: node - linkType: hard - "is-alphabetical@npm:^1.0.0": version: 1.0.4 resolution: "is-alphabetical@npm:1.0.4" @@ -9918,13 +9351,6 @@ __metadata: languageName: node linkType: hard -"is-buffer@npm:^1.1.5": - version: 1.1.6 - resolution: "is-buffer@npm:1.1.6" - checksum: 4a186d995d8bbf9153b4bd9ff9fd04ae75068fe695d29025d25e592d9488911eeece84eefbd8fa41b8ddcc0711058a71d4c466dcf6f1f6e1d83830052d8ca707 - languageName: node - linkType: hard - "is-buffer@npm:^2.0.0": version: 2.0.5 resolution: "is-buffer@npm:2.0.5" @@ -9939,7 +9365,7 @@ __metadata: languageName: node linkType: hard -"is-ci@npm:2.0.0, is-ci@npm:^2.0.0": +"is-ci@npm:2.0.0": version: 2.0.0 resolution: "is-ci@npm:2.0.0" dependencies: @@ -9959,24 +9385,6 @@ __metadata: languageName: node linkType: hard -"is-data-descriptor@npm:^0.1.4": - version: 0.1.4 - resolution: "is-data-descriptor@npm:0.1.4" - dependencies: - kind-of: ^3.0.2 - checksum: 5c622e078ba933a78338ae398a3d1fc5c23332b395312daf4f74bab4afb10d061cea74821add726cb4db8b946ba36217ee71a24fe71dd5bca4632edb7f6aad87 - languageName: node - linkType: hard - -"is-data-descriptor@npm:^1.0.0": - version: 1.0.0 - resolution: "is-data-descriptor@npm:1.0.0" - dependencies: - kind-of: ^6.0.0 - checksum: e705e6816241c013b05a65dc452244ee378d1c3e3842bd140beabe6e12c0d700ef23c91803f971aa7b091fb0573c5da8963af34a2b573337d87bc3e1f53a4e6d - languageName: node - linkType: hard - "is-date-object@npm:^1.0.1": version: 1.0.5 resolution: "is-date-object@npm:1.0.5" @@ -9993,28 +9401,6 @@ __metadata: languageName: node linkType: hard -"is-descriptor@npm:^0.1.0": - version: 0.1.6 - resolution: "is-descriptor@npm:0.1.6" - dependencies: - is-accessor-descriptor: ^0.1.6 - is-data-descriptor: ^0.1.4 - kind-of: ^5.0.0 - checksum: 0f780c1b46b465f71d970fd7754096ffdb7b69fd8797ca1f5069c163eaedcd6a20ec4a50af669075c9ebcfb5266d2e53c8b227e485eefdb0d1fee09aa1dd8ab6 - languageName: node - linkType: hard - -"is-descriptor@npm:^1.0.0, is-descriptor@npm:^1.0.2": - version: 1.0.2 - resolution: "is-descriptor@npm:1.0.2" - dependencies: - is-accessor-descriptor: ^1.0.0 - is-data-descriptor: ^1.0.0 - kind-of: ^6.0.2 - checksum: 2ed623560bee035fb67b23e32ce885700bef8abe3fbf8c909907d86507b91a2c89a9d3a4d835a4d7334dd5db0237a0aeae9ca109c1e4ef1c0e7b577c0846ab5a - languageName: node - linkType: hard - "is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": version: 2.2.1 resolution: "is-docker@npm:2.2.1" @@ -10024,22 +9410,6 @@ __metadata: languageName: node linkType: hard -"is-extendable@npm:^0.1.0, is-extendable@npm:^0.1.1": - version: 0.1.1 - resolution: "is-extendable@npm:0.1.1" - checksum: 3875571d20a7563772ecc7a5f36cb03167e9be31ad259041b4a8f73f33f885441f778cee1f1fe0085eb4bc71679b9d8c923690003a36a6a5fdf8023e6e3f0672 - languageName: node - linkType: hard - -"is-extendable@npm:^1.0.1": - version: 1.0.1 - resolution: "is-extendable@npm:1.0.1" - dependencies: - is-plain-object: ^2.0.4 - checksum: db07bc1e9de6170de70eff7001943691f05b9d1547730b11be01c0ebfe67362912ba743cf4be6fd20a5e03b4180c685dad80b7c509fe717037e3eee30ad8e84f - languageName: node - linkType: hard - "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -10107,15 +9477,6 @@ __metadata: languageName: node linkType: hard -"is-number@npm:^3.0.0": - version: 3.0.0 - resolution: "is-number@npm:3.0.0" - dependencies: - kind-of: ^3.0.2 - checksum: 0c62bf8e9d72c4dd203a74d8cfc751c746e75513380fef420cda8237e619a988ee43e678ddb23c87ac24d91ac0fe9f22e4ffb1301a50310c697e9d73ca3994e9 - languageName: node - linkType: hard - "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -10158,7 +9519,7 @@ __metadata: languageName: node linkType: hard -"is-plain-object@npm:^2.0.3, is-plain-object@npm:^2.0.4": +"is-plain-object@npm:^2.0.4": version: 2.0.4 resolution: "is-plain-object@npm:2.0.4" dependencies: @@ -10216,13 +9577,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^1.1.0": - version: 1.1.0 - resolution: "is-stream@npm:1.1.0" - checksum: 063c6bec9d5647aa6d42108d4c59723d2bd4ae42135a2d4db6eadbd49b7ea05b750fd69d279e5c7c45cf9da753ad2c00d8978be354d65aa9f6bb434969c6a2ae - languageName: node - linkType: hard - "is-stream@npm:^2.0.0": version: 2.0.1 resolution: "is-stream@npm:2.0.1" @@ -10266,13 +9620,6 @@ __metadata: languageName: node linkType: hard -"is-typedarray@npm:^1.0.0": - version: 1.0.0 - resolution: "is-typedarray@npm:1.0.0" - checksum: 3508c6cd0a9ee2e0df2fa2e9baabcdc89e911c7bd5cf64604586697212feec525aa21050e48affb5ffc3df20f0f5d2e2cf79b08caa64e1ccc9578e251763aef7 - languageName: node - linkType: hard - "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -10289,13 +9636,6 @@ __metadata: languageName: node linkType: hard -"is-windows@npm:^1.0.2": - version: 1.0.2 - resolution: "is-windows@npm:1.0.2" - checksum: 438b7e52656fe3b9b293b180defb4e448088e7023a523ec21a91a80b9ff8cdb3377ddb5b6e60f7c7de4fa8b63ab56e121b6705fe081b3cf1b828b0a380009ad7 - languageName: node - linkType: hard - "is-wsl@npm:^2.2.0": version: 2.2.0 resolution: "is-wsl@npm:2.2.0" @@ -10305,13 +9645,6 @@ __metadata: languageName: node linkType: hard -"isarray@npm:1.0.0, isarray@npm:~1.0.0": - version: 1.0.0 - resolution: "isarray@npm:1.0.0" - checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab - languageName: node - linkType: hard - "isarray@npm:^2.0.5": version: 2.0.5 resolution: "isarray@npm:2.0.5" @@ -10319,6 +9652,13 @@ __metadata: languageName: node linkType: hard +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -10326,16 +9666,7 @@ __metadata: languageName: node linkType: hard -"isobject@npm:^2.0.0": - version: 2.1.0 - resolution: "isobject@npm:2.1.0" - dependencies: - isarray: 1.0.0 - checksum: 811c6f5a866877d31f0606a88af4a45f282544de886bf29f6a34c46616a1ae2ed17076cc6bf34c0128f33eecf7e1fcaa2c82cf3770560d3e26810894e96ae79f - languageName: node - linkType: hard - -"isobject@npm:^3.0.0, isobject@npm:^3.0.1": +"isobject@npm:^3.0.1": version: 3.0.1 resolution: "isobject@npm:3.0.1" checksum: db85c4c970ce30693676487cca0e61da2ca34e8d4967c2e1309143ff910c207133a969f9e4ddb2dc6aba670aabce4e0e307146c310350b298e74a31f7d464703 @@ -10356,18 +9687,6 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-instrument@npm:^4.0.3": - version: 4.0.3 - resolution: "istanbul-lib-instrument@npm:4.0.3" - dependencies: - "@babel/core": ^7.7.5 - "@istanbuljs/schema": ^0.1.2 - istanbul-lib-coverage: ^3.0.0 - semver: ^6.3.0 - checksum: fa1171d3022b1bb8f6a734042620ac5d9ee7dc80f3065a0bb12863e9f0494d0eefa3d86608fcc0254ab2765d29d7dad8bdc42e5f8df2f9a1fbe85ccc59d76cb9 - languageName: node - linkType: hard - "istanbul-lib-instrument@npm:^5.0.4, istanbul-lib-instrument@npm:^5.1.0": version: 5.2.1 resolution: "istanbul-lib-instrument@npm:5.2.1" @@ -10403,7 +9722,7 @@ __metadata: languageName: node linkType: hard -"istanbul-reports@npm:^3.0.2, istanbul-reports@npm:^3.1.3": +"istanbul-reports@npm:^3.1.3": version: 3.1.6 resolution: "istanbul-reports@npm:3.1.6" dependencies: @@ -10440,17 +9759,6 @@ __metadata: languageName: node linkType: hard -"jest-changed-files@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-changed-files@npm:26.6.2" - dependencies: - "@jest/types": ^26.6.2 - execa: ^4.0.0 - throat: ^5.0.0 - checksum: 8c405f5ff905ee69ace9fd39355233206e3e233badf6a3f3b27e45bbf0a46d86943430be2e080d25b1e085f4231b9b3b27c94317aa04116efb40b592184066f4 - languageName: node - linkType: hard - "jest-changed-files@npm:^29.5.0": version: 29.5.0 resolution: "jest-changed-files@npm:29.5.0" @@ -10489,26 +9797,31 @@ __metadata: languageName: node linkType: hard -"jest-cli@npm:^26.6.3": - version: 26.6.3 - resolution: "jest-cli@npm:26.6.3" +"jest-circus@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-circus@npm:29.6.2" dependencies: - "@jest/core": ^26.6.3 - "@jest/test-result": ^26.6.2 - "@jest/types": ^26.6.2 + "@jest/environment": ^29.6.2 + "@jest/expect": ^29.6.2 + "@jest/test-result": ^29.6.2 + "@jest/types": ^29.6.1 + "@types/node": "*" chalk: ^4.0.0 - exit: ^0.1.2 - graceful-fs: ^4.2.4 - import-local: ^3.0.2 - is-ci: ^2.0.0 - jest-config: ^26.6.3 - jest-util: ^26.6.2 - jest-validate: ^26.6.2 - prompts: ^2.0.1 - yargs: ^15.4.1 - bin: - jest: bin/jest.js - checksum: c8554147be756f09f5566974f0026485f78742e8642d2723f8fbee5746f50f44fb72b17aad181226655a8446d3ecc8ad8ed0a11a8a55686fa2b9c10d85700121 + co: ^4.6.0 + dedent: ^1.0.0 + is-generator-fn: ^2.0.0 + jest-each: ^29.6.2 + jest-matcher-utils: ^29.6.2 + jest-message-util: ^29.6.2 + jest-runtime: ^29.6.2 + jest-snapshot: ^29.6.2 + jest-util: ^29.6.2 + p-limit: ^3.1.0 + pretty-format: ^29.6.2 + pure-rand: ^6.0.0 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 4f5a96a68c3c808c3d5a9279a2f39a2937386e2cebba5096971f267d79562ce2133a13bc05356a39f8f1ba68fcfe1eb39c4572b3fb0f91affbd932950e89c1e3 languageName: node linkType: hard @@ -10539,34 +9852,30 @@ __metadata: languageName: node linkType: hard -"jest-config@npm:^26.6.3": - version: 26.6.3 - resolution: "jest-config@npm:26.6.3" +"jest-cli@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-cli@npm:29.6.2" dependencies: - "@babel/core": ^7.1.0 - "@jest/test-sequencer": ^26.6.3 - "@jest/types": ^26.6.2 - babel-jest: ^26.6.3 + "@jest/core": ^29.6.2 + "@jest/test-result": ^29.6.2 + "@jest/types": ^29.6.1 chalk: ^4.0.0 - deepmerge: ^4.2.2 - glob: ^7.1.1 - graceful-fs: ^4.2.4 - jest-environment-jsdom: ^26.6.2 - jest-environment-node: ^26.6.2 - jest-get-type: ^26.3.0 - jest-jasmine2: ^26.6.3 - jest-regex-util: ^26.0.0 - jest-resolve: ^26.6.2 - jest-util: ^26.6.2 - jest-validate: ^26.6.2 - micromatch: ^4.0.2 - pretty-format: ^26.6.2 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + import-local: ^3.0.2 + jest-config: ^29.6.2 + jest-util: ^29.6.2 + jest-validate: ^29.6.2 + prompts: ^2.0.1 + yargs: ^17.3.1 peerDependencies: - ts-node: ">=9.0.0" + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: - ts-node: + node-notifier: optional: true - checksum: 303c798582d3c5d4b4e6ab8a4d91a83ded28e4ebbc0bcfc1ad271f9864437ef5409b7c7773010143811bc8176b0695c096717b91419c6484b56dcc032560a74b + bin: + jest: bin/jest.js + checksum: 0b7b09ae4bd327caf1981eac5a14679ddda3c5c836c9f8ea0ecfe1e5e10e9a39a5ed783fa38d25383604c4d3405595e74b391d955e99aea7e51acb41a59ea108 languageName: node linkType: hard @@ -10608,15 +9917,41 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:^26.0.0, jest-diff@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-diff@npm:26.6.2" +"jest-config@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-config@npm:29.6.2" dependencies: + "@babel/core": ^7.11.6 + "@jest/test-sequencer": ^29.6.2 + "@jest/types": ^29.6.1 + babel-jest: ^29.6.2 chalk: ^4.0.0 - diff-sequences: ^26.6.2 - jest-get-type: ^26.3.0 - pretty-format: ^26.6.2 - checksum: d00d297f31e1ac0252127089892432caa7a11c69bde29cf3bb6c7a839c8afdb95cf1fd401f9df16a4422745da2e6a5d94b428b30666a2540c38e1c5699915c2d + ci-info: ^3.2.0 + deepmerge: ^4.2.2 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-circus: ^29.6.2 + jest-environment-node: ^29.6.2 + jest-get-type: ^29.4.3 + jest-regex-util: ^29.4.3 + jest-resolve: ^29.6.2 + jest-runner: ^29.6.2 + jest-util: ^29.6.2 + jest-validate: ^29.6.2 + micromatch: ^4.0.4 + parse-json: ^5.2.0 + pretty-format: ^29.6.2 + slash: ^3.0.0 + strip-json-comments: ^3.1.1 + peerDependencies: + "@types/node": "*" + ts-node: ">=9.0.0" + peerDependenciesMeta: + "@types/node": + optional: true + ts-node: + optional: true + checksum: 3bd104a3ac2dd9d34986238142437606354169766dcf88359a7a12ac106d0dc17dcc6b627e4f20db97a58bac5b0502b5436c9cc4722b3629b2a114bba6da9128 languageName: node linkType: hard @@ -10632,12 +9967,15 @@ __metadata: languageName: node linkType: hard -"jest-docblock@npm:^26.0.0": - version: 26.0.0 - resolution: "jest-docblock@npm:26.0.0" +"jest-diff@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-diff@npm:29.6.2" dependencies: - detect-newline: ^3.0.0 - checksum: e03ef104ee8c571335e6fa394b8fc8d2bd87eec9fe8b3d7d9aac056ada7de288f37ee8ac4922bb3a4222ac304db975d8832d5abc85486092866c534a16847cd5 + chalk: ^4.0.0 + diff-sequences: ^29.4.3 + jest-get-type: ^29.4.3 + pretty-format: ^29.6.2 + checksum: 0effd66a0c23f8c139ebf7ca99ed30b479b86fff66f19ad4869f130aaf7ae6a24ca1533f697b7e4930cbe2ddffc85387723fcca673501c653fb77a38f538e959 languageName: node linkType: hard @@ -10650,19 +9988,6 @@ __metadata: languageName: node linkType: hard -"jest-each@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-each@npm:26.6.2" - dependencies: - "@jest/types": ^26.6.2 - chalk: ^4.0.0 - jest-get-type: ^26.3.0 - jest-util: ^26.6.2 - pretty-format: ^26.6.2 - checksum: 4e00ea4667e4fe015b894dc698cce0ae695cf458e021e5da62d4a5b052cd2c0a878da93f8c97cbdde60bcecf70982e8d3a7a5d63e1588f59531cc797a18c39ef - languageName: node - linkType: hard - "jest-each@npm:^29.6.1": version: 29.6.1 resolution: "jest-each@npm:29.6.1" @@ -10676,18 +10001,16 @@ __metadata: languageName: node linkType: hard -"jest-environment-jsdom@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-environment-jsdom@npm:26.6.2" +"jest-each@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-each@npm:29.6.2" dependencies: - "@jest/environment": ^26.6.2 - "@jest/fake-timers": ^26.6.2 - "@jest/types": ^26.6.2 - "@types/node": "*" - jest-mock: ^26.6.2 - jest-util: ^26.6.2 - jsdom: ^16.4.0 - checksum: 8af9ffdf1b147362a19032bfe9ed51b709d43c74dc4b1c45e56d721808bf6cabdca8c226855b55a985ea196ce51cdb171bfe420ceec3daa2d13818d5c1915890 + "@jest/types": ^29.6.1 + chalk: ^4.0.0 + jest-get-type: ^29.4.3 + jest-util: ^29.6.2 + pretty-format: ^29.6.2 + checksum: b64194f4ca27afc6070a42b7ecccbc68be0ded19a849f8cd8f91a2abb23fadae2d38d47559a315f4d1f576927761f3ea437a75ab6cf19206332abb8527d7c165 languageName: node linkType: hard @@ -10712,20 +10035,6 @@ __metadata: languageName: node linkType: hard -"jest-environment-node@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-environment-node@npm:26.6.2" - dependencies: - "@jest/environment": ^26.6.2 - "@jest/fake-timers": ^26.6.2 - "@jest/types": ^26.6.2 - "@types/node": "*" - jest-mock: ^26.6.2 - jest-util: ^26.6.2 - checksum: 0b69b481e6d6f2350ed241c2dabc70b0b1f3a00f9a410b7dad97c8ab38e88026acf7445ca663eb314f46ff50acee0133100b1006bf4ebda5298ffb02763a6861 - languageName: node - linkType: hard - "jest-environment-node@npm:^29.6.1": version: 29.6.1 resolution: "jest-environment-node@npm:29.6.1" @@ -10740,42 +10049,24 @@ __metadata: languageName: node linkType: hard -"jest-get-type@npm:^26.3.0": - version: 26.3.0 - resolution: "jest-get-type@npm:26.3.0" - checksum: 1cc6465ae4f5e880be22ba52fd270fa64c21994915f81b41f8f7553a7957dd8e077cc8d03035de9412e2d739f8bad6a032ebb5dab5805692a5fb9e20dd4ea666 - languageName: node - linkType: hard - -"jest-get-type@npm:^29.4.3": - version: 29.4.3 - resolution: "jest-get-type@npm:29.4.3" - checksum: 6ac7f2dde1c65e292e4355b6c63b3a4897d7e92cb4c8afcf6d397f2682f8080e094c8b0b68205a74d269882ec06bf696a9de6cd3e1b7333531e5ed7b112605ce - languageName: node - linkType: hard - -"jest-haste-map@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-haste-map@npm:26.6.2" +"jest-environment-node@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-environment-node@npm:29.6.2" dependencies: - "@jest/types": ^26.6.2 - "@types/graceful-fs": ^4.1.2 + "@jest/environment": ^29.6.2 + "@jest/fake-timers": ^29.6.2 + "@jest/types": ^29.6.1 "@types/node": "*" - anymatch: ^3.0.3 - fb-watchman: ^2.0.0 - fsevents: ^2.1.2 - graceful-fs: ^4.2.4 - jest-regex-util: ^26.0.0 - jest-serializer: ^26.6.2 - jest-util: ^26.6.2 - jest-worker: ^26.6.2 - micromatch: ^4.0.2 - sane: ^4.0.3 - walker: ^1.0.7 - dependenciesMeta: - fsevents: - optional: true - checksum: 8ad5236d5646d2388d2bd58a57ea53698923434f43d59ea9ebdc58bce4d0b8544c8de2f7acaa9a6d73171f04460388b2b6d7d6b6c256aea4ebb8780140781596 + jest-mock: ^29.6.2 + jest-util: ^29.6.2 + checksum: 0b754ac2d3bdb7ce5d6fc28595b9d1c64176f20506b6f773b18b0280ab0b396ed7d927c8519779d3c560fa2b13236ee7077092ccb19a13bea23d40dd30f06450 + languageName: node + linkType: hard + +"jest-get-type@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-get-type@npm:29.4.3" + checksum: 6ac7f2dde1c65e292e4355b6c63b3a4897d7e92cb4c8afcf6d397f2682f8080e094c8b0b68205a74d269882ec06bf696a9de6cd3e1b7333531e5ed7b112605ce languageName: node linkType: hard @@ -10802,29 +10093,26 @@ __metadata: languageName: node linkType: hard -"jest-jasmine2@npm:^26.6.3": - version: 26.6.3 - resolution: "jest-jasmine2@npm:26.6.3" +"jest-haste-map@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-haste-map@npm:29.6.2" dependencies: - "@babel/traverse": ^7.1.0 - "@jest/environment": ^26.6.2 - "@jest/source-map": ^26.6.2 - "@jest/test-result": ^26.6.2 - "@jest/types": ^26.6.2 + "@jest/types": ^29.6.1 + "@types/graceful-fs": ^4.1.3 "@types/node": "*" - chalk: ^4.0.0 - co: ^4.6.0 - expect: ^26.6.2 - is-generator-fn: ^2.0.0 - jest-each: ^26.6.2 - jest-matcher-utils: ^26.6.2 - jest-message-util: ^26.6.2 - jest-runtime: ^26.6.3 - jest-snapshot: ^26.6.2 - jest-util: ^26.6.2 - pretty-format: ^26.6.2 - throat: ^5.0.0 - checksum: 41df0b993ae0cdeb2660fb3d8e88e2dcc83aec6b5c27d85eb233c2d507b546f8dce45fc54898ffbefa48ccc4633f225d0e023fd0979b8f7f2f1626074a69a9a3 + anymatch: ^3.0.3 + fb-watchman: ^2.0.0 + fsevents: ^2.3.2 + graceful-fs: ^4.2.9 + jest-regex-util: ^29.4.3 + jest-util: ^29.6.2 + jest-worker: ^29.6.2 + micromatch: ^4.0.4 + walker: ^1.0.8 + dependenciesMeta: + fsevents: + optional: true + checksum: 726233972030eb2e5bce6c9468e497310436b455c88b40e744bd053e20a6f3ff19aec340edcbd89537c629ed5cf8916506bc895d690cc39a0862c74dcd95b7b8 languageName: node linkType: hard @@ -10840,16 +10128,6 @@ __metadata: languageName: node linkType: hard -"jest-leak-detector@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-leak-detector@npm:26.6.2" - dependencies: - jest-get-type: ^26.3.0 - pretty-format: ^26.6.2 - checksum: 364dd4d021347e26c66ba9c09da8a30477f14a3a8a208d2d7d64e4c396db81b85d8cb6b6834bcfc47a61b5938e274553957d11a7de2255f058c9d55d7f8fdfe7 - languageName: node - linkType: hard - "jest-leak-detector@npm:^29.6.1": version: 29.6.1 resolution: "jest-leak-detector@npm:29.6.1" @@ -10860,15 +10138,13 @@ __metadata: languageName: node linkType: hard -"jest-matcher-utils@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-matcher-utils@npm:26.6.2" +"jest-leak-detector@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-leak-detector@npm:29.6.2" dependencies: - chalk: ^4.0.0 - jest-diff: ^26.6.2 - jest-get-type: ^26.3.0 - pretty-format: ^26.6.2 - checksum: 74d2165c1ac7fe98fe27cd2b5407499478e6b2fe99dd54e26d8ee5c9f5f913bdd7bdc07c7221b9b04df0c15e9be0e866ff3455b03e38cc66c480d9996d6d5405 + jest-get-type: ^29.4.3 + pretty-format: ^29.6.2 + checksum: e00152acdba8aa8f9334775b77375947508051c34646fbeb702275da2b6ac6145f8cad6d5893112e76484d00fa8c0b4fd71b78ab0b4ef34950f5b6a84f37ae67 languageName: node linkType: hard @@ -10884,20 +10160,15 @@ __metadata: languageName: node linkType: hard -"jest-message-util@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-message-util@npm:26.6.2" +"jest-matcher-utils@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-matcher-utils@npm:29.6.2" dependencies: - "@babel/code-frame": ^7.0.0 - "@jest/types": ^26.6.2 - "@types/stack-utils": ^2.0.0 chalk: ^4.0.0 - graceful-fs: ^4.2.4 - micromatch: ^4.0.2 - pretty-format: ^26.6.2 - slash: ^3.0.0 - stack-utils: ^2.0.2 - checksum: ffe5a715591c41240b9ed4092faf10f3eaf9ddfdf25d257a0c9f903aaa8d9eed5baa7e38016d2ec4f610fd29225e0f5231a91153e087a043e62824972c83d015 + jest-diff: ^29.6.2 + jest-get-type: ^29.4.3 + pretty-format: ^29.6.2 + checksum: 3e1b65dd30d05f75fe56dc45fbe4135aec2ff96a3d1e21afbf6a66f3a45a7e29cd0fd37cf80b9564e0381d6205833f77ccaf766c6f7e1aad6b7924d117be504e languageName: node linkType: hard @@ -10918,13 +10189,20 @@ __metadata: languageName: node linkType: hard -"jest-mock@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-mock@npm:26.6.2" +"jest-message-util@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-message-util@npm:29.6.2" dependencies: - "@jest/types": ^26.6.2 - "@types/node": "*" - checksum: 6c0fe028ff0cdc87b5d63b9ca749af04cae6c5577aaab234f602e546cae3f4b932adac9d77e6de2abb24955ee00978e1e5d5a861725654e2f9a42317d91fbc1f + "@babel/code-frame": ^7.12.13 + "@jest/types": ^29.6.1 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^29.6.2 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: e8e3c8d2301e2ca4038ed6df8cbba7fedc6949d1ede4c0e3f1f44f53afb56d77eb35983fa460140d0eadeab99a5f3ae04b703fe77cd7b316b40b361228b5aa1a languageName: node linkType: hard @@ -10939,6 +10217,17 @@ __metadata: languageName: node linkType: hard +"jest-mock@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-mock@npm:29.6.2" + dependencies: + "@jest/types": ^29.6.1 + "@types/node": "*" + jest-util: ^29.6.2 + checksum: 0bacb5d58441462c0e531ec4d2f7377eecbe21f664d8a460e72f94ba61d22635028931678e7a0f1c3e3f5894973db8e409432f7db4c01283456c8fdbd85f5b3b + languageName: node + linkType: hard + "jest-pnp-resolver@npm:^1.2.2": version: 1.2.3 resolution: "jest-pnp-resolver@npm:1.2.3" @@ -10951,13 +10240,6 @@ __metadata: languageName: node linkType: hard -"jest-regex-util@npm:^26.0.0": - version: 26.0.0 - resolution: "jest-regex-util@npm:26.0.0" - checksum: 930a00665e8dfbedc29140678b4a54f021b41b895cf35050f76f557c1da3ac48ff42dd7b18ba2ccba6f4e518c6445d6753730d03ec7049901b93992db1ef0483 - languageName: node - linkType: hard - "jest-regex-util@npm:^29.4.3": version: 29.4.3 resolution: "jest-regex-util@npm:29.4.3" @@ -10965,17 +10247,6 @@ __metadata: languageName: node linkType: hard -"jest-resolve-dependencies@npm:^26.6.3": - version: 26.6.3 - resolution: "jest-resolve-dependencies@npm:26.6.3" - dependencies: - "@jest/types": ^26.6.2 - jest-regex-util: ^26.0.0 - jest-snapshot: ^26.6.2 - checksum: 533ea1e271426006ff02c03c9802b108fcd68f2144615b6110ae59f3a0a2cc4a7abb3f44c3c65299c76b3a725d5d8220aaed9c58b79c8c8c508c18699a96e3f7 - languageName: node - linkType: hard - "jest-resolve-dependencies@npm:^29.6.1": version: 29.6.1 resolution: "jest-resolve-dependencies@npm:29.6.1" @@ -10986,19 +10257,13 @@ __metadata: languageName: node linkType: hard -"jest-resolve@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-resolve@npm:26.6.2" +"jest-resolve-dependencies@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-resolve-dependencies@npm:29.6.2" dependencies: - "@jest/types": ^26.6.2 - chalk: ^4.0.0 - graceful-fs: ^4.2.4 - jest-pnp-resolver: ^1.2.2 - jest-util: ^26.6.2 - read-pkg-up: ^7.0.1 - resolve: ^1.18.1 - slash: ^3.0.0 - checksum: d6264d3f39b098753802a237c8c54f3109f5f3b3b7fa6f8d7aec7dca01b357ddf518ce1c33a68454357c15f48fb3c6026a92b9c4f5d72f07e24e80f04bcc8d58 + jest-regex-util: ^29.4.3 + jest-snapshot: ^29.6.2 + checksum: d40ee11af2c9d2ef0dbbcf9a5b7dda37c2b86cf4e5de1705795919fd8927907569115c502116ab56de0dca576d5faa31ec9b636240333b6830a568a63004da17 languageName: node linkType: hard @@ -11019,31 +10284,20 @@ __metadata: languageName: node linkType: hard -"jest-runner@npm:^26.6.3": - version: 26.6.3 - resolution: "jest-runner@npm:26.6.3" +"jest-resolve@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-resolve@npm:29.6.2" dependencies: - "@jest/console": ^26.6.2 - "@jest/environment": ^26.6.2 - "@jest/test-result": ^26.6.2 - "@jest/types": ^26.6.2 - "@types/node": "*" chalk: ^4.0.0 - emittery: ^0.7.1 - exit: ^0.1.2 - graceful-fs: ^4.2.4 - jest-config: ^26.6.3 - jest-docblock: ^26.0.0 - jest-haste-map: ^26.6.2 - jest-leak-detector: ^26.6.2 - jest-message-util: ^26.6.2 - jest-resolve: ^26.6.2 - jest-runtime: ^26.6.3 - jest-util: ^26.6.2 - jest-worker: ^26.6.2 - source-map-support: ^0.5.6 - throat: ^5.0.0 - checksum: ccd69918baa49a5efa45985cf60cfa1fbb1686b32d7a86296b7b55f89684e36d1f08e62598c4b7be7e81f2cf2e245d1a65146ea7bdcaedfa6ed176d3e645d7e2 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.2 + jest-pnp-resolver: ^1.2.2 + jest-util: ^29.6.2 + jest-validate: ^29.6.2 + resolve: ^1.20.0 + resolve.exports: ^2.0.0 + slash: ^3.0.0 + checksum: 01721957e61821a576b2ded043eeab8b392166e0e6d8d680f75657737e2ea7481ff29c2716b866ccd12e743f3a8da465504b1028e78b6a3c68b9561303de7ec8 languageName: node linkType: hard @@ -11076,40 +10330,32 @@ __metadata: languageName: node linkType: hard -"jest-runtime@npm:^26.6.3": - version: 26.6.3 - resolution: "jest-runtime@npm:26.6.3" +"jest-runner@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-runner@npm:29.6.2" dependencies: - "@jest/console": ^26.6.2 - "@jest/environment": ^26.6.2 - "@jest/fake-timers": ^26.6.2 - "@jest/globals": ^26.6.2 - "@jest/source-map": ^26.6.2 - "@jest/test-result": ^26.6.2 - "@jest/transform": ^26.6.2 - "@jest/types": ^26.6.2 - "@types/yargs": ^15.0.0 + "@jest/console": ^29.6.2 + "@jest/environment": ^29.6.2 + "@jest/test-result": ^29.6.2 + "@jest/transform": ^29.6.2 + "@jest/types": ^29.6.1 + "@types/node": "*" chalk: ^4.0.0 - cjs-module-lexer: ^0.6.0 - collect-v8-coverage: ^1.0.0 - exit: ^0.1.2 - glob: ^7.1.3 - graceful-fs: ^4.2.4 - jest-config: ^26.6.3 - jest-haste-map: ^26.6.2 - jest-message-util: ^26.6.2 - jest-mock: ^26.6.2 - jest-regex-util: ^26.0.0 - jest-resolve: ^26.6.2 - jest-snapshot: ^26.6.2 - jest-util: ^26.6.2 - jest-validate: ^26.6.2 - slash: ^3.0.0 - strip-bom: ^4.0.0 - yargs: ^15.4.1 - bin: - jest-runtime: bin/jest-runtime.js - checksum: 867922b49f9ab4cf2f5f1356ac3d9962c4477c7a2ff696cc841ea4c600ea389e7d6dfcbf945fec6849e606f81980addf31e4f34d63eaa3d3415f4901de2f605a + emittery: ^0.13.1 + graceful-fs: ^4.2.9 + jest-docblock: ^29.4.3 + jest-environment-node: ^29.6.2 + jest-haste-map: ^29.6.2 + jest-leak-detector: ^29.6.2 + jest-message-util: ^29.6.2 + jest-resolve: ^29.6.2 + jest-runtime: ^29.6.2 + jest-util: ^29.6.2 + jest-watcher: ^29.6.2 + jest-worker: ^29.6.2 + p-limit: ^3.1.0 + source-map-support: 0.5.13 + checksum: 46bd506a08ddf79628a509aed4105ab74c0b03727a3e24c90bbc2915531860b3da99f7ace2fd9603194440553cffac9cfb1a3b7d0ce03d5fc9c5f2d5ffbb3d3f languageName: node linkType: hard @@ -11143,37 +10389,33 @@ __metadata: languageName: node linkType: hard -"jest-serializer@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-serializer@npm:26.6.2" +"jest-runtime@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-runtime@npm:29.6.2" dependencies: + "@jest/environment": ^29.6.2 + "@jest/fake-timers": ^29.6.2 + "@jest/globals": ^29.6.2 + "@jest/source-map": ^29.6.0 + "@jest/test-result": ^29.6.2 + "@jest/transform": ^29.6.2 + "@jest/types": ^29.6.1 "@types/node": "*" - graceful-fs: ^4.2.4 - checksum: dbecfb0d01462fe486a0932cf1680cf6abb204c059db2a8f72c6c2a7c9842a82f6d256874112774cea700764ed8f38fc9e3db982456c138d87353e3390e746fe - languageName: node - linkType: hard - -"jest-snapshot@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-snapshot@npm:26.6.2" - dependencies: - "@babel/types": ^7.0.0 - "@jest/types": ^26.6.2 - "@types/babel__traverse": ^7.0.4 - "@types/prettier": ^2.0.0 chalk: ^4.0.0 - expect: ^26.6.2 - graceful-fs: ^4.2.4 - jest-diff: ^26.6.2 - jest-get-type: ^26.3.0 - jest-haste-map: ^26.6.2 - jest-matcher-utils: ^26.6.2 - jest-message-util: ^26.6.2 - jest-resolve: ^26.6.2 - natural-compare: ^1.4.0 - pretty-format: ^26.6.2 - semver: ^7.3.2 - checksum: 53f1de055b1d3840bc6e851fd674d5991b844d4695dadbd07354c93bf191048d8767b8606999847e97c4214a485b9afb45c1d2411772befa1870414ac973b3e2 + cjs-module-lexer: ^1.0.0 + collect-v8-coverage: ^1.0.0 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.6.2 + jest-message-util: ^29.6.2 + jest-mock: ^29.6.2 + jest-regex-util: ^29.4.3 + jest-resolve: ^29.6.2 + jest-snapshot: ^29.6.2 + jest-util: ^29.6.2 + slash: ^3.0.0 + strip-bom: ^4.0.0 + checksum: 8e7e4486b23b01a9c407313681bed0def39680c2ae21cf01347f111983252ec3a024c56493c5411fed53633f02863eed0816099110cbe04b3889aa5babf1042d languageName: node linkType: hard @@ -11206,17 +10448,31 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^26.1.0, jest-util@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-util@npm:26.6.2" +"jest-snapshot@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-snapshot@npm:29.6.2" dependencies: - "@jest/types": ^26.6.2 - "@types/node": "*" + "@babel/core": ^7.11.6 + "@babel/generator": ^7.7.2 + "@babel/plugin-syntax-jsx": ^7.7.2 + "@babel/plugin-syntax-typescript": ^7.7.2 + "@babel/types": ^7.3.3 + "@jest/expect-utils": ^29.6.2 + "@jest/transform": ^29.6.2 + "@jest/types": ^29.6.1 + babel-preset-current-node-syntax: ^1.0.0 chalk: ^4.0.0 - graceful-fs: ^4.2.4 - is-ci: ^2.0.0 - micromatch: ^4.0.2 - checksum: 3c6a5fba05c4c6892cd3a9f66196ea8867087b77a5aa1a3f6cd349c785c3f1ca24abfd454664983aed1a165cab7846688e44fe8630652d666ba326b08625bc3d + expect: ^29.6.2 + graceful-fs: ^4.2.9 + jest-diff: ^29.6.2 + jest-get-type: ^29.4.3 + jest-matcher-utils: ^29.6.2 + jest-message-util: ^29.6.2 + jest-util: ^29.6.2 + natural-compare: ^1.4.0 + pretty-format: ^29.6.2 + semver: ^7.5.3 + checksum: c1c70a9dbce7fca62ed73ac38234b4ee643e8b667acf71b4417ab67776c1188bb08b8ad450e56a2889ad182903ffd416386fa8082a477724ccf8d8c29a4c6906 languageName: node linkType: hard @@ -11234,17 +10490,17 @@ __metadata: languageName: node linkType: hard -"jest-validate@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-validate@npm:26.6.2" +"jest-util@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-util@npm:29.6.2" dependencies: - "@jest/types": ^26.6.2 - camelcase: ^6.0.0 + "@jest/types": ^29.6.1 + "@types/node": "*" chalk: ^4.0.0 - jest-get-type: ^26.3.0 - leven: ^3.1.0 - pretty-format: ^26.6.2 - checksum: bac11d6586d9b8885328a4a66eec45b692e45ac23034a5c09eb0ee32de324f2d3d52b073e0c34e9c222b3642b083d1152a736cf24c52109e4957537d731ca62b + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: 8aedc0c80083d0cabd6c6c4f04dea1cbcac609fd7bc3b1fc05a3999291bd6e63dd52b0c806f9378d5cae28eff5a6191709a4987861001293f8d03e53984adca4 languageName: node linkType: hard @@ -11262,18 +10518,17 @@ __metadata: languageName: node linkType: hard -"jest-watcher@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-watcher@npm:26.6.2" +"jest-validate@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-validate@npm:29.6.2" dependencies: - "@jest/test-result": ^26.6.2 - "@jest/types": ^26.6.2 - "@types/node": "*" - ansi-escapes: ^4.2.1 + "@jest/types": ^29.6.1 + camelcase: ^6.2.0 chalk: ^4.0.0 - jest-util: ^26.6.2 - string-length: ^4.0.1 - checksum: 401137f1a73bf23cdf390019ebffb3f6f89c53ca49d48252d1dd6daf17a68787fef75cc55a623de28b63d87d0e8f13d8972d7dd06740f2f64f7b2a0409d119d2 + jest-get-type: ^29.4.3 + leven: ^3.1.0 + pretty-format: ^29.6.2 + checksum: 32648d002189c0ad8a958eace7c6b7d05ea1dc440a1b91e0f22dc1aef489899446ec80b2d527fd13713862d89dfb4606e24a3bf8a10c4ddac3c911e93b7f0374 languageName: node linkType: hard @@ -11293,14 +10548,19 @@ __metadata: languageName: node linkType: hard -"jest-worker@npm:^26.6.2": - version: 26.6.2 - resolution: "jest-worker@npm:26.6.2" +"jest-watcher@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-watcher@npm:29.6.2" dependencies: + "@jest/test-result": ^29.6.2 + "@jest/types": ^29.6.1 "@types/node": "*" - merge-stream: ^2.0.0 - supports-color: ^7.0.0 - checksum: f9afa3b88e3f12027901e4964ba3ff048285b5783b5225cab28fac25b4058cea8ad54001e9a1577ee2bed125fac3ccf5c80dc507b120300cc1bbcb368796533e + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + emittery: ^0.13.1 + jest-util: ^29.6.2 + string-length: ^4.0.1 + checksum: 14624190fc8b5fbae466a2ec81458a88c15716d99f042bb4674d53e9623d305cb2905bc1dffeda05fd1a10a05c2a83efe5ac41942477e2b15eaebb08d0aaab32 languageName: node linkType: hard @@ -11327,16 +10587,34 @@ __metadata: languageName: node linkType: hard -"jest@npm:^26.0.0": - version: 26.6.3 - resolution: "jest@npm:26.6.3" +"jest-worker@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-worker@npm:29.6.2" + dependencies: + "@types/node": "*" + jest-util: ^29.6.2 + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 11035564534bf181ead80b25be138c2d42372bd5626151a3e705200d47a74fd9da3ca79f8a7b15806cdc325ad73c3d21d23acceeed99d50941589ff02915ed38 + languageName: node + linkType: hard + +"jest@npm:^29": + version: 29.6.2 + resolution: "jest@npm:29.6.2" dependencies: - "@jest/core": ^26.6.3 + "@jest/core": ^29.6.2 + "@jest/types": ^29.6.1 import-local: ^3.0.2 - jest-cli: ^26.6.3 + jest-cli: ^29.6.2 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true bin: jest: bin/jest.js - checksum: 3a9b4c70e9bd5391e7367a0036045c1d3545c2a39e1439a71fb4b59b1748bc34e2ccb324faa1046b99bffc8dc2ed7b3c59016c462255b2646f5fa9300351f914 + checksum: dd63facd4e6aefc35d2c42acd7e4c9fb0d8fe4705df4b3ccedd953605424d7aa89c88af8cf4c9951752709cac081d29c35b264e1794643d5688ea724ccc9a485 languageName: node linkType: hard @@ -11389,46 +10667,6 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^16.4.0": - version: 16.7.0 - resolution: "jsdom@npm:16.7.0" - dependencies: - abab: ^2.0.5 - acorn: ^8.2.4 - acorn-globals: ^6.0.0 - cssom: ^0.4.4 - cssstyle: ^2.3.0 - data-urls: ^2.0.0 - decimal.js: ^10.2.1 - domexception: ^2.0.1 - escodegen: ^2.0.0 - form-data: ^3.0.0 - html-encoding-sniffer: ^2.0.1 - http-proxy-agent: ^4.0.1 - https-proxy-agent: ^5.0.0 - is-potential-custom-element-name: ^1.0.1 - nwsapi: ^2.2.0 - parse5: 6.0.1 - saxes: ^5.0.1 - symbol-tree: ^3.2.4 - tough-cookie: ^4.0.0 - w3c-hr-time: ^1.0.2 - w3c-xmlserializer: ^2.0.0 - webidl-conversions: ^6.1.0 - whatwg-encoding: ^1.0.5 - whatwg-mimetype: ^2.3.0 - whatwg-url: ^8.5.0 - ws: ^7.4.6 - xml-name-validator: ^3.0.0 - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 454b83371857000763ed31130a049acd1b113e3b927e6dcd75c67ddc30cdd242d7ebcac5c2294b7a1a6428155cb1398709c573b3c6d809218692ea68edd93370 - languageName: node - linkType: hard - "jsdom@npm:^20.0.0": version: 20.0.3 resolution: "jsdom@npm:20.0.3" @@ -11573,7 +10811,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:2.x, json5@npm:^2.1.1, json5@npm:^2.1.2, json5@npm:^2.2.2, json5@npm:^2.2.3": +"json5@npm:^2.1.1, json5@npm:^2.1.2, json5@npm:^2.2.2, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -11641,32 +10879,7 @@ __metadata: languageName: node linkType: hard -"kind-of@npm:^3.0.2, kind-of@npm:^3.0.3, kind-of@npm:^3.2.0": - version: 3.2.2 - resolution: "kind-of@npm:3.2.2" - dependencies: - is-buffer: ^1.1.5 - checksum: e898df8ca2f31038f27d24f0b8080da7be274f986bc6ed176f37c77c454d76627619e1681f6f9d2e8d2fd7557a18ecc419a6bb54e422abcbb8da8f1a75e4b386 - languageName: node - linkType: hard - -"kind-of@npm:^4.0.0": - version: 4.0.0 - resolution: "kind-of@npm:4.0.0" - dependencies: - is-buffer: ^1.1.5 - checksum: 1b9e7624a8771b5a2489026e820f3bbbcc67893e1345804a56b23a91e9069965854d2a223a7c6ee563c45be9d8c6ff1ef87f28ed5f0d1a8d00d9dcbb067c529f - languageName: node - linkType: hard - -"kind-of@npm:^5.0.0": - version: 5.1.0 - resolution: "kind-of@npm:5.1.0" - checksum: f2a0102ae0cf19c4a953397e552571bad2b588b53282874f25fca7236396e650e2db50d41f9f516bd402536e4df968dbb51b8e69e4d5d4a7173def78448f7bab - languageName: node - linkType: hard - -"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2, kind-of@npm:^6.0.3": +"kind-of@npm:^6.0.2, kind-of@npm:^6.0.3": version: 6.0.3 resolution: "kind-of@npm:6.0.3" checksum: 3ab01e7b1d440b22fe4c31f23d8d38b4d9b91d9f291df683476576493d5dfd2e03848a8b05813dd0c3f0e835bc63f433007ddeceb71f05cb25c45ae1b19c6d3b @@ -12093,7 +11306,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:4.x, lodash@npm:^4.17.15, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0": +"lodash@npm:^4.17.15, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -12268,13 +11481,6 @@ __metadata: languageName: node linkType: hard -"map-cache@npm:^0.2.2": - version: 0.2.2 - resolution: "map-cache@npm:0.2.2" - checksum: 3067cea54285c43848bb4539f978a15dedc63c03022abeec6ef05c8cb6829f920f13b94bcaf04142fc6a088318e564c4785704072910d120d55dbc2e0c421969 - languageName: node - linkType: hard - "map-obj@npm:^1.0.0": version: 1.0.1 resolution: "map-obj@npm:1.0.1" @@ -12289,15 +11495,6 @@ __metadata: languageName: node linkType: hard -"map-visit@npm:^1.0.0": - version: 1.0.0 - resolution: "map-visit@npm:1.0.0" - dependencies: - object-visit: ^1.0.0 - checksum: c27045a5021c344fc19b9132eb30313e441863b2951029f8f8b66f79d3d8c1e7e5091578075a996f74e417479506fe9ede28c44ca7bc351a61c9d8073daec36a - languageName: node - linkType: hard - "markdown-to-jsx@npm:^7.2.1": version: 7.2.1 resolution: "markdown-to-jsx@npm:7.2.1" @@ -12718,28 +11915,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^3.1.4": - version: 3.1.10 - resolution: "micromatch@npm:3.1.10" - dependencies: - arr-diff: ^4.0.0 - array-unique: ^0.3.2 - braces: ^2.3.1 - define-property: ^2.0.2 - extend-shallow: ^3.0.2 - extglob: ^2.0.4 - fragment-cache: ^0.2.1 - kind-of: ^6.0.2 - nanomatch: ^1.2.9 - object.pick: ^1.3.0 - regex-not: ^1.0.0 - snapdragon: ^0.8.1 - to-regex: ^3.0.2 - checksum: ad226cba4daa95b4eaf47b2ca331c8d2e038d7b41ae7ed0697cde27f3f1d6142881ab03d4da51b65d9d315eceb5e4cdddb3fbb55f5f72cfa19cf3ea469d054dc - languageName: node - linkType: hard - -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": +"micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": version: 4.0.5 resolution: "micromatch@npm:4.0.5" dependencies: @@ -12864,7 +12040,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.1.1, minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:~1.2.0": +"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:~1.2.0": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -12987,16 +12163,6 @@ __metadata: languageName: node linkType: hard -"mixin-deep@npm:^1.2.0": - version: 1.3.2 - resolution: "mixin-deep@npm:1.3.2" - dependencies: - for-in: ^1.0.2 - is-extendable: ^1.0.1 - checksum: 820d5a51fcb7479f2926b97f2c3bb223546bc915e6b3a3eb5d906dda871bba569863595424a76682f2b15718252954644f3891437cb7e3f220949bed54b1750d - languageName: node - linkType: hard - "mkdirp-infer-owner@npm:^2.0.0": version: 2.0.0 resolution: "mkdirp-infer-owner@npm:2.0.0" @@ -13008,7 +12174,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:1.x, mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": +"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" bin: @@ -13038,13 +12204,6 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.0.0": - version: 2.0.0 - resolution: "ms@npm:2.0.0" - checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4 - languageName: node - linkType: hard - "ms@npm:2.1.2": version: 2.1.2 resolution: "ms@npm:2.1.2" @@ -13088,25 +12247,6 @@ __metadata: languageName: node linkType: hard -"nanomatch@npm:^1.2.9": - version: 1.2.13 - resolution: "nanomatch@npm:1.2.13" - dependencies: - arr-diff: ^4.0.0 - array-unique: ^0.3.2 - define-property: ^2.0.2 - extend-shallow: ^3.0.2 - fragment-cache: ^0.2.1 - is-windows: ^1.0.2 - kind-of: ^6.0.2 - object.pick: ^1.3.0 - regex-not: ^1.0.0 - snapdragon: ^0.8.1 - to-regex: ^3.0.1 - checksum: 54d4166d6ef08db41252eb4e96d4109ebcb8029f0374f9db873bd91a1f896c32ec780d2a2ea65c0b2d7caf1f28d5e1ea33746a470f32146ac8bba821d80d38d8 - languageName: node - linkType: hard - "napi-macros@npm:~2.0.0": version: 2.0.0 resolution: "napi-macros@npm:2.0.0" @@ -13229,20 +12369,6 @@ __metadata: languageName: node linkType: hard -"node-notifier@npm:^8.0.0": - version: 8.0.2 - resolution: "node-notifier@npm:8.0.2" - dependencies: - growly: ^1.3.0 - is-wsl: ^2.2.0 - semver: ^7.3.2 - shellwords: ^0.1.1 - uuid: ^8.3.0 - which: ^2.0.2 - checksum: 7db1683003f6aaa4324959dfa663cd56e301ccc0165977a9e7737989ffe3b4763297f9fc85f44d0662b63a4fd85516eda43411b492a4d2fae207afb23773f912 - languageName: node - linkType: hard - "node-releases@npm:^2.0.12": version: 2.0.13 resolution: "node-releases@npm:2.0.13" @@ -13320,15 +12446,6 @@ __metadata: languageName: node linkType: hard -"normalize-path@npm:^2.1.1": - version: 2.1.1 - resolution: "normalize-path@npm:2.1.1" - dependencies: - remove-trailing-separator: ^1.0.1 - checksum: 7e9cbdcf7f5b8da7aa191fbfe33daf290cdcd8c038f422faf1b8a83c972bf7a6d94c5be34c4326cb00fb63bc0fd97d9fbcfaf2e5d6142332c2cd36d2e1b86cea - languageName: node - linkType: hard - "normalize-path@npm:^3.0.0": version: 3.0.0 resolution: "normalize-path@npm:3.0.0" @@ -13527,16 +12644,7 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^2.0.0": - version: 2.0.2 - resolution: "npm-run-path@npm:2.0.2" - dependencies: - path-key: ^2.0.0 - checksum: acd5ad81648ba4588ba5a8effb1d98d2b339d31be16826a118d50f182a134ac523172101b82eab1d01cb4c2ba358e857d54cfafd8163a1ffe7bd52100b741125 - languageName: node - linkType: hard - -"npm-run-path@npm:^4.0.0, npm-run-path@npm:^4.0.1": +"npm-run-path@npm:^4.0.1": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" dependencies: @@ -13569,7 +12677,7 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.0, nwsapi@npm:^2.2.2": +"nwsapi@npm:^2.2.2": version: 2.2.7 resolution: "nwsapi@npm:2.2.7" checksum: cab25f7983acec7e23490fec3ef7be608041b460504229770e3bfcf9977c41d6fe58f518994d3bd9aa3a101f501089a3d4a63536f4ff8ae4b8c4ca23bdbfda4e @@ -13664,17 +12772,6 @@ __metadata: languageName: node linkType: hard -"object-copy@npm:^0.1.0": - version: 0.1.0 - resolution: "object-copy@npm:0.1.0" - dependencies: - copy-descriptor: ^0.1.0 - define-property: ^0.2.5 - kind-of: ^3.0.3 - checksum: a9e35f07e3a2c882a7e979090360d1a20ab51d1fa19dfdac3aa8873b328a7c4c7683946ee97c824ae40079d848d6740a3788fa14f2185155dab7ed970a72c783 - languageName: node - linkType: hard - "object-inspect@npm:^1.12.3, object-inspect@npm:^1.9.0": version: 1.12.3 resolution: "object-inspect@npm:1.12.3" @@ -13699,15 +12796,6 @@ __metadata: languageName: node linkType: hard -"object-visit@npm:^1.0.0": - version: 1.0.1 - resolution: "object-visit@npm:1.0.1" - dependencies: - isobject: ^3.0.0 - checksum: b0ee07f5bf3bb881b881ff53b467ebbde2b37ebb38649d6944a6cd7681b32eedd99da9bd1e01c55facf81f54ed06b13af61aba6ad87f0052982995e09333f790 - languageName: node - linkType: hard - "object.assign@npm:^4.1.4": version: 4.1.4 resolution: "object.assign@npm:4.1.4" @@ -13720,16 +12808,7 @@ __metadata: languageName: node linkType: hard -"object.pick@npm:^1.3.0": - version: 1.3.0 - resolution: "object.pick@npm:1.3.0" - dependencies: - isobject: ^3.0.1 - checksum: 77fb6eed57c67adf75e9901187e37af39f052ef601cb4480386436561357eb9e459e820762f01fd02c5c1b42ece839ad393717a6d1850d848ee11fbabb3e580a - languageName: node - linkType: hard - -"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": +"once@npm:^1.3.0, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -13796,13 +12875,6 @@ __metadata: languageName: node linkType: hard -"p-each-series@npm:^2.1.0": - version: 2.2.0 - resolution: "p-each-series@npm:2.2.0" - checksum: 5fbe2f1f1966f55833bd401fe36f7afe410707d5e9fb6032c6dde8aa716d50521c3bb201fdb584130569b5941d5e84993e09e0b3f76a474288e0ede8f632983c - languageName: node - linkType: hard - "p-finally@npm:^1.0.0": version: 1.0.0 resolution: "p-finally@npm:1.0.0" @@ -14073,13 +13145,6 @@ __metadata: languageName: node linkType: hard -"parse5@npm:6.0.1": - version: 6.0.1 - resolution: "parse5@npm:6.0.1" - checksum: 7d569a176c5460897f7c8f3377eff640d54132b9be51ae8a8fa4979af940830b2b0c296ce75e5bd8f4041520aadde13170dbdec44889975f906098ea0002f4bd - languageName: node - linkType: hard - "parse5@npm:^7.0.0, parse5@npm:^7.1.1": version: 7.1.2 resolution: "parse5@npm:7.1.2" @@ -14089,13 +13154,6 @@ __metadata: languageName: node linkType: hard -"pascalcase@npm:^0.1.1": - version: 0.1.1 - resolution: "pascalcase@npm:0.1.1" - checksum: f83681c3c8ff75fa473a2bb2b113289952f802ff895d435edd717e7cb898b0408cbdb247117a938edcbc5d141020909846cc2b92c47213d764e2a94d2ad2b925 - languageName: node - linkType: hard - "path-browserify@npm:^1.0.0": version: 1.0.1 resolution: "path-browserify@npm:1.0.1" @@ -14124,7 +13182,7 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^2.0.0, path-key@npm:^2.0.1": +"path-key@npm:^2.0.1": version: 2.0.1 resolution: "path-key@npm:2.0.1" checksum: f7ab0ad42fe3fb8c7f11d0c4f849871e28fbd8e1add65c370e422512fc5887097b9cf34d09c1747d45c942a8c1e26468d6356e2df3f740bf177ab8ca7301ebfd @@ -14222,7 +13280,7 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.1, pirates@npm:^4.0.4": +"pirates@npm:^4.0.4": version: 4.0.6 resolution: "pirates@npm:4.0.6" checksum: 46a65fefaf19c6f57460388a5af9ab81e3d7fd0e7bc44ca59d753cb5c4d0df97c6c6e583674869762101836d68675f027d60f841c105d72734df9dfca97cbcc6 @@ -14245,13 +13303,6 @@ __metadata: languageName: node linkType: hard -"posix-character-classes@npm:^0.1.0": - version: 0.1.1 - resolution: "posix-character-classes@npm:0.1.1" - checksum: dedb99913c60625a16050cfed2fb5c017648fc075be41ac18474e1c6c3549ef4ada201c8bd9bd006d36827e289c571b6092e1ef6e756cdbab2fd7046b25c6442 - languageName: node - linkType: hard - "postcss-media-query-parser@npm:^0.2.3": version: 0.2.3 resolution: "postcss-media-query-parser@npm:0.2.3" @@ -14383,15 +13434,14 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^26.0.0, pretty-format@npm:^26.6.2": - version: 26.6.2 - resolution: "pretty-format@npm:26.6.2" +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.6.2": + version: 29.6.2 + resolution: "pretty-format@npm:29.6.2" dependencies: - "@jest/types": ^26.6.2 - ansi-regex: ^5.0.0 - ansi-styles: ^4.0.0 - react-is: ^17.0.1 - checksum: e3b808404d7e1519f0df1aa1f25cee0054ab475775c6b2b8c5568ff23194a92d54bf93274139b6f584ca70fd773be4eaa754b0e03f12bb0a8d1426b07f079976 + "@jest/schemas": ^29.6.0 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: a0f972a44f959023c0df9cdfe9eed7540264d7f7ddf74667db8a5294444d5aa153fd47d20327df10ae86964e2ceec10e46ea06b1a5c9c12e02348b78c952c9fc languageName: node linkType: hard @@ -14567,16 +13617,6 @@ __metadata: languageName: node linkType: hard -"pump@npm:^3.0.0": - version: 3.0.0 - resolution: "pump@npm:3.0.0" - dependencies: - end-of-stream: ^1.1.0 - once: ^1.3.1 - checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9 - languageName: node - linkType: hard - "punycode@npm:^1.4.1": version: 1.4.1 resolution: "punycode@npm:1.4.1" @@ -14676,13 +13716,6 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^17.0.1": - version: 17.0.2 - resolution: "react-is@npm:17.0.2" - checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8 - languageName: node - linkType: hard - "react-is@npm:^18.0.0, react-is@npm:^18.2.0": version: 18.2.0 resolution: "react-is@npm:18.2.0" @@ -15028,16 +14061,6 @@ __metadata: languageName: node linkType: hard -"regex-not@npm:^1.0.0, regex-not@npm:^1.0.2": - version: 1.0.2 - resolution: "regex-not@npm:1.0.2" - dependencies: - extend-shallow: ^3.0.2 - safe-regex: ^1.1.0 - checksum: 3081403de79559387a35ef9d033740e41818a559512668cef3d12da4e8a29ef34ee13c8ed1256b07e27ae392790172e8a15c8a06b72962fd4550476cde3d8f77 - languageName: node - linkType: hard - "regexp-match-indices@npm:^1.0.2": version: 1.0.2 resolution: "regexp-match-indices@npm:1.0.2" @@ -15148,27 +14171,6 @@ __metadata: languageName: node linkType: hard -"remove-trailing-separator@npm:^1.0.1": - version: 1.1.0 - resolution: "remove-trailing-separator@npm:1.1.0" - checksum: d3c20b5a2d987db13e1cca9385d56ecfa1641bae143b620835ac02a6b70ab88f68f117a0021838db826c57b31373d609d52e4f31aca75fc490c862732d595419 - languageName: node - linkType: hard - -"repeat-element@npm:^1.1.2": - version: 1.1.4 - resolution: "repeat-element@npm:1.1.4" - checksum: 1edd0301b7edad71808baad226f0890ba709443f03a698224c9ee4f2494c317892dc5211b2ba8cbea7194a9ddbcac01e283bd66de0467ab24ee1fc1a3711d8a9 - languageName: node - linkType: hard - -"repeat-string@npm:^1.6.1": - version: 1.6.1 - resolution: "repeat-string@npm:1.6.1" - checksum: 1b809fc6db97decdc68f5b12c4d1a671c8e3f65ec4a40c238bc5200e44e85bcc52a54f78268ab9c29fcf5fe4f1343e805420056d1f30fa9a9ee4c2d93e3cc6c0 - languageName: node - linkType: hard - "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -15183,13 +14185,6 @@ __metadata: languageName: node linkType: hard -"require-main-filename@npm:^2.0.0": - version: 2.0.0 - resolution: "require-main-filename@npm:2.0.0" - checksum: e9e294695fea08b076457e9ddff854e81bffbe248ed34c1eec348b7abbd22a0d02e8d75506559e2265e96978f3c4720bd77a6dad84755de8162b357eb6c778c7 - languageName: node - linkType: hard - "requires-port@npm:^1.0.0": version: 1.0.0 resolution: "requires-port@npm:1.0.0" @@ -15220,13 +14215,6 @@ __metadata: languageName: node linkType: hard -"resolve-url@npm:^0.2.1": - version: 0.2.1 - resolution: "resolve-url@npm:0.2.1" - checksum: 7b7035b9ed6e7bc7d289e90aef1eab5a43834539695dac6416ca6e91f1a94132ae4796bbd173cdacfdc2ade90b5f38a3fb6186bebc1b221cd157777a23b9ad14 - languageName: node - linkType: hard - "resolve.exports@npm:^2.0.0": version: 2.0.2 resolution: "resolve.exports@npm:2.0.2" @@ -15234,7 +14222,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.18.1, resolve@npm:^1.19.0, resolve@npm:^1.20.0": +"resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0": version: 1.22.3 resolution: "resolve@npm:1.22.3" dependencies: @@ -15247,7 +14235,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.18.1#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin": +"resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin": version: 1.22.3 resolution: "resolve@patch:resolve@npm%3A1.22.3#~builtin::version=1.22.3&hash=c3c19d" dependencies: @@ -15270,13 +14258,6 @@ __metadata: languageName: node linkType: hard -"ret@npm:~0.1.10": - version: 0.1.15 - resolution: "ret@npm:0.1.15" - checksum: d76a9159eb8c946586567bd934358dfc08a36367b3257f7a3d7255fdd7b56597235af23c6afa0d7f0254159e8051f93c918809962ebd6df24ca2a83dbe4d4151 - languageName: node - linkType: hard - "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -15313,13 +14294,6 @@ __metadata: languageName: node linkType: hard -"rsvp@npm:^4.8.4": - version: 4.8.5 - resolution: "rsvp@npm:4.8.5" - checksum: 2d8ef30d8febdf05bdf856ccca38001ae3647e41835ca196bc1225333f79b94ae44def733121ca549ccc36209c9b689f6586905e2a043873262609744da8efc1 - languageName: node - linkType: hard - "run-async@npm:^2.4.0": version: 2.4.1 resolution: "run-async@npm:2.4.1" @@ -15391,15 +14365,6 @@ __metadata: languageName: node linkType: hard -"safe-regex@npm:^1.1.0": - version: 1.1.0 - resolution: "safe-regex@npm:1.1.0" - dependencies: - ret: ~0.1.10 - checksum: 9a8bba57c87a841f7997b3b951e8e403b1128c1a4fd1182f40cc1a20e2d490593d7c2a21030fadfea320c8e859219019e136f678c6689ed5960b391b822f01d5 - languageName: node - linkType: hard - "safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" @@ -15407,25 +14372,6 @@ __metadata: languageName: node linkType: hard -"sane@npm:^4.0.3": - version: 4.1.0 - resolution: "sane@npm:4.1.0" - dependencies: - "@cnakazawa/watch": ^1.0.3 - anymatch: ^2.0.0 - capture-exit: ^2.0.0 - exec-sh: ^0.3.2 - execa: ^1.0.0 - fb-watchman: ^2.0.0 - micromatch: ^3.1.4 - minimist: ^1.1.1 - walker: ~1.0.5 - bin: - sane: ./src/cli.js - checksum: 97716502d456c0d38670a902a4ea943d196dcdf998d1e40532d8f3e24e25d7eddfd4c3579025a1eee8eac09a48dfd05fba61a2156c56704e7feaa450eb249f7c - languageName: node - linkType: hard - "sanitize-html@npm:~2.7.3": version: 2.7.3 resolution: "sanitize-html@npm:2.7.3" @@ -15440,15 +14386,6 @@ __metadata: languageName: node linkType: hard -"saxes@npm:^5.0.1": - version: 5.0.1 - resolution: "saxes@npm:5.0.1" - dependencies: - xmlchars: ^2.2.0 - checksum: 5636b55cf15f7cf0baa73f2797bf992bdcf75d1b39d82c0aa4608555c774368f6ac321cb641fd5f3d3ceb87805122cd47540da6a7b5960fe0dbdb8f8c263f000 - languageName: node - linkType: hard - "saxes@npm:^6.0.0": version: 6.0.0 resolution: "saxes@npm:6.0.0" @@ -15542,23 +14479,23 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.x, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3": - version: 7.5.4 - resolution: "semver@npm:7.5.4" - dependencies: - lru-cache: ^6.0.0 +"semver@npm:^6.0.0, semver@npm:^6.3.0, semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" bin: semver: bin/semver.js - checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 + checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 languageName: node linkType: hard -"semver@npm:^6.0.0, semver@npm:^6.3.0, semver@npm:^6.3.1": - version: 6.3.1 - resolution: "semver@npm:6.3.1" +"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.2.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3": + version: 7.5.4 + resolution: "semver@npm:7.5.4" + dependencies: + lru-cache: ^6.0.0 bin: semver: bin/semver.js - checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 + checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 languageName: node linkType: hard @@ -15578,18 +14515,6 @@ __metadata: languageName: node linkType: hard -"set-value@npm:^2.0.0, set-value@npm:^2.0.1": - version: 2.0.1 - resolution: "set-value@npm:2.0.1" - dependencies: - extend-shallow: ^2.0.1 - is-extendable: ^0.1.1 - is-plain-object: ^2.0.3 - split-string: ^3.0.1 - checksum: 09a4bc72c94641aeae950eb60dc2755943b863780fcc32e441eda964b64df5e3f50603d5ebdd33394ede722528bd55ed43aae26e9df469b4d32e2292b427b601 - languageName: node - linkType: hard - "shallow-clone@npm:^3.0.0": version: 3.0.1 resolution: "shallow-clone@npm:3.0.1" @@ -15638,13 +14563,6 @@ __metadata: languageName: node linkType: hard -"shellwords@npm:^0.1.1": - version: 0.1.1 - resolution: "shellwords@npm:0.1.1" - checksum: 8d73a5e9861f5e5f1068e2cfc39bc0002400fe58558ab5e5fa75630d2c3adf44ca1fac81957609c8320d5533e093802fcafc72904bf1a32b95de3c19a0b1c0d4 - languageName: node - linkType: hard - "side-channel@npm:^1.0.4": version: 1.0.4 resolution: "side-channel@npm:1.0.4" @@ -15656,7 +14574,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:3.0.7, signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"signal-exit@npm:3.0.7, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 @@ -15725,42 +14643,6 @@ __metadata: languageName: node linkType: hard -"snapdragon-node@npm:^2.0.1": - version: 2.1.1 - resolution: "snapdragon-node@npm:2.1.1" - dependencies: - define-property: ^1.0.0 - isobject: ^3.0.0 - snapdragon-util: ^3.0.1 - checksum: 9bb57d759f9e2a27935dbab0e4a790137adebace832b393e350a8bf5db461ee9206bb642d4fe47568ee0b44080479c8b4a9ad0ebe3712422d77edf9992a672fd - languageName: node - linkType: hard - -"snapdragon-util@npm:^3.0.1": - version: 3.0.1 - resolution: "snapdragon-util@npm:3.0.1" - dependencies: - kind-of: ^3.2.0 - checksum: 684997dbe37ec995c03fd3f412fba2b711fc34cb4010452b7eb668be72e8811a86a12938b511e8b19baf853b325178c56d8b78d655305e5cfb0bb8b21677e7b7 - languageName: node - linkType: hard - -"snapdragon@npm:^0.8.1": - version: 0.8.2 - resolution: "snapdragon@npm:0.8.2" - dependencies: - base: ^0.11.1 - debug: ^2.2.0 - define-property: ^0.2.5 - extend-shallow: ^2.0.1 - map-cache: ^0.2.2 - source-map: ^0.5.6 - source-map-resolve: ^0.5.0 - use: ^3.1.0 - checksum: a197f242a8f48b11036563065b2487e9b7068f50a20dd81d9161eca6af422174fc158b8beeadbe59ce5ef172aa5718143312b3aebaae551c124b7824387c8312 - languageName: node - linkType: hard - "socks-proxy-agent@npm:^7.0.0": version: 7.0.0 resolution: "socks-proxy-agent@npm:7.0.0" @@ -15820,19 +14702,6 @@ __metadata: languageName: node linkType: hard -"source-map-resolve@npm:^0.5.0": - version: 0.5.3 - resolution: "source-map-resolve@npm:0.5.3" - dependencies: - atob: ^2.1.2 - decode-uri-component: ^0.2.0 - resolve-url: ^0.2.1 - source-map-url: ^0.4.0 - urix: ^0.1.0 - checksum: c73fa44ac00783f025f6ad9e038ab1a2e007cd6a6b86f47fe717c3d0765b4a08d264f6966f3bd7cd9dbcd69e4832783d5472e43247775b2a550d6f2155d24bae - languageName: node - linkType: hard - "source-map-support@npm:0.5.13": version: 0.5.13 resolution: "source-map-support@npm:0.5.13" @@ -15843,7 +14712,7 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:^0.5.6, source-map-support@npm:~0.5.20": +"source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" dependencies: @@ -15853,14 +14722,7 @@ __metadata: languageName: node linkType: hard -"source-map-url@npm:^0.4.0": - version: 0.4.1 - resolution: "source-map-url@npm:0.4.1" - checksum: 64c5c2c77aff815a6e61a4120c309ae4cac01298d9bcbb3deb1b46a4dd4c46d4a1eaeda79ec9f684766ae80e8dc86367b89326ce9dd2b89947bd9291fc1ac08c - languageName: node - linkType: hard - -"source-map@npm:^0.5.6, source-map@npm:^0.5.7": +"source-map@npm:^0.5.7": version: 0.5.7 resolution: "source-map@npm:0.5.7" checksum: 5dc2043b93d2f194142c7f38f74a24670cd7a0063acdaf4bf01d2964b402257ae843c2a8fa822ad5b71013b5fcafa55af7421383da919752f22ff488bc553f4d @@ -15874,13 +14736,6 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.7.3": - version: 0.7.4 - resolution: "source-map@npm:0.7.4" - checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5 - languageName: node - linkType: hard - "space-separated-tokens@npm:^1.0.0": version: 1.1.5 resolution: "space-separated-tokens@npm:1.1.5" @@ -15929,15 +14784,6 @@ __metadata: languageName: node linkType: hard -"split-string@npm:^3.0.1, split-string@npm:^3.0.2": - version: 3.1.0 - resolution: "split-string@npm:3.1.0" - dependencies: - extend-shallow: ^3.0.0 - checksum: ae5af5c91bdc3633628821bde92fdf9492fa0e8a63cf6a0376ed6afde93c701422a1610916f59be61972717070119e848d10dfbbd5024b7729d6a71972d2a84c - languageName: node - linkType: hard - "split2@npm:^3.0.0": version: 3.2.2 resolution: "split2@npm:3.2.2" @@ -15981,7 +14827,7 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.2, stack-utils@npm:^2.0.3": +"stack-utils@npm:^2.0.3": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" dependencies: @@ -15990,16 +14836,6 @@ __metadata: languageName: node linkType: hard -"static-extend@npm:^0.1.1": - version: 0.1.2 - resolution: "static-extend@npm:0.1.2" - dependencies: - define-property: ^0.2.5 - object-copy: ^0.1.0 - checksum: 8657485b831f79e388a437260baf22784540417a9b29e11572c87735df24c22b84eda42107403a64b30861b2faf13df9f7fc5525d51f9d1d2303aba5cbf4e12c - languageName: node - linkType: hard - "string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" @@ -16126,13 +14962,6 @@ __metadata: languageName: node linkType: hard -"strip-eof@npm:^1.0.0": - version: 1.0.0 - resolution: "strip-eof@npm:1.0.0" - checksum: 40bc8ddd7e072f8ba0c2d6d05267b4e0a4800898c3435b5fb5f5a21e6e47dfaff18467e7aa0d1844bb5d6274c3097246595841fbfeb317e541974ee992cac506 - languageName: node - linkType: hard - "strip-final-newline@npm:^2.0.0": version: 2.0.0 resolution: "strip-final-newline@npm:2.0.0" @@ -16327,7 +15156,7 @@ __metadata: languageName: node linkType: hard -"supports-hyperlinks@npm:^2.0.0, supports-hyperlinks@npm:^2.3.0": +"supports-hyperlinks@npm:^2.3.0": version: 2.3.0 resolution: "supports-hyperlinks@npm:2.3.0" dependencies: @@ -16446,16 +15275,6 @@ __metadata: languageName: node linkType: hard -"terminal-link@npm:^2.0.0": - version: 2.1.1 - resolution: "terminal-link@npm:2.1.1" - dependencies: - ansi-escapes: ^4.2.1 - supports-hyperlinks: ^2.0.0 - checksum: ce3d2cd3a438c4a9453947aa664581519173ea40e77e2534d08c088ee6dda449eabdbe0a76d2a516b8b73c33262fedd10d5270ccf7576ae316e3db170ce6562f - languageName: node - linkType: hard - "terser-webpack-plugin@npm:^5.3.7": version: 5.3.9 resolution: "terser-webpack-plugin@npm:5.3.9" @@ -16517,13 +15336,6 @@ __metadata: languageName: node linkType: hard -"throat@npm:^5.0.0": - version: 5.0.0 - resolution: "throat@npm:5.0.0" - checksum: 031ff7f4431618036c1dedd99c8aa82f5c33077320a8358ed829e84b320783781d1869fe58e8f76e948306803de966f5f7573766a437562c9f5c033297ad2fe2 - languageName: node - linkType: hard - "through2@npm:^2.0.0": version: 2.0.5 resolution: "through2@npm:2.0.5" @@ -16582,25 +15394,6 @@ __metadata: languageName: node linkType: hard -"to-object-path@npm:^0.3.0": - version: 0.3.0 - resolution: "to-object-path@npm:0.3.0" - dependencies: - kind-of: ^3.0.2 - checksum: 9425effee5b43e61d720940fa2b889623f77473d459c2ce3d4a580a4405df4403eec7be6b857455908070566352f9e2417304641ed158dda6f6a365fe3e66d70 - languageName: node - linkType: hard - -"to-regex-range@npm:^2.1.0": - version: 2.1.1 - resolution: "to-regex-range@npm:2.1.1" - dependencies: - is-number: ^3.0.0 - repeat-string: ^1.6.1 - checksum: 46093cc14be2da905cc931e442d280b2e544e2bfdb9a24b3cf821be8d342f804785e5736c108d5be026021a05d7b38144980a61917eee3c88de0a5e710e10320 - languageName: node - linkType: hard - "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -16610,19 +15403,7 @@ __metadata: languageName: node linkType: hard -"to-regex@npm:^3.0.1, to-regex@npm:^3.0.2": - version: 3.0.2 - resolution: "to-regex@npm:3.0.2" - dependencies: - define-property: ^2.0.2 - extend-shallow: ^3.0.2 - regex-not: ^1.0.2 - safe-regex: ^1.1.0 - checksum: 4ed4a619059b64e204aad84e4e5f3ea82d97410988bcece7cf6cbfdbf193d11bff48cf53842d88b8bb00b1bfc0d048f61f20f0709e6f393fd8fe0122662d9db4 - languageName: node - linkType: hard - -"tough-cookie@npm:^4.0.0, tough-cookie@npm:^4.1.2": +"tough-cookie@npm:^4.1.2": version: 4.1.3 resolution: "tough-cookie@npm:4.1.3" dependencies: @@ -16687,30 +15468,7 @@ __metadata: languageName: node linkType: hard -"ts-jest@npm:^26.0.0": - version: 26.5.6 - resolution: "ts-jest@npm:26.5.6" - dependencies: - bs-logger: 0.x - buffer-from: 1.x - fast-json-stable-stringify: 2.x - jest-util: ^26.1.0 - json5: 2.x - lodash: 4.x - make-error: 1.x - mkdirp: 1.x - semver: 7.x - yargs-parser: 20.x - peerDependencies: - jest: ">=26 <27" - typescript: ">=3.8 <5.0" - bin: - ts-jest: cli.js - checksum: 6f65ad4fe67ab3f0fd4c7f9954acbee863af05b2b3f88dd0f490bbcdc58002960fac908b2cb9f009ec14da6fe13cb00a39e291260d6e555abe72448d1c0a017f - languageName: node - linkType: hard - -"ts-jest@npm:^29.1.0": +"ts-jest@npm:^29, ts-jest@npm:^29.1.0": version: 29.1.1 resolution: "ts-jest@npm:29.1.1" dependencies: @@ -16923,15 +15681,6 @@ __metadata: languageName: node linkType: hard -"typedarray-to-buffer@npm:^3.1.5": - version: 3.1.5 - resolution: "typedarray-to-buffer@npm:3.1.5" - dependencies: - is-typedarray: ^1.0.0 - checksum: 99c11aaa8f45189fcfba6b8a4825fd684a321caa9bd7a76a27cf0c7732c174d198b99f449c52c3818107430b5f41c0ccbbfb75cb2ee3ca4a9451710986d61a60 - languageName: node - linkType: hard - "typedarray@npm:^0.0.6": version: 0.0.6 resolution: "typedarray@npm:0.0.6" @@ -16949,13 +15698,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:~4.1.3": - version: 4.1.6 - resolution: "typescript@npm:4.1.6" +"typescript@npm:~4.3.0": + version: 4.3.5 + resolution: "typescript@npm:4.3.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 54aed909f94b16178c8a8d8911871b4e1c04454a3e6c82166715e28083e7ce6271e4d1df6f82c89544a4759b07aec780785032534e9c93b254e2107a18712c05 + checksum: bab033b5e2b0790dd35b77fd005df976ef80b8d84fd2c6e63cc31808151875beae9216e5a315fe7068e8499905c3c354248fe83272cdfc13b7705635f0c66c97 languageName: node linkType: hard @@ -16969,13 +15718,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@~4.1.3#~builtin": - version: 4.1.6 - resolution: "typescript@patch:typescript@npm%3A4.1.6#~builtin::version=4.1.6&hash=4a8eb8" +"typescript@patch:typescript@~4.3.0#~builtin": + version: 4.3.5 + resolution: "typescript@patch:typescript@npm%3A4.3.5#~builtin::version=4.3.5&hash=dba6d9" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 3bd9915f236817e4e2d32dd0d90e8902875929f014bb87a478000e32adda91d12f0425931ee6f9d6a2bc7d0c9242588fcee1050ac294497dfabf27d3d73b335c + checksum: 365df18cf979c971ef9543b2acaa8694377a803f98e1804c41d0ede0b09d7046cb0cd98f2eaf3884b0fe923c01a60af1f653841bd8805c9715d5479c09a4ebe4 languageName: node linkType: hard @@ -17056,18 +15805,6 @@ __metadata: languageName: node linkType: hard -"union-value@npm:^1.0.0": - version: 1.0.1 - resolution: "union-value@npm:1.0.1" - dependencies: - arr-union: ^3.1.0 - get-value: ^2.0.6 - is-extendable: ^0.1.1 - set-value: ^2.0.1 - checksum: a3464097d3f27f6aa90cf103ed9387541bccfc006517559381a10e0dffa62f465a9d9a09c9b9c3d26d0f4cbe61d4d010e2fbd710fd4bf1267a768ba8a774b0ba - languageName: node - linkType: hard - "unique-filename@npm:^2.0.0": version: 2.0.1 resolution: "unique-filename@npm:2.0.1" @@ -17209,16 +15946,6 @@ __metadata: languageName: node linkType: hard -"unset-value@npm:^1.0.0": - version: 1.0.0 - resolution: "unset-value@npm:1.0.0" - dependencies: - has-value: ^0.3.1 - isobject: ^3.0.0 - checksum: 5990ecf660672be2781fc9fb322543c4aa592b68ed9a3312fa4df0e9ba709d42e823af090fc8f95775b4cd2c9a5169f7388f0cec39238b6d0d55a69fc2ab6b29 - languageName: node - linkType: hard - "upath@npm:2.0.1, upath@npm:^2.0.1": version: 2.0.1 resolution: "upath@npm:2.0.1" @@ -17249,13 +15976,6 @@ __metadata: languageName: node linkType: hard -"urix@npm:^0.1.0": - version: 0.1.0 - resolution: "urix@npm:0.1.0" - checksum: 4c076ecfbf3411e888547fe844e52378ab5ada2d2f27625139011eada79925e77f7fbf0e4016d45e6a9e9adb6b7e64981bd49b22700c7c401c5fc15f423303b3 - languageName: node - linkType: hard - "url-parse@npm:^1.5.3, url-parse@npm:~1.5.1, url-parse@npm:~1.5.4": version: 1.5.10 resolution: "url-parse@npm:1.5.10" @@ -17276,13 +15996,6 @@ __metadata: languageName: node linkType: hard -"use@npm:^3.1.0": - version: 3.1.1 - resolution: "use@npm:3.1.1" - checksum: 08a130289f5238fcbf8f59a18951286a6e660d17acccc9d58d9b69dfa0ee19aa038e8f95721b00b432c36d1629a9e32a464bf2e7e0ae6a244c42ddb30bdd8b33 - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -17290,7 +16003,7 @@ __metadata: languageName: node linkType: hard -"uuid@npm:8.3.2, uuid@npm:^8.3.0, uuid@npm:^8.3.2": +"uuid@npm:8.3.2, uuid@npm:^8.3.2": version: 8.3.2 resolution: "uuid@npm:8.3.2" bin: @@ -17320,17 +16033,6 @@ __metadata: languageName: node linkType: hard -"v8-to-istanbul@npm:^7.0.0": - version: 7.1.2 - resolution: "v8-to-istanbul@npm:7.1.2" - dependencies: - "@types/istanbul-lib-coverage": ^2.0.1 - convert-source-map: ^1.6.0 - source-map: ^0.7.3 - checksum: e52b48764f55aed62ff87f2b5f710c874f992cd1313eac8f438bf65aeeb0689153d85bb76e39514fd90ba3521d6ebea929a8ae1339b6d7b0cf18fb0ed13d8b40 - languageName: node - linkType: hard - "v8-to-istanbul@npm:^9.0.1": version: 9.1.0 resolution: "v8-to-istanbul@npm:9.1.0" @@ -17491,15 +16193,6 @@ __metadata: languageName: node linkType: hard -"w3c-hr-time@npm:^1.0.2": - version: 1.0.2 - resolution: "w3c-hr-time@npm:1.0.2" - dependencies: - browser-process-hrtime: ^1.0.0 - checksum: ec3c2dacbf8050d917bbf89537a101a08c2e333b4c19155f7d3bedde43529d4339db6b3d049d9610789cb915f9515f8be037e0c54c079e9d4735c50b37ed52b9 - languageName: node - linkType: hard - "w3c-keyname@npm:^2.2.4": version: 2.2.8 resolution: "w3c-keyname@npm:2.2.8" @@ -17507,15 +16200,6 @@ __metadata: languageName: node linkType: hard -"w3c-xmlserializer@npm:^2.0.0": - version: 2.0.0 - resolution: "w3c-xmlserializer@npm:2.0.0" - dependencies: - xml-name-validator: ^3.0.0 - checksum: ae25c51cf71f1fb2516df1ab33a481f83461a117565b95e3d0927432522323f93b1b2846cbb60196d337970c421adb604fc2d0d180c6a47a839da01db5b9973b - languageName: node - linkType: hard - "w3c-xmlserializer@npm:^4.0.0": version: 4.0.0 resolution: "w3c-xmlserializer@npm:4.0.0" @@ -17532,7 +16216,7 @@ __metadata: languageName: node linkType: hard -"walker@npm:^1.0.7, walker@npm:^1.0.8, walker@npm:~1.0.5": +"walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" dependencies: @@ -17583,13 +16267,6 @@ __metadata: languageName: node linkType: hard -"webidl-conversions@npm:^5.0.0": - version: 5.0.0 - resolution: "webidl-conversions@npm:5.0.0" - checksum: ccf1ec2ca7c0b5671e5440ace4a66806ae09c49016ab821481bec0c05b1b82695082dc0a27d1fe9d804d475a408ba0c691e6803fd21be608e710955d4589cd69 - languageName: node - linkType: hard - "webidl-conversions@npm:^6.1.0": version: 6.1.0 resolution: "webidl-conversions@npm:6.1.0" @@ -17700,15 +16377,6 @@ __metadata: languageName: node linkType: hard -"whatwg-encoding@npm:^1.0.5": - version: 1.0.5 - resolution: "whatwg-encoding@npm:1.0.5" - dependencies: - iconv-lite: 0.4.24 - checksum: 5be4efe111dce29ddee3448d3915477fcc3b28f991d9cf1300b4e50d6d189010d47bca2f51140a844cf9b726e8f066f4aee72a04d687bfe4f2ee2767b2f5b1e6 - languageName: node - linkType: hard - "whatwg-encoding@npm:^2.0.0": version: 2.0.0 resolution: "whatwg-encoding@npm:2.0.0" @@ -17752,7 +16420,7 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^8.0.0, whatwg-url@npm:^8.5.0": +"whatwg-url@npm:^8.0.0": version: 8.7.0 resolution: "whatwg-url@npm:8.7.0" dependencies: @@ -17776,13 +16444,6 @@ __metadata: languageName: node linkType: hard -"which-module@npm:^2.0.0": - version: 2.0.1 - resolution: "which-module@npm:2.0.1" - checksum: 1967b7ce17a2485544a4fdd9063599f0f773959cca24176dbe8f405e55472d748b7c549cd7920ff6abb8f1ab7db0b0f1b36de1a21c57a8ff741f4f1e792c52be - languageName: node - linkType: hard - "which-typed-array@npm:^1.1.10, which-typed-array@npm:^1.1.11": version: 1.1.11 resolution: "which-typed-array@npm:1.1.11" @@ -17875,17 +16536,6 @@ __metadata: languageName: node linkType: hard -"wrap-ansi@npm:^6.2.0": - version: 6.2.0 - resolution: "wrap-ansi@npm:6.2.0" - dependencies: - ansi-styles: ^4.0.0 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - checksum: 6cd96a410161ff617b63581a08376f0cb9162375adeb7956e10c8cd397821f7eb2a6de24eb22a0b28401300bf228c86e50617cd568209b5f6775b93c97d2fe3a - languageName: node - linkType: hard - "wrap-ansi@npm:^8.1.0": version: 8.1.0 resolution: "wrap-ansi@npm:8.1.0" @@ -17925,18 +16575,6 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^3.0.0": - version: 3.0.3 - resolution: "write-file-atomic@npm:3.0.3" - dependencies: - imurmurhash: ^0.1.4 - is-typedarray: ^1.0.0 - signal-exit: ^3.0.2 - typedarray-to-buffer: ^3.1.5 - checksum: c55b24617cc61c3a4379f425fc62a386cc51916a9b9d993f39734d005a09d5a4bb748bc251f1304e7abd71d0a26d339996c275955f527a131b1dcded67878280 - languageName: node - linkType: hard - "write-file-atomic@npm:^4.0.2": version: 4.0.2 resolution: "write-file-atomic@npm:4.0.2" @@ -18021,13 +16659,6 @@ __metadata: languageName: node linkType: hard -"xml-name-validator@npm:^3.0.0": - version: 3.0.0 - resolution: "xml-name-validator@npm:3.0.0" - checksum: b3ac459afed783c285bb98e4960bd1f3ba12754fd4f2320efa0f9181ca28928c53cc75ca660d15d205e81f92304419afe94c531c7cfb3e0649aa6d140d53ecb0 - languageName: node - linkType: hard - "xml-name-validator@npm:^4.0.0": version: 4.0.0 resolution: "xml-name-validator@npm:4.0.0" @@ -18100,13 +16731,6 @@ __metadata: languageName: node linkType: hard -"y18n@npm:^4.0.0": - version: 4.0.3 - resolution: "y18n@npm:4.0.3" - checksum: 014dfcd9b5f4105c3bb397c1c8c6429a9df004aa560964fb36732bfb999bfe83d45ae40aeda5b55d21b1ee53d8291580a32a756a443e064317953f08025b1aa4 - languageName: node - linkType: hard - "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8" @@ -18142,13 +16766,6 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:20.x, yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": - version: 20.2.9 - resolution: "yargs-parser@npm:20.2.9" - checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 - languageName: node - linkType: hard - "yargs-parser@npm:21.1.1, yargs-parser@npm:^21.0.1, yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" @@ -18156,13 +16773,10 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^18.1.2": - version: 18.1.3 - resolution: "yargs-parser@npm:18.1.3" - dependencies: - camelcase: ^5.0.0 - decamelize: ^1.2.0 - checksum: 60e8c7d1b85814594d3719300ecad4e6ae3796748b0926137bfec1f3042581b8646d67e83c6fc80a692ef08b8390f21ddcacb9464476c39bbdf52e34961dd4d9 +"yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": + version: 20.2.9 + resolution: "yargs-parser@npm:20.2.9" + checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 languageName: node linkType: hard @@ -18181,25 +16795,6 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^15.4.1": - version: 15.4.1 - resolution: "yargs@npm:15.4.1" - dependencies: - cliui: ^6.0.0 - decamelize: ^1.2.0 - find-up: ^4.1.0 - get-caller-file: ^2.0.1 - require-directory: ^2.1.1 - require-main-filename: ^2.0.0 - set-blocking: ^2.0.0 - string-width: ^4.2.0 - which-module: ^2.0.0 - y18n: ^4.0.0 - yargs-parser: ^18.1.2 - checksum: 40b974f508d8aed28598087720e086ecd32a5fd3e945e95ea4457da04ee9bdb8bdd17fd91acff36dc5b7f0595a735929c514c40c402416bbb87c03f6fb782373 - languageName: node - linkType: hard - "yargs@npm:^17.3.1, yargs@npm:^17.6.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" From 640f36c45c3d4a586e5c1c8e6f68e610ca02bf87 Mon Sep 17 00:00:00 2001 From: Jason Weill <93281816+JasonWeill@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:26:31 -0700 Subject: [PATCH 4/4] Adds help text for registry model providers in chat UI settings (#373) * WIP change: display help in settings panel * Interprets markdown, updates Hugging Face help with explicit link * Edits SageMaker help to be neutral in use * Displays help message for all providers with one --- examples/commands.ipynb | 108 ++++++++++++++---- .../jupyter_ai_magics/providers.py | 4 +- packages/jupyter-ai/jupyter_ai/handlers.py | 1 + packages/jupyter-ai/jupyter_ai/models.py | 1 + .../src/components/chat-settings.tsx | 14 ++- packages/jupyter-ai/src/handler.ts | 1 + packages/jupyter-ai/style/chat-settings.css | 11 ++ 7 files changed, 114 insertions(+), 26 deletions(-) diff --git a/examples/commands.ipynb b/examples/commands.ipynb index efc574e55..f2fa722b4 100644 --- a/examples/commands.ipynb +++ b/examples/commands.ipynb @@ -136,13 +136,16 @@ "| Provider | Environment variable | Set? | Models |\n", "|----------|----------------------|------|--------|\n", "| `ai21` | `AI21_API_KEY` | | `ai21:j1-large`, `ai21:j1-grande`, `ai21:j1-jumbo`, `ai21:j1-grande-instruct`, `ai21:j2-large`, `ai21:j2-grande`, `ai21:j2-jumbo`, `ai21:j2-grande-instruct`, `ai21:j2-jumbo-instruct` |\n", - "| `anthropic` | `ANTHROPIC_API_KEY` | | `anthropic:claude-v1`, `anthropic:claude-v1.0`, `anthropic:claude-v1.2`, `anthropic:claude-instant-v1`, `anthropic:claude-instant-v1.0` |\n", + "| `bedrock` | Not applicable. | N/A | `bedrock:amazon.titan-tg1-large`, `bedrock:anthropic.claude-v1`, `bedrock:anthropic.claude-instant-v1`, `bedrock:anthropic.claude-v2`, `bedrock:ai21.j2-jumbo-instruct`, `bedrock:ai21.j2-grande-instruct` |\n", + "| `anthropic` | `ANTHROPIC_API_KEY` | | `anthropic:claude-v1`, `anthropic:claude-v1.0`, `anthropic:claude-v1.2`, `anthropic:claude-2`, `anthropic:claude-instant-v1`, `anthropic:claude-instant-v1.0` |\n", + "| `azure-chat-openai` | `OPENAI_API_KEY` | | This provider does not define a list of models. |\n", "| `cohere` | `COHERE_API_KEY` | | `cohere:medium`, `cohere:xlarge` |\n", - "| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | | See https://huggingface.co/models for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n", + "| `gpt4all` | Not applicable. | N/A | `gpt4all:ggml-gpt4all-j-v1.2-jazzy`, `gpt4all:ggml-gpt4all-j-v1.3-groovy`, `gpt4all:ggml-gpt4all-l13b-snoozy` |\n", + "| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | | See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n", "| `openai` | `OPENAI_API_KEY` | | `openai:text-davinci-003`, `openai:text-davinci-002`, `openai:text-curie-001`, `openai:text-babbage-001`, `openai:text-ada-001`, `openai:davinci`, `openai:curie`, `openai:babbage`, `openai:ada` |\n", - "| `openai-chat` | `OPENAI_API_KEY` | | `openai-chat:gpt-4`, `openai-chat:gpt-4-0314`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0314`, `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-0301` |\n", - "| `openai-chat-new` | `OPENAI_API_KEY` | | `openai-chat-new:gpt-4`, `openai-chat-new:gpt-4-0314`, `openai-chat-new:gpt-4-32k`, `openai-chat-new:gpt-4-32k-0314`, `openai-chat-new:gpt-3.5-turbo`, `openai-chat-new:gpt-3.5-turbo-0301` |\n", - "| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must include the `--region_name`, `--request_schema`, and the `--response_path` arguments. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n", + "| `openai-chat` | `OPENAI_API_KEY` | | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0314`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0314`, `openai-chat:gpt-4-32k-0613` |\n", + "| `openai-chat-new` | `OPENAI_API_KEY` | | `openai-chat-new:gpt-3.5-turbo`, `openai-chat-new:gpt-3.5-turbo-16k`, `openai-chat-new:gpt-3.5-turbo-0301`, `openai-chat-new:gpt-3.5-turbo-0613`, `openai-chat-new:gpt-3.5-turbo-16k-0613`, `openai-chat-new:gpt-4`, `openai-chat-new:gpt-4-0314`, `openai-chat-new:gpt-4-0613`, `openai-chat-new:gpt-4-32k`, `openai-chat-new:gpt-4-32k-0314`, `openai-chat-new:gpt-4-32k-0613` |\n", + "| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n", "\n", "Aliases and custom commands:\n", "\n", @@ -166,22 +169,40 @@ "* ai21:j2-grande-instruct\n", "* ai21:j2-jumbo-instruct\n", "\n", + "bedrock\n", + "* bedrock:amazon.titan-tg1-large\n", + "* bedrock:anthropic.claude-v1\n", + "* bedrock:anthropic.claude-instant-v1\n", + "* bedrock:anthropic.claude-v2\n", + "* bedrock:ai21.j2-jumbo-instruct\n", + "* bedrock:ai21.j2-grande-instruct\n", + "\n", "anthropic\n", "Requires environment variable ANTHROPIC_API_KEY (set)\n", "* anthropic:claude-v1\n", "* anthropic:claude-v1.0\n", "* anthropic:claude-v1.2\n", + "* anthropic:claude-2\n", "* anthropic:claude-instant-v1\n", "* anthropic:claude-instant-v1.0\n", "\n", + "azure-chat-openai\n", + "Requires environment variable OPENAI_API_KEY (set)\n", + "* This provider does not define a list of models.\n", + "\n", "cohere\n", "Requires environment variable COHERE_API_KEY (set)\n", "* cohere:medium\n", "* cohere:xlarge\n", "\n", + "gpt4all\n", + "* gpt4all:ggml-gpt4all-j-v1.2-jazzy\n", + "* gpt4all:ggml-gpt4all-j-v1.3-groovy\n", + "* gpt4all:ggml-gpt4all-l13b-snoozy\n", + "\n", "huggingface_hub\n", "Requires environment variable HUGGINGFACEHUB_API_TOKEN (set)\n", - "* See https://huggingface.co/models for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`.\n", + "* See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`.\n", "\n", "openai\n", "Requires environment variable OPENAI_API_KEY (set)\n", @@ -197,24 +218,34 @@ "\n", "openai-chat\n", "Requires environment variable OPENAI_API_KEY (set)\n", + "* openai-chat:gpt-3.5-turbo\n", + "* openai-chat:gpt-3.5-turbo-16k\n", + "* openai-chat:gpt-3.5-turbo-0301\n", + "* openai-chat:gpt-3.5-turbo-0613\n", + "* openai-chat:gpt-3.5-turbo-16k-0613\n", "* openai-chat:gpt-4\n", "* openai-chat:gpt-4-0314\n", + "* openai-chat:gpt-4-0613\n", "* openai-chat:gpt-4-32k\n", "* openai-chat:gpt-4-32k-0314\n", - "* openai-chat:gpt-3.5-turbo\n", - "* openai-chat:gpt-3.5-turbo-0301\n", + "* openai-chat:gpt-4-32k-0613\n", "\n", "openai-chat-new\n", "Requires environment variable OPENAI_API_KEY (set)\n", + "* openai-chat-new:gpt-3.5-turbo\n", + "* openai-chat-new:gpt-3.5-turbo-16k\n", + "* openai-chat-new:gpt-3.5-turbo-0301\n", + "* openai-chat-new:gpt-3.5-turbo-0613\n", + "* openai-chat-new:gpt-3.5-turbo-16k-0613\n", "* openai-chat-new:gpt-4\n", "* openai-chat-new:gpt-4-0314\n", + "* openai-chat-new:gpt-4-0613\n", "* openai-chat-new:gpt-4-32k\n", "* openai-chat-new:gpt-4-32k-0314\n", - "* openai-chat-new:gpt-3.5-turbo\n", - "* openai-chat-new:gpt-3.5-turbo-0301\n", + "* openai-chat-new:gpt-4-32k-0613\n", "\n", "sagemaker-endpoint\n", - "* Specify an endpoint name as the model ID. In addition, you must include the `--region_name`, `--request_schema`, and the `--response_path` arguments. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints).\n", + "* Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints).\n", "\n", "\n", "Aliases and custom commands:\n", @@ -318,13 +349,16 @@ "| Provider | Environment variable | Set? | Models |\n", "|----------|----------------------|------|--------|\n", "| `ai21` | `AI21_API_KEY` | | `ai21:j1-large`, `ai21:j1-grande`, `ai21:j1-jumbo`, `ai21:j1-grande-instruct`, `ai21:j2-large`, `ai21:j2-grande`, `ai21:j2-jumbo`, `ai21:j2-grande-instruct`, `ai21:j2-jumbo-instruct` |\n", - "| `anthropic` | `ANTHROPIC_API_KEY` | | `anthropic:claude-v1`, `anthropic:claude-v1.0`, `anthropic:claude-v1.2`, `anthropic:claude-instant-v1`, `anthropic:claude-instant-v1.0` |\n", + "| `bedrock` | Not applicable. | N/A | `bedrock:amazon.titan-tg1-large`, `bedrock:anthropic.claude-v1`, `bedrock:anthropic.claude-instant-v1`, `bedrock:anthropic.claude-v2`, `bedrock:ai21.j2-jumbo-instruct`, `bedrock:ai21.j2-grande-instruct` |\n", + "| `anthropic` | `ANTHROPIC_API_KEY` | | `anthropic:claude-v1`, `anthropic:claude-v1.0`, `anthropic:claude-v1.2`, `anthropic:claude-2`, `anthropic:claude-instant-v1`, `anthropic:claude-instant-v1.0` |\n", + "| `azure-chat-openai` | `OPENAI_API_KEY` | | This provider does not define a list of models. |\n", "| `cohere` | `COHERE_API_KEY` | | `cohere:medium`, `cohere:xlarge` |\n", - "| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | | See https://huggingface.co/models for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n", + "| `gpt4all` | Not applicable. | N/A | `gpt4all:ggml-gpt4all-j-v1.2-jazzy`, `gpt4all:ggml-gpt4all-j-v1.3-groovy`, `gpt4all:ggml-gpt4all-l13b-snoozy` |\n", + "| `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | | See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`. |\n", "| `openai` | `OPENAI_API_KEY` | | `openai:text-davinci-003`, `openai:text-davinci-002`, `openai:text-curie-001`, `openai:text-babbage-001`, `openai:text-ada-001`, `openai:davinci`, `openai:curie`, `openai:babbage`, `openai:ada` |\n", - "| `openai-chat` | `OPENAI_API_KEY` | | `openai-chat:gpt-4`, `openai-chat:gpt-4-0314`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0314`, `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-0301` |\n", - "| `openai-chat-new` | `OPENAI_API_KEY` | | `openai-chat-new:gpt-4`, `openai-chat-new:gpt-4-0314`, `openai-chat-new:gpt-4-32k`, `openai-chat-new:gpt-4-32k-0314`, `openai-chat-new:gpt-3.5-turbo`, `openai-chat-new:gpt-3.5-turbo-0301` |\n", - "| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must include the `--region_name`, `--request_schema`, and the `--response_path` arguments. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n", + "| `openai-chat` | `OPENAI_API_KEY` | | `openai-chat:gpt-3.5-turbo`, `openai-chat:gpt-3.5-turbo-16k`, `openai-chat:gpt-3.5-turbo-0301`, `openai-chat:gpt-3.5-turbo-0613`, `openai-chat:gpt-3.5-turbo-16k-0613`, `openai-chat:gpt-4`, `openai-chat:gpt-4-0314`, `openai-chat:gpt-4-0613`, `openai-chat:gpt-4-32k`, `openai-chat:gpt-4-32k-0314`, `openai-chat:gpt-4-32k-0613` |\n", + "| `openai-chat-new` | `OPENAI_API_KEY` | | `openai-chat-new:gpt-3.5-turbo`, `openai-chat-new:gpt-3.5-turbo-16k`, `openai-chat-new:gpt-3.5-turbo-0301`, `openai-chat-new:gpt-3.5-turbo-0613`, `openai-chat-new:gpt-3.5-turbo-16k-0613`, `openai-chat-new:gpt-4`, `openai-chat-new:gpt-4-0314`, `openai-chat-new:gpt-4-0613`, `openai-chat-new:gpt-4-32k`, `openai-chat-new:gpt-4-32k-0314`, `openai-chat-new:gpt-4-32k-0613` |\n", + "| `sagemaker-endpoint` | Not applicable. | N/A | Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints). |\n", "\n", "Aliases and custom commands:\n", "\n", @@ -349,22 +383,40 @@ "* ai21:j2-grande-instruct\n", "* ai21:j2-jumbo-instruct\n", "\n", + "bedrock\n", + "* bedrock:amazon.titan-tg1-large\n", + "* bedrock:anthropic.claude-v1\n", + "* bedrock:anthropic.claude-instant-v1\n", + "* bedrock:anthropic.claude-v2\n", + "* bedrock:ai21.j2-jumbo-instruct\n", + "* bedrock:ai21.j2-grande-instruct\n", + "\n", "anthropic\n", "Requires environment variable ANTHROPIC_API_KEY (set)\n", "* anthropic:claude-v1\n", "* anthropic:claude-v1.0\n", "* anthropic:claude-v1.2\n", + "* anthropic:claude-2\n", "* anthropic:claude-instant-v1\n", "* anthropic:claude-instant-v1.0\n", "\n", + "azure-chat-openai\n", + "Requires environment variable OPENAI_API_KEY (set)\n", + "* This provider does not define a list of models.\n", + "\n", "cohere\n", "Requires environment variable COHERE_API_KEY (set)\n", "* cohere:medium\n", "* cohere:xlarge\n", "\n", + "gpt4all\n", + "* gpt4all:ggml-gpt4all-j-v1.2-jazzy\n", + "* gpt4all:ggml-gpt4all-j-v1.3-groovy\n", + "* gpt4all:ggml-gpt4all-l13b-snoozy\n", + "\n", "huggingface_hub\n", "Requires environment variable HUGGINGFACEHUB_API_TOKEN (set)\n", - "* See https://huggingface.co/models for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`.\n", + "* See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`.\n", "\n", "openai\n", "Requires environment variable OPENAI_API_KEY (set)\n", @@ -380,24 +432,34 @@ "\n", "openai-chat\n", "Requires environment variable OPENAI_API_KEY (set)\n", + "* openai-chat:gpt-3.5-turbo\n", + "* openai-chat:gpt-3.5-turbo-16k\n", + "* openai-chat:gpt-3.5-turbo-0301\n", + "* openai-chat:gpt-3.5-turbo-0613\n", + "* openai-chat:gpt-3.5-turbo-16k-0613\n", "* openai-chat:gpt-4\n", "* openai-chat:gpt-4-0314\n", + "* openai-chat:gpt-4-0613\n", "* openai-chat:gpt-4-32k\n", "* openai-chat:gpt-4-32k-0314\n", - "* openai-chat:gpt-3.5-turbo\n", - "* openai-chat:gpt-3.5-turbo-0301\n", + "* openai-chat:gpt-4-32k-0613\n", "\n", "openai-chat-new\n", "Requires environment variable OPENAI_API_KEY (set)\n", + "* openai-chat-new:gpt-3.5-turbo\n", + "* openai-chat-new:gpt-3.5-turbo-16k\n", + "* openai-chat-new:gpt-3.5-turbo-0301\n", + "* openai-chat-new:gpt-3.5-turbo-0613\n", + "* openai-chat-new:gpt-3.5-turbo-16k-0613\n", "* openai-chat-new:gpt-4\n", "* openai-chat-new:gpt-4-0314\n", + "* openai-chat-new:gpt-4-0613\n", "* openai-chat-new:gpt-4-32k\n", "* openai-chat-new:gpt-4-32k-0314\n", - "* openai-chat-new:gpt-3.5-turbo\n", - "* openai-chat-new:gpt-3.5-turbo-0301\n", + "* openai-chat-new:gpt-4-32k-0613\n", "\n", "sagemaker-endpoint\n", - "* Specify an endpoint name as the model ID. In addition, you must include the `--region_name`, `--request_schema`, and the `--response_path` arguments. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints).\n", + "* Specify an endpoint name as the model ID. In addition, you must specify a region name, request schema, and response path. For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints).\n", "\n", "\n", "Aliases and custom commands:\n", @@ -1055,7 +1117,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py b/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py index 93616a655..149cf9fd8 100644 --- a/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py +++ b/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py @@ -300,7 +300,7 @@ class HfHubProvider(BaseProvider, HuggingFaceHub): models = ["*"] model_id_key = "repo_id" help = ( - "See https://huggingface.co/models for a list of models. " + "See [https://huggingface.co/models](https://huggingface.co/models) for a list of models. " "Pass a model's repository ID as the model ID; for example, `huggingface_hub:ExampleOwner/example-model`." ) # ipywidgets needed to suppress tqdm warning @@ -542,7 +542,7 @@ class SmEndpointProvider(BaseProvider, SagemakerEndpoint): # This all needs to be on one line of markdown, for use in a table help = ( "Specify an endpoint name as the model ID. " - "In addition, you must include the `--region_name`, `--request_schema`, and the `--response_path` arguments. " + "In addition, you must specify a region name, request schema, and response path. " "For more information, see the documentation about [SageMaker endpoints deployment](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints-deployment.html) " "and about [using magic commands with SageMaker endpoints](https://jupyter-ai.readthedocs.io/en/latest/users/index.html#using-magic-commands-with-sagemaker-endpoints)." ) diff --git a/packages/jupyter-ai/jupyter_ai/handlers.py b/packages/jupyter-ai/jupyter_ai/handlers.py index 965da598c..ddc4c6255 100644 --- a/packages/jupyter-ai/jupyter_ai/handlers.py +++ b/packages/jupyter-ai/jupyter_ai/handlers.py @@ -262,6 +262,7 @@ def get(self): id=provider.id, name=provider.name, models=provider.models, + help=provider.help, auth_strategy=provider.auth_strategy, registry=provider.registry, fields=provider.fields, diff --git a/packages/jupyter-ai/jupyter_ai/models.py b/packages/jupyter-ai/jupyter_ai/models.py index 8e4e992aa..efe501923 100644 --- a/packages/jupyter-ai/jupyter_ai/models.py +++ b/packages/jupyter-ai/jupyter_ai/models.py @@ -79,6 +79,7 @@ class ListProvidersEntry(BaseModel): name: str model_id_label: Optional[str] models: List[str] + help: Optional[str] auth_strategy: AuthStrategy registry: bool fields: List[Field] diff --git a/packages/jupyter-ai/src/components/chat-settings.tsx b/packages/jupyter-ai/src/components/chat-settings.tsx index 773e519b4..583cfa9f0 100644 --- a/packages/jupyter-ai/src/components/chat-settings.tsx +++ b/packages/jupyter-ai/src/components/chat-settings.tsx @@ -1,4 +1,7 @@ import React, { useEffect, useState, useMemo } from 'react'; + +import ReactMarkdown from 'react-markdown'; + import { Box } from '@mui/system'; import { Alert, @@ -10,7 +13,8 @@ import { Radio, RadioGroup, TextField, - CircularProgress + CircularProgress, + Typography } from '@mui/material'; import { Select } from './select'; @@ -36,6 +40,7 @@ export function ChatSettings(): JSX.Element { const [lmProvider, setLmProvider] = useState(null); const [showLmLocalId, setShowLmLocalId] = useState(false); + const [helpMarkdown, setHelpMarkdown] = useState(null); const [lmLocalId, setLmLocalId] = useState(''); const lmGlobalId = useMemo(() => { if (!lmProvider) { @@ -72,6 +77,7 @@ export function ChatSettings(): JSX.Element { setLmLocalId(server.lmLocalId); setEmGlobalId(server.config.embeddings_provider_id); setSendWse(server.config.send_with_shift_enter); + setHelpMarkdown(server.lmProvider?.help ?? null); if (server.lmProvider?.registry) { setShowLmLocalId(true); } @@ -237,6 +243,7 @@ export function ChatSettings(): JSX.Element { const nextLmLocalId = getModelLocalId(lmGid)!; setLmProvider(nextLmProvider); + setHelpMarkdown(nextLmProvider?.help ?? null); if (nextLmProvider.registry) { setLmLocalId(''); setShowLmLocalId(true); @@ -264,6 +271,11 @@ export function ChatSettings(): JSX.Element { fullWidth /> )} + {helpMarkdown && ( + + {helpMarkdown} + + )} {lmGlobalId && (