diff --git a/.gitignore b/.gitignore index b18810b57..79f88f5fd 100644 --- a/.gitignore +++ b/.gitignore @@ -132,3 +132,5 @@ dev.sh .jupyter_ystore.db .yarn + +.conda/ diff --git a/docs/source/users/index.md b/docs/source/users/index.md index 28f34ddf3..d413aed57 100644 --- a/docs/source/users/index.md +++ b/docs/source/users/index.md @@ -122,7 +122,7 @@ Jupyter AI supports a wide range of model providers and models. To use Jupyter A Jupyter AI supports the following model providers: -| Provider | Provider ID | Environment variable | Python package(s) | +| Provider | Provider ID | Environment variable(s) | Python package(s) | |---------------------|----------------------|----------------------------|---------------------------------| | AI21 | `ai21` | `AI21_API_KEY` | `ai21` | | Anthropic | `anthropic` | `ANTHROPIC_API_KEY` | `anthropic` | @@ -130,6 +130,7 @@ Jupyter AI supports the following model providers: | Bedrock | `bedrock` | N/A | `boto3` | | Bedrock (chat) | `bedrock-chat` | N/A | `boto3` | | Cohere | `cohere` | `COHERE_API_KEY` | `cohere` | +| ERNIE-Bot | `qianfan` | `QIANFAN_AK`, `QIANFAN_SK` | `qianfan` | | GPT4All | `gpt4all` | N/A | `gpt4all` | | Hugging Face Hub | `huggingface_hub` | `HUGGINGFACEHUB_API_TOKEN` | `huggingface_hub`, `ipywidgets`, `pillow` | | OpenAI | `openai` | `OPENAI_API_KEY` | `openai` | @@ -137,6 +138,7 @@ Jupyter AI supports the following model providers: | SageMaker | `sagemaker-endpoint` | N/A | `boto3` | The environment variable names shown above are also the names of the settings keys used when setting up the chat interface. +If multiple variables are listed for a provider, **all** must be specified. To use the Bedrock models, you need access to the Bedrock service. For more information, see the [Amazon Bedrock Homepage](https://aws.amazon.com/bedrock/). diff --git a/packages/jupyter-ai-magics/jupyter_ai_magics/__init__.py b/packages/jupyter-ai-magics/jupyter_ai_magics/__init__.py index cf808476a..1bfdaeb24 100644 --- a/packages/jupyter-ai-magics/jupyter_ai_magics/__init__.py +++ b/packages/jupyter-ai-magics/jupyter_ai_magics/__init__.py @@ -8,6 +8,7 @@ GPT4AllEmbeddingsProvider, HfHubEmbeddingsProvider, OpenAIEmbeddingsProvider, + QianfanEmbeddingsEndpointProvider, ) from .exception import store_exception from .magics import AiMagics @@ -27,6 +28,7 @@ GPT4AllProvider, HfHubProvider, OpenAIProvider, + QianfanProvider, SmEndpointProvider, ) diff --git a/packages/jupyter-ai-magics/jupyter_ai_magics/aliases.py b/packages/jupyter-ai-magics/jupyter_ai_magics/aliases.py index ab383af32..96cac4efe 100644 --- a/packages/jupyter-ai-magics/jupyter_ai_magics/aliases.py +++ b/packages/jupyter-ai-magics/jupyter_ai_magics/aliases.py @@ -3,4 +3,7 @@ "gpt3": "openai:text-davinci-003", "chatgpt": "openai-chat:gpt-3.5-turbo", "gpt4": "openai-chat:gpt-4", + "ernie-bot": "qianfan:ERNIE-Bot", + "ernie-bot-4": "qianfan:ERNIE-Bot-4", + "titan": "bedrock:amazon.titan-tg1-large", } diff --git a/packages/jupyter-ai-magics/jupyter_ai_magics/embedding_providers.py b/packages/jupyter-ai-magics/jupyter_ai_magics/embedding_providers.py index 7dcda78b8..75c8fa0a3 100644 --- a/packages/jupyter-ai-magics/jupyter_ai_magics/embedding_providers.py +++ b/packages/jupyter-ai-magics/jupyter_ai_magics/embedding_providers.py @@ -6,6 +6,7 @@ AwsAuthStrategy, EnvAuthStrategy, Field, + MultiEnvAuthStrategy, ) from langchain.embeddings import ( BedrockEmbeddings, @@ -13,6 +14,7 @@ GPT4AllEmbeddings, HuggingFaceHubEmbeddings, OpenAIEmbeddings, + QianfanEmbeddingsEndpoint, ) from langchain.pydantic_v1 import BaseModel, Extra @@ -127,3 +129,14 @@ def __init__(self, **kwargs): models = ["all-MiniLM-L6-v2-f16"] model_id_key = "model_id" pypi_package_deps = ["gpt4all"] + + +class QianfanEmbeddingsEndpointProvider( + BaseEmbeddingsProvider, QianfanEmbeddingsEndpoint +): + id = "qianfan" + name = "ERNIE-Bot" + models = ["ERNIE-Bot", "ERNIE-Bot-4"] + model_id_key = "model" + pypi_package_deps = ["qianfan"] + auth_strategy = MultiEnvAuthStrategy(names=["QIANFAN_AK", "QIANFAN_SK"]) diff --git a/packages/jupyter-ai-magics/jupyter_ai_magics/magics.py b/packages/jupyter-ai-magics/jupyter_ai_magics/magics.py index 8763566f4..f34e28a22 100644 --- a/packages/jupyter-ai-magics/jupyter_ai_magics/magics.py +++ b/packages/jupyter-ai-magics/jupyter_ai_magics/magics.py @@ -11,6 +11,7 @@ from IPython import get_ipython from IPython.core.magic import Magics, line_cell_magic, magics_class from IPython.display import HTML, JSON, Markdown, Math +from jupyter_ai_magics.aliases import MODEL_ID_ALIASES from jupyter_ai_magics.utils import decompose_model_id, get_lm_providers from langchain.chains import LLMChain from langchain.schema import HumanMessage @@ -28,14 +29,6 @@ ) from .providers import BaseProvider -MODEL_ID_ALIASES = { - "gpt2": "huggingface_hub:gpt2", - "gpt3": "openai:text-davinci-003", - "chatgpt": "openai-chat:gpt-3.5-turbo", - "gpt4": "openai-chat:gpt-4", - "titan": "bedrock:amazon.titan-tg1-large", -} - class TextOrMarkdown: def __init__(self, text, markdown): @@ -95,6 +88,18 @@ def _repr_mimebundle_(self, include=None, exclude=None): AI_COMMANDS = {"delete", "error", "help", "list", "register", "update"} +# Strings for listing providers and models +# Avoid composing strings, to make localization easier in the future +ENV_NOT_SET = "You have not set this environment variable, so you cannot use this provider's models." +ENV_SET = ( + "You have set this environment variable, so you can use this provider's models." +) +MULTIENV_NOT_SET = "You have not set all of these environment variables, so you cannot use this provider's models." +MULTIENV_SET = "You have set all of these environment variables, so you can use this provider's models." + +ENV_REQUIRES = "Requires environment variable:" +MULTIENV_REQUIRES = "Requires environment variables:" + class FormatDict(dict): """Subclass of dict to be passed to str#format(). Suppresses KeyError and @@ -177,44 +182,53 @@ def _ai_env_status_for_provider_markdown(self, provider_id): ): return na_message # No emoji - try: - env_var = self.providers[provider_id].auth_strategy.name - except AttributeError: # No "name" attribute + not_set_title = ENV_NOT_SET + set_title = ENV_SET + env_status_ok = False + + auth_strategy = self.providers[provider_id].auth_strategy + if auth_strategy.type == "env": + var_name = auth_strategy.name + env_var_display = f"`{var_name}`" + env_status_ok = var_name in os.environ + elif auth_strategy.type == "multienv": + # Check multiple environment variables + var_names = self.providers[provider_id].auth_strategy.names + formatted_names = [f"`{name}`" for name in var_names] + env_var_display = ", ".join(formatted_names) + env_status_ok = all(var_name in os.environ for var_name in var_names) + not_set_title = MULTIENV_NOT_SET + set_title = MULTIENV_SET + else: # No environment variables return na_message - output = f"`{env_var}` | " - if os.getenv(env_var) == None: - output += ( - '" - ) + output = f"{env_var_display} | " + if env_status_ok: + output += f'' else: - output += ( - '" - ) + output += f'' return output def _ai_env_status_for_provider_text(self, provider_id): - if ( - provider_id not in self.providers - or self.providers[provider_id].auth_strategy == None + # only handle providers with "env" or "multienv" auth strategy + auth_strategy = getattr(self.providers[provider_id], "auth_strategy", None) + if not auth_strategy or ( + auth_strategy.type != "env" and auth_strategy.type != "multienv" ): - return "" # No message necessary - - try: - env_var = self.providers[provider_id].auth_strategy.name - except AttributeError: # No "name" attribute return "" - output = f"Requires environment variable {env_var} " - if os.getenv(env_var) != None: - output += "(set)" - else: - output += "(not set)" + prefix = ENV_REQUIRES if auth_strategy.type == "env" else MULTIENV_REQUIRES + envvars = ( + [auth_strategy.name] + if auth_strategy.type == "env" + else auth_strategy.names[:] + ) + + for i in range(len(envvars)): + envvars[i] += " (set)" if envvars[i] in os.environ else " (not set)" - return output + "\n" + return prefix + " " + ", ".join(envvars) + "\n" # Is this a name of a Python variable that can be called as a LangChain chain? def _is_langchain_chain(self, name): @@ -493,13 +507,22 @@ def run_ai_cell(self, args: CellArgs, prompt: str): # validate presence of authn credentials auth_strategy = self.providers[provider_id].auth_strategy if auth_strategy: - # TODO: handle auth strategies besides EnvAuthStrategy if auth_strategy.type == "env" and auth_strategy.name not in os.environ: raise OSError( - f"Authentication environment variable {auth_strategy.name} not provided.\n" + f"Authentication environment variable {auth_strategy.name} is not set.\n" f"An authentication token is required to use models from the {Provider.name} provider.\n" f"Please specify it via `%env {auth_strategy.name}=token`. " ) from None + if auth_strategy.type == "multienv": + # Multiple environment variables must be set + missing_vars = [ + var for var in auth_strategy.names if var not in os.environ + ] + raise OSError( + f"Authentication environment variables {missing_vars} are not set.\n" + f"Multiple authentication tokens are required to use models from the {Provider.name} provider.\n" + f"Please specify them all via `%env` commands. " + ) from None # configure and instantiate provider provider_params = {"model_id": local_model_id} diff --git a/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py b/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py index 8d353638d..166925ef7 100644 --- a/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py +++ b/packages/jupyter-ai-magics/jupyter_ai_magics/providers.py @@ -23,6 +23,7 @@ BedrockChat, ChatAnthropic, ChatOpenAI, + QianfanChatEndpoint, ) from langchain.chat_models.base import BaseChatModel from langchain.llms import ( @@ -34,6 +35,7 @@ HuggingFaceHub, OpenAI, OpenAIChat, + QianfanLLMEndpoint, SagemakerEndpoint, ) from langchain.llms.sagemaker_endpoint import LLMContentHandler @@ -54,7 +56,7 @@ class EnvAuthStrategy(BaseModel): class MultiEnvAuthStrategy(BaseModel): """Require multiple auth tokens via multiple environment variables.""" - type: Literal["file"] = "file" + type: Literal["multienv"] = "multienv" names: List[str] @@ -516,6 +518,7 @@ class OpenAIProvider(BaseProvider, OpenAI): "text-curie-001", "text-babbage-001", "text-ada-001", + "gpt-3.5-turbo-instruct", "davinci", "curie", "babbage", @@ -775,3 +778,13 @@ async def _agenerate(self, *args, **kwargs) -> Coroutine[Any, Any, LLMResult]: @property def allows_concurrency(self): return not "anthropic" in self.model_id + + +# Baidu QianfanChat provider. temporarily living as a separate class until +class QianfanProvider(BaseProvider, QianfanChatEndpoint): + id = "qianfan" + name = "ERNIE-Bot" + models = ["ERNIE-Bot", "ERNIE-Bot-4"] + model_id_key = "model_name" + pypi_package_deps = ["qianfan"] + auth_strategy = MultiEnvAuthStrategy(names=["QIANFAN_AK", "QIANFAN_SK"]) diff --git a/packages/jupyter-ai-magics/pyproject.toml b/packages/jupyter-ai-magics/pyproject.toml index f280f1619..05e11a10d 100644 --- a/packages/jupyter-ai-magics/pyproject.toml +++ b/packages/jupyter-ai-magics/pyproject.toml @@ -50,7 +50,8 @@ all = [ "ipywidgets", "pillow", "openai", - "boto3" + "boto3", + "qianfan" ] [project.entry-points."jupyter_ai.model_providers"] @@ -67,6 +68,7 @@ sagemaker-endpoint = "jupyter_ai_magics:SmEndpointProvider" amazon-bedrock = "jupyter_ai_magics:BedrockProvider" anthropic-chat = "jupyter_ai_magics:ChatAnthropicProvider" amazon-bedrock-chat = "jupyter_ai_magics:BedrockChatProvider" +qianfan = "jupyter_ai_magics:QianfanProvider" [project.entry-points."jupyter_ai.embeddings_model_providers"] bedrock = "jupyter_ai_magics:BedrockEmbeddingsProvider" @@ -74,6 +76,7 @@ cohere = "jupyter_ai_magics:CohereEmbeddingsProvider" gpt4all = "jupyter_ai_magics:GPT4AllEmbeddingsProvider" huggingface_hub = "jupyter_ai_magics:HfHubEmbeddingsProvider" openai = "jupyter_ai_magics:OpenAIEmbeddingsProvider" +qianfan = "jupyter_ai_magics:QianfanEmbeddingsEndpointProvider" [tool.hatch.version] source = "nodejs" diff --git a/packages/jupyter-ai/jupyter_ai/completions/__init__.py b/packages/jupyter-ai/jupyter_ai/completions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/jupyter-ai/jupyter_ai/completions/handlers/__init__.py b/packages/jupyter-ai/jupyter_ai/completions/handlers/__init__.py new file mode 100644 index 000000000..f0d412a94 --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/completions/handlers/__init__.py @@ -0,0 +1,4 @@ +from .base import BaseInlineCompletionHandler +from .default import DefaultInlineCompletionHandler + +__all__ = ["BaseInlineCompletionHandler", "DefaultInlineCompletionHandler"] diff --git a/packages/jupyter-ai/jupyter_ai/completions/handlers/base.py b/packages/jupyter-ai/jupyter_ai/completions/handlers/base.py new file mode 100644 index 000000000..275bf2bd0 --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/completions/handlers/base.py @@ -0,0 +1,76 @@ +import traceback + +# necessary to prevent circular import +from typing import TYPE_CHECKING, AsyncIterator, Dict + +from jupyter_ai.completions.handlers.llm_mixin import LLMHandlerMixin +from jupyter_ai.completions.models import ( + CompletionError, + InlineCompletionList, + InlineCompletionReply, + InlineCompletionRequest, + InlineCompletionStreamChunk, + ModelChangedNotification, +) +from jupyter_ai.config_manager import ConfigManager, Logger + +if TYPE_CHECKING: + from jupyter_ai.handlers import InlineCompletionHandler + + +class BaseInlineCompletionHandler(LLMHandlerMixin): + """Class implementing completion handling.""" + + handler_kind = "completion" + + def __init__( + self, + log: Logger, + config_manager: ConfigManager, + model_parameters: Dict[str, Dict], + ws_sessions: Dict[str, "InlineCompletionHandler"], + ): + super().__init__(log, config_manager, model_parameters) + self.ws_sessions = ws_sessions + + async def on_message( + self, message: InlineCompletionRequest + ) -> InlineCompletionReply: + try: + return await self.process_message(message) + except Exception as e: + return await self._handle_exc(e, message) + + async def process_message( + self, message: InlineCompletionRequest + ) -> InlineCompletionReply: + """ + Processes an inline completion request. Completion handlers + (subclasses) must implement this method. + + The method definition does not need to be wrapped in a try/except block. + """ + raise NotImplementedError("Should be implemented by subclasses.") + + async def stream( + self, message: InlineCompletionRequest + ) -> AsyncIterator[InlineCompletionStreamChunk]: + """ " + Stream the inline completion as it is generated. Completion handlers + (subclasses) can implement this method. + """ + raise NotImplementedError() + + async def _handle_exc(self, e: Exception, message: InlineCompletionRequest): + error = CompletionError( + type=e.__class__.__name__, + title=e.args[0] if e.args else "Exception", + traceback=traceback.format_exc(), + ) + return InlineCompletionReply( + list=InlineCompletionList(items=[]), error=error, reply_to=message.number + ) + + def broadcast(self, message: ModelChangedNotification): + for session in self.ws_sessions.values(): + session.write_message(message.dict()) diff --git a/packages/jupyter-ai/jupyter_ai/completions/handlers/default.py b/packages/jupyter-ai/jupyter_ai/completions/handlers/default.py new file mode 100644 index 000000000..7cf771342 --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/completions/handlers/default.py @@ -0,0 +1,184 @@ +from typing import Dict, Type + +from jupyter_ai_magics.providers import BaseProvider +from langchain.prompts import ( + ChatPromptTemplate, + HumanMessagePromptTemplate, + PromptTemplate, + SystemMessagePromptTemplate, +) +from langchain.schema.output_parser import StrOutputParser +from langchain.schema.runnable import Runnable + +from ..models import ( + InlineCompletionList, + InlineCompletionReply, + InlineCompletionRequest, + InlineCompletionStreamChunk, + ModelChangedNotification, +) +from .base import BaseInlineCompletionHandler + +SYSTEM_PROMPT = """ +You are an application built to provide helpful code completion suggestions. +You should only produce code. Keep comments to minimum, use the +programming language comment syntax. Produce clean code. +The code is written in JupyterLab, a data analysis and code development +environment which can execute code extended with additional syntax for +interactive features, such as magics. +""".strip() + +AFTER_TEMPLATE = """ +The code after the completion request is: + +``` +{suffix} +``` +""".strip() + +DEFAULT_TEMPLATE = """ +The document is called `{filename}` and written in {language}. +{after} + +Complete the following code: + +``` +{prefix}""" + + +class DefaultInlineCompletionHandler(BaseInlineCompletionHandler): + llm_chain: Runnable + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def create_llm_chain( + self, provider: Type[BaseProvider], provider_params: Dict[str, str] + ): + lm_provider = self.config_manager.lm_provider + lm_provider_params = self.config_manager.lm_provider_params + next_lm_id = ( + f'{lm_provider.id}:{lm_provider_params["model_id"]}' + if lm_provider + else None + ) + self.broadcast(ModelChangedNotification(model=next_lm_id)) + + model_parameters = self.get_model_parameters(provider, provider_params) + llm = provider(**provider_params, **model_parameters) + + if llm.is_chat_provider: + prompt_template = ChatPromptTemplate.from_messages( + [ + SystemMessagePromptTemplate.from_template(SYSTEM_PROMPT), + HumanMessagePromptTemplate.from_template(DEFAULT_TEMPLATE), + ] + ) + else: + prompt_template = PromptTemplate( + input_variables=["prefix", "suffix", "language", "filename"], + template=SYSTEM_PROMPT + "\n\n" + DEFAULT_TEMPLATE, + ) + + self.llm = llm + self.llm_chain = prompt_template | llm | StrOutputParser() + + async def process_message( + self, request: InlineCompletionRequest + ) -> InlineCompletionReply: + if request.stream: + token = self._token_from_request(request, 0) + return InlineCompletionReply( + list=InlineCompletionList( + items=[ + { + # insert text starts empty as we do not pre-generate any part + "insertText": "", + "isIncomplete": True, + "token": token, + } + ] + ), + reply_to=request.number, + ) + else: + self.get_llm_chain() + model_arguments = self._template_inputs_from_request(request) + suggestion = await self.llm_chain.ainvoke(input=model_arguments) + suggestion = self._post_process_suggestion(suggestion, request) + return InlineCompletionReply( + list=InlineCompletionList(items=[{"insertText": suggestion}]), + reply_to=request.number, + ) + + async def stream(self, request: InlineCompletionRequest): + self.get_llm_chain() + token = self._token_from_request(request, 0) + model_arguments = self._template_inputs_from_request(request) + suggestion = "" + async for fragment in self.llm_chain.astream(input=model_arguments): + suggestion += fragment + if suggestion.startswith("```"): + if "\n" not in suggestion: + # we are not ready to apply post-processing + continue + else: + suggestion = self._post_process_suggestion(suggestion, request) + yield InlineCompletionStreamChunk( + type="stream", + response={"insertText": suggestion, "token": token}, + reply_to=request.number, + done=False, + ) + # at the end send a message confirming that we are done + yield InlineCompletionStreamChunk( + type="stream", + response={"insertText": suggestion, "token": token}, + reply_to=request.number, + done=True, + ) + + def _token_from_request(self, request: InlineCompletionRequest, suggestion: int): + """Generate a deterministic token (for matching streamed messages) + using request number and suggestion number""" + return f"t{request.number}s{suggestion}" + + def _template_inputs_from_request(self, request: InlineCompletionRequest) -> Dict: + suffix = request.suffix.strip() + # only add the suffix template if the suffix is there to save input tokens/computation time + after = AFTER_TEMPLATE.format(suffix=suffix) if suffix else "" + filename = request.path.split("/")[-1] if request.path else "untitled" + + return { + "prefix": request.prefix, + "after": after, + "language": request.language, + "filename": filename, + "stop": ["\n```"], + } + + def _post_process_suggestion( + self, suggestion: str, request: InlineCompletionRequest + ) -> str: + """Remove spurious fragments from the suggestion. + + While most models (especially instruct and infill models do not require + any pre-processing, some models such as gpt-4 which only have chat APIs + may require removing spurious fragments. This function uses heuristics + and request data to remove such fragments. + """ + # gpt-4 tends to add "```python" or similar + language = request.language or "python" + markdown_identifiers = {"ipython": ["ipython", "python", "py"]} + bad_openings = [ + f"```{identifier}" + for identifier in markdown_identifiers.get(language, [language]) + ] + ["```"] + for opening in bad_openings: + if suggestion.startswith(opening): + suggestion = suggestion[len(opening) :].lstrip() + # check for the prefix inclusion (only if there was a bad opening) + if suggestion.startswith(request.prefix): + suggestion = suggestion[len(request.prefix) :] + break + return suggestion diff --git a/packages/jupyter-ai/jupyter_ai/completions/handlers/llm_mixin.py b/packages/jupyter-ai/jupyter_ai/completions/handlers/llm_mixin.py new file mode 100644 index 000000000..a0a3b0505 --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/completions/handlers/llm_mixin.py @@ -0,0 +1,73 @@ +from typing import Dict, Type + +from jupyter_ai.config_manager import ConfigManager, Logger +from jupyter_ai_magics.providers import BaseProvider + + +class LLMHandlerMixin: + """Base class containing shared methods and attributes used by LLM handler classes.""" + + # This could be used to derive `BaseChatHandler` too (there is a lot of duplication!), + # but it was decided against it to avoid introducing conflicts for backports against 1.x + + handler_kind: str + + def __init__( + self, + log: Logger, + config_manager: ConfigManager, + model_parameters: Dict[str, Dict], + ): + self.log = log + self.config_manager = config_manager + self.model_parameters = model_parameters + self.llm = None + self.llm_params = None + self.llm_chain = None + + def model_changed_callback(self): + """Method which can be overridden in sub-classes to listen to model change.""" + pass + + def get_llm_chain(self): + 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 + ) + next_lm_id = ( + f'{lm_provider.id}:{lm_provider_params["model_id"]}' + if lm_provider + else None + ) + + if not lm_provider or not lm_provider_params: + return None + + if curr_lm_id != next_lm_id: + self.log.info( + f"Switching {self.handler_kind} language model from {curr_lm_id} to {next_lm_id}." + ) + self.create_llm_chain(lm_provider, lm_provider_params) + self.model_changed_callback() + elif self.llm_params != lm_provider_params: + self.log.info( + f"{self.handler_kind} model params changed, updating the llm chain." + ) + self.create_llm_chain(lm_provider, lm_provider_params) + + self.llm_params = lm_provider_params + return self.llm_chain + + def get_model_parameters( + self, provider: Type[BaseProvider], provider_params: Dict[str, str] + ): + return self.model_parameters.get( + f"{provider.id}:{provider_params['model_id']}", {} + ) + + def create_llm_chain( + self, provider: Type[BaseProvider], provider_params: Dict[str, str] + ): + raise NotImplementedError("Should be implemented by subclasses") diff --git a/packages/jupyter-ai/jupyter_ai/completions/models.py b/packages/jupyter-ai/jupyter_ai/completions/models.py new file mode 100644 index 000000000..a64610036 --- /dev/null +++ b/packages/jupyter-ai/jupyter_ai/completions/models.py @@ -0,0 +1,76 @@ +from typing import List, Literal, Optional + +from pydantic import BaseModel + + +class InlineCompletionRequest(BaseModel): + """Message send by client to request inline completions. + + Prefix/suffix implementation is used to avoid the need for synchronising + the notebook state at every key press (subject to change in future).""" + + # unique message ID generated by the client used to identify replies and + # to easily discard replies for older requests + number: int + # prefix should include full text of the current cell preceding the cursor + prefix: str + # suffix should include full text of the current cell preceding the cursor + suffix: str + # media type for the current language, e.g. `text/x-python` + mime: str + # whether to stream the response (if supported by the model) + stream: bool + # path to the notebook of file for which the completions are generated + path: Optional[str] + # language inferred from the document mime type (if possible) + language: Optional[str] + # identifier of the cell for which the completions are generated if in a notebook + # previous cells and following cells can be used to learn the wider context + cell_id: Optional[str] + + +class InlineCompletionItem(BaseModel): + """The inline completion suggestion to be displayed on the frontend. + + See JuptyerLab `InlineCompletionItem` documentation for the details. + """ + + insertText: str + filterText: Optional[str] + isIncomplete: Optional[bool] + token: Optional[str] + + +class CompletionError(BaseModel): + type: str + traceback: str + + +class InlineCompletionList(BaseModel): + """Reflection of JupyterLab's `IInlineCompletionList`.""" + + items: List[InlineCompletionItem] + + +class InlineCompletionReply(BaseModel): + """Message sent from model to client with the infill suggestions""" + + list: InlineCompletionList + # number of request for which we are replying + reply_to: int + error: Optional[CompletionError] + + +class InlineCompletionStreamChunk(BaseModel): + """Message sent from model to client with the infill suggestions""" + + type: Literal["stream"] = "stream" + response: InlineCompletionItem + reply_to: int + done: bool + error: Optional[CompletionError] + + +class ModelChangedNotification(BaseModel): + type: Literal["model_changed"] = "model_changed" + model: Optional[str] diff --git a/packages/jupyter-ai/jupyter_ai/extension.py b/packages/jupyter-ai/jupyter_ai/extension.py index a41c556c7..8ce680b7c 100644 --- a/packages/jupyter-ai/jupyter_ai/extension.py +++ b/packages/jupyter-ai/jupyter_ai/extension.py @@ -18,12 +18,14 @@ LearnChatHandler, ) from .chat_handlers.help import HelpMessage +from .completions.handlers import DefaultInlineCompletionHandler from .config_manager import ConfigManager from .handlers import ( ApiKeysHandler, ChatHistoryHandler, EmbeddingsModelProviderHandler, GlobalConfigHandler, + InlineCompletionHandler, ModelProviderHandler, RootChatHandler, ) @@ -38,6 +40,7 @@ class AiExtension(ExtensionApp): (r"api/ai/chats/history?", ChatHistoryHandler), (r"api/ai/providers?", ModelProviderHandler), (r"api/ai/providers/embeddings?", EmbeddingsModelProviderHandler), + (r"api/ai/completion/inline/?", InlineCompletionHandler), ] allowed_providers = List( @@ -149,6 +152,7 @@ def initialize_settings(self): # Store chat clients in a dictionary self.settings["chat_clients"] = {} self.settings["jai_root_chat_handlers"] = {} + self.settings["jai_inline_completion_sessions"] = {} # list of chat messages to broadcast to new clients # this is only used to render the UI, and is not the conversational @@ -169,17 +173,21 @@ def initialize_settings(self): dask_client_future = loop.create_task(self._get_dask_client()) eps = entry_points() - # initialize chat handlers - chat_handler_eps = eps.select(group="jupyter_ai.chat_handlers") - chat_handler_kwargs = { + common_handler_kargs = { "log": self.log, "config_manager": self.settings["jai_config_manager"], + "model_parameters": self.settings["model_parameters"], + } + + # initialize chat handlers + chat_handler_eps = eps.select(group="jupyter_ai.chat_handlers") + chat_handler_kwargs = { + **common_handler_kargs, "root_chat_handlers": self.settings["jai_root_chat_handlers"], "chat_history": self.settings["chat_history"], "root_dir": self.serverapp.root_dir, "dask_client_future": dask_client_future, - "model_parameters": self.settings["model_parameters"], } default_chat_handler = DefaultChatHandler(**chat_handler_kwargs) clear_chat_handler = ClearChatHandler(**chat_handler_kwargs) @@ -258,6 +266,13 @@ def initialize_settings(self): ) self.settings["jai_chat_handlers"] = jai_chat_handlers + # initialize completion handlers + default_completion_handler = DefaultInlineCompletionHandler( + **common_handler_kargs, + ws_sessions=self.settings["jai_inline_completion_sessions"], + ) + self.settings["jai_inline_completion_handler"] = default_completion_handler + latency_ms = round((time.time() - start) * 1000) self.log.info(f"Initialized Jupyter AI server extension in {latency_ms} ms.") diff --git a/packages/jupyter-ai/jupyter_ai/handlers.py b/packages/jupyter-ai/jupyter_ai/handlers.py index 230b308d5..bb322ce03 100644 --- a/packages/jupyter-ai/jupyter_ai/handlers.py +++ b/packages/jupyter-ai/jupyter_ai/handlers.py @@ -15,6 +15,7 @@ from tornado import web, websocket from tornado.web import HTTPError +from .completions.models import InlineCompletionRequest from .models import ( AgentChatMessage, ChatClient, @@ -244,6 +245,99 @@ def on_close(self): self.log.debug("Chat clients: %s", self.root_chat_handlers.keys()) +class InlineCompletionHandler(JupyterHandler, websocket.WebSocketHandler): + """Receives completion requests and dispatches them to the model supporting infill.""" + + @property + def websocket_sessions(self) -> Dict[str, "InlineCompletionHandler"]: + """Mapping sessions IDs to their corresponding InlineCompletionHandler instances.""" + return self.settings["jai_inline_completion_sessions"] + + @property + def loop(self) -> AbstractEventLoop: + return self.settings["jai_event_loop"] + + def initialize(self): + self.log.debug("Initializing websocket connection %s", self.request.path) + + def pre_get(self): + """Handles authentication/authorization.""" + # authenticate the request before opening the websocket + user = self.current_user + if user is None: + self.log.warning("Couldn't authenticate WebSocket connection") + raise web.HTTPError(403) + + # authorize the user. + if not self.authorizer.is_authorized(self, user, "execute", "events"): + raise web.HTTPError(403) + + async def get(self, *args, **kwargs): + """Get an event socket.""" + self.pre_get() + res = super().get(*args, **kwargs) + await res + + def generate_client_id(self): + """Generates a client ID to identify the current WS connection.""" + return uuid.uuid4().hex + + def open(self): + """Handles opening of a WebSocket connection.""" + client_id = self.generate_client_id() + + self.websocket_sessions[client_id] = self + self.client_id = client_id + self.write_message(ConnectionMessage(client_id=client_id).dict()) + + self.log.info(f"Inline completion connected. ID: {client_id}") + self.log.debug( + f"Inline completion sessions are: {self.websocket_sessions.keys()}" + ) + + async def on_message(self, message): + self.log.debug("Message received: %s", message) + + try: + message = json.loads(message) + request = InlineCompletionRequest(**message) + except ValidationError as e: + self.log.error(e) + return + + if request.stream: + try: + stream_coroutine = self._stream(request) + except NotImplementedError: + self.log.info( + "Not streaming as handler does not implement stream() method" + ) + await self._complete(request) + self.loop.create_task(stream_coroutine) + else: + self.loop.create_task(self._complete(request)) + + async def _complete(self, request: InlineCompletionRequest): + start = time.time() + reply = await self.settings["jai_inline_completion_handler"].on_message(request) + latency_ms = round((time.time() - start) * 1000) + self.log.info(f"Inline completion handler resolved in {latency_ms} ms.") + self.write_message(reply.dict()) + + async def _stream(self, request: InlineCompletionRequest): + start = time.time() + handler = self.settings["jai_inline_completion_handler"] + async for chunk in handler.stream(request): + self.write_message(chunk.dict()) + latency_ms = round((time.time() - start) * 1000) + self.log.info(f"Inline completion streaming completed in {latency_ms} ms.") + + def on_close(self): + self.log.debug(f"Disconnecting client {self.client_id}") + self.websocket_sessions.pop(self.client_id, None) + self.log.info(f"Completer session disconnected. ID: {self.client_id}") + + class ProviderHandler(BaseAPIHandler): """ Helper base class used for HTTP handlers hosting endpoints relating to diff --git a/packages/jupyter-ai/package.json b/packages/jupyter-ai/package.json index 2e8348983..a2ed693ce 100644 --- a/packages/jupyter-ai/package.json +++ b/packages/jupyter-ai/package.json @@ -65,6 +65,7 @@ "@jupyterlab/cells": "^4", "@jupyterlab/codeeditor": "^4", "@jupyterlab/codemirror": "^4", + "@jupyterlab/completer": "^4.1.0-alpha.3", "@jupyterlab/coreutils": "^6", "@jupyterlab/fileeditor": "^4", "@jupyterlab/notebook": "^4", diff --git a/packages/jupyter-ai/src/completions/handler.ts b/packages/jupyter-ai/src/completions/handler.ts new file mode 100644 index 000000000..9517a0d29 --- /dev/null +++ b/packages/jupyter-ai/src/completions/handler.ts @@ -0,0 +1,161 @@ +import { IDisposable } from '@lumino/disposable'; +import { PromiseDelegate } from '@lumino/coreutils'; +import { ServerConnection } from '@jupyterlab/services'; +import { URLExt } from '@jupyterlab/coreutils'; +import { AiCompleterService as AiService } from './types'; +import { Signal, ISignal } from '@lumino/signaling'; + +const SERVICE_URL = 'api/ai/completion/inline'; + +type StreamChunk = AiService.InlineCompletionStreamChunk; + +export class CompletionWebsocketHandler implements IDisposable { + /** + * The server settings used to make API requests. + */ + readonly serverSettings: ServerConnection.ISettings; + + /** + * Create a new completion handler. + */ + constructor(options: AiService.IOptions = {}) { + this.serverSettings = + options.serverSettings ?? ServerConnection.makeSettings(); + } + + /** + * Initializes the WebSocket connection to the completion backend. Promise is + * resolved when server acknowledges connection and sends the client ID. This + * must be awaited before calling any other method. + */ + public async initialize(): Promise { + await this._initialize(); + } + + /** + * Sends a message across the WebSocket. Promise resolves to the message ID + * when the server sends the same message back, acknowledging receipt. + */ + public sendMessage( + message: AiService.InlineCompletionRequest + ): Promise { + return new Promise(resolve => { + this._socket?.send(JSON.stringify(message)); + this._replyForResolver[message.number] = resolve; + }); + } + + /** + * Signal emitted when completion AI model changes. + */ + get modelChanged(): ISignal { + return this._modelChanged; + } + + /** + * Signal emitted when a new chunk of completion is streamed. + */ + get streamed(): ISignal { + return this._streamed; + } + + /** + * Whether the completion handler is disposed. + */ + get isDisposed(): boolean { + return this._isDisposed; + } + + /** + * Dispose the completion handler. + */ + dispose(): void { + if (this.isDisposed) { + return; + } + this._isDisposed = true; + + // Clean up socket. + const socket = this._socket; + if (socket) { + this._socket = null; + socket.onopen = () => undefined; + socket.onerror = () => undefined; + socket.onmessage = () => undefined; + socket.onclose = () => undefined; + socket.close(); + } + } + + private _onMessage(message: AiService.CompleterMessage): void { + switch (message.type) { + case 'model_changed': { + this._modelChanged.emit(message.model); + break; + } + case 'connection': { + this._initialized.resolve(); + break; + } + case 'stream': { + this._streamed.emit(message); + break; + } + default: { + if (message.reply_to in this._replyForResolver) { + this._replyForResolver[message.reply_to](message); + delete this._replyForResolver[message.reply_to]; + } else { + console.warn('Unhandled message', message); + } + break; + } + } + } + + /** + * Dictionary mapping message IDs to Promise resolvers. + */ + private _replyForResolver: Record< + number, + (value: AiService.InlineCompletionReply) => void + > = {}; + + private _onClose(e: CloseEvent, reject: any) { + reject(new Error('Inline completion websocket disconnected')); + console.error('Inline completion websocket disconnected'); + // only attempt re-connect if there was an abnormal closure + // WebSocket status codes defined in RFC 6455: https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1 + if (e.code === 1006) { + const delaySeconds = 1; + console.info(`Will try to reconnect in ${delaySeconds} s.`); + setTimeout(async () => await this._initialize(), delaySeconds * 1000); + } + } + + private async _initialize(): Promise { + if (this.isDisposed) { + return; + } + const promise = new PromiseDelegate(); + this._initialized = promise; + console.log( + 'Creating a new websocket connection for inline completions...' + ); + const { token, WebSocket, wsUrl } = this.serverSettings; + const url = + URLExt.join(wsUrl, SERVICE_URL) + + (token ? `?token=${encodeURIComponent(token)}` : ''); + + const socket = (this._socket = new WebSocket(url)); + socket.onclose = e => this._onClose(e, promise.reject); + socket.onerror = e => promise.reject(e); + socket.onmessage = msg => msg.data && this._onMessage(JSON.parse(msg.data)); + } + + private _isDisposed = false; + private _socket: WebSocket | null = null; + private _modelChanged = new Signal(this); + private _streamed = new Signal(this); + private _initialized: PromiseDelegate = new PromiseDelegate(); +} diff --git a/packages/jupyter-ai/src/completions/index.ts b/packages/jupyter-ai/src/completions/index.ts new file mode 100644 index 000000000..598272900 --- /dev/null +++ b/packages/jupyter-ai/src/completions/index.ts @@ -0,0 +1 @@ +export { inlineCompletionProvider } from './plugin'; diff --git a/packages/jupyter-ai/src/completions/plugin.ts b/packages/jupyter-ai/src/completions/plugin.ts new file mode 100644 index 000000000..5826426e9 --- /dev/null +++ b/packages/jupyter-ai/src/completions/plugin.ts @@ -0,0 +1,149 @@ +import { + JupyterFrontEnd, + JupyterFrontEndPlugin +} from '@jupyterlab/application'; +import { ICompletionProviderManager } from '@jupyterlab/completer'; +import { ISettingRegistry } from '@jupyterlab/settingregistry'; +import { + IEditorLanguageRegistry, + IEditorLanguage +} from '@jupyterlab/codemirror'; +import { getEditor } from '../selection-watcher'; +import { IJupyternautStatus } from '../tokens'; +import { displayName, JupyterAIInlineProvider } from './provider'; +import { CompletionWebsocketHandler } from './handler'; + +export namespace CommandIDs { + /** + * Command to toggle completions globally. + */ + export const toggleCompletions = 'jupyter-ai:toggle-completions'; + /** + * Command to toggle completions for specific language. + */ + export const toggleLanguageCompletions = + 'jupyter-ai:toggle-language-completions'; +} + +const INLINE_COMPLETER_PLUGIN = + '@jupyterlab/completer-extension:inline-completer'; + +export const inlineCompletionProvider: JupyterFrontEndPlugin = { + id: 'jupyter_ai:inline-completions', + autoStart: true, + requires: [ + ICompletionProviderManager, + IEditorLanguageRegistry, + ISettingRegistry + ], + optional: [IJupyternautStatus], + activate: async ( + app: JupyterFrontEnd, + manager: ICompletionProviderManager, + languageRegistry: IEditorLanguageRegistry, + settingRegistry: ISettingRegistry, + statusMenu: IJupyternautStatus | null + ): Promise => { + if (typeof manager.registerInlineProvider === 'undefined') { + // Gracefully short-circuit on JupyterLab 4.0 and Notebook 7.0 + console.warn( + 'Inline completions are only supported in JupyterLab 4.1+ and Jupyter Notebook 7.1+' + ); + return; + } + const completionHandler = new CompletionWebsocketHandler(); + const provider = new JupyterAIInlineProvider({ + completionHandler, + languageRegistry + }); + await completionHandler.initialize(); + manager.registerInlineProvider(provider); + + const findCurrentLanguage = (): IEditorLanguage | null => { + const widget = app.shell.currentWidget; + const editor = getEditor(widget); + if (!editor) { + return null; + } + return languageRegistry.findByMIME(editor.model.mimeType); + }; + + let settings: ISettingRegistry.ISettings | null = null; + + settingRegistry.pluginChanged.connect(async (_emitter, plugin) => { + if (plugin === INLINE_COMPLETER_PLUGIN) { + // Only load the settings once the plugin settings were transformed + settings = await settingRegistry.load(INLINE_COMPLETER_PLUGIN); + } + }); + + app.commands.addCommand(CommandIDs.toggleCompletions, { + execute: () => { + if (!settings) { + return; + } + const providers = Object.assign({}, settings.user.providers) as any; + const ourSettings = { + ...JupyterAIInlineProvider.DEFAULT_SETTINGS, + ...providers[provider.identifier] + }; + const wasEnabled = ourSettings['enabled']; + providers[provider.identifier]['enabled'] = !wasEnabled; + settings.set('providers', providers); + }, + label: 'Enable Jupyternaut Completions', + isToggled: () => { + return provider.isEnabled(); + } + }); + + app.commands.addCommand(CommandIDs.toggleLanguageCompletions, { + execute: () => { + const language = findCurrentLanguage(); + if (!settings || !language) { + return; + } + const providers = Object.assign({}, settings.user.providers) as any; + const ourSettings = { + ...JupyterAIInlineProvider.DEFAULT_SETTINGS, + ...providers[provider.identifier] + }; + const wasDisabled = ourSettings['disabledLanguages'].includes( + language.name + ); + const disabledList: string[] = + providers[provider.identifier]['disabledLanguages']; + if (wasDisabled) { + disabledList.filter(name => name !== language.name); + } else { + disabledList.push(language.name); + } + settings.set('providers', providers); + }, + label: () => { + const language = findCurrentLanguage(); + return language + ? `Enable Completions in ${displayName(language)}` + : 'Enable Completions for Language of Current Editor'; + }, + isToggled: () => { + const language = findCurrentLanguage(); + return !!language && provider.isLanguageEnabled(language.name); + }, + isEnabled: () => { + return !!findCurrentLanguage() && provider.isEnabled(); + } + }); + + if (statusMenu) { + statusMenu.addItem({ + command: CommandIDs.toggleCompletions, + rank: 1 + }); + statusMenu.addItem({ + command: CommandIDs.toggleLanguageCompletions, + rank: 2 + }); + } + } +}; diff --git a/packages/jupyter-ai/src/completions/provider.ts b/packages/jupyter-ai/src/completions/provider.ts new file mode 100644 index 000000000..12d3031e0 --- /dev/null +++ b/packages/jupyter-ai/src/completions/provider.ts @@ -0,0 +1,431 @@ +import { + JupyterFrontEnd, + JupyterFrontEndPlugin +} from '@jupyterlab/application'; +import { + ICompletionProviderManager, + InlineCompletionTriggerKind, + IInlineCompletionProvider, + IInlineCompletionContext, + IInlineCompletionList, + IInlineCompletionItem, + CompletionHandler +} from '@jupyterlab/completer'; +import { ISettingRegistry } from '@jupyterlab/settingregistry'; +import { Notification, showErrorMessage } from '@jupyterlab/apputils'; +import { JSONValue, PromiseDelegate } from '@lumino/coreutils'; +import { + IEditorLanguageRegistry, + IEditorLanguage +} from '@jupyterlab/codemirror'; +import { NotebookPanel } from '@jupyterlab/notebook'; +import { AiCompleterService as AiService } from './types'; +import { DocumentWidget } from '@jupyterlab/docregistry'; +import { jupyternautIcon } from '../icons'; +import { getEditor } from '../selection-watcher'; +import { IJupyternautStatus } from '../tokens'; +import { CompletionWebsocketHandler } from './handler'; + +type StreamChunk = AiService.InlineCompletionStreamChunk; + +/** + * Format the language name nicely. + */ +export function displayName(language: IEditorLanguage): string { + if (language.name === 'ipythongfm') { + return 'Markdown (IPython)'; + } + if (language.name === 'ipython') { + return 'IPython'; + } + return language.displayName ?? language.name; +} + +export class JupyterAIInlineProvider implements IInlineCompletionProvider { + readonly identifier = 'jupyter-ai'; + readonly icon = jupyternautIcon.bindprops({ width: 16, top: 1 }); + + constructor(protected options: JupyterAIInlineProvider.IOptions) { + options.completionHandler.modelChanged.connect( + (_emitter, model: string) => { + this._currentModel = model; + } + ); + options.completionHandler.streamed.connect(this._receiveStreamChunk, this); + } + + get name(): string { + if (this._currentModel.length > 0) { + return `JupyterAI (${this._currentModel})`; + } else { + // This one is displayed in the settings. + return 'JupyterAI'; + } + } + + async fetch( + request: CompletionHandler.IRequest, + context: IInlineCompletionContext + ): Promise> { + const mime = request.mimeType ?? 'text/plain'; + const language = this.options.languageRegistry.findByMIME(mime); + if (!language) { + console.warn( + `Could not recognise language for ${mime} - cannot complete` + ); + return { items: [] }; + } + if (!this.isLanguageEnabled(language?.name)) { + // Do not offer suggestions if disabled. + return { items: [] }; + } + let cellId = undefined; + let path = context.session?.path; + if (context.widget instanceof NotebookPanel) { + const activeCell = context.widget.content.activeCell; + if (activeCell) { + cellId = activeCell.model.id; + } + } + if (!path && context.widget instanceof DocumentWidget) { + path = context.widget.context.path; + } + const number = ++this._counter; + + const streamPreference = this._settings.streaming; + const stream = + streamPreference === 'always' + ? true + : streamPreference === 'never' + ? false + : context.triggerKind === InlineCompletionTriggerKind.Invoke; + + if (stream) { + // Reset stream promises handler + this._streamPromises.clear(); + } + const result = await this.options.completionHandler.sendMessage({ + path: context.session?.path, + mime, + prefix: this._prefixFromRequest(request), + suffix: this._suffixFromRequest(request), + language: this._resolveLanguage(language), + number, + stream, + cell_id: cellId + }); + + const error = result.error; + if (error) { + Notification.emit(`Inline completion failed: ${error.type}`, 'error', { + autoClose: false, + actions: [ + { + label: 'Show Traceback', + callback: () => { + showErrorMessage('Inline completion failed on the server side', { + message: error.traceback + }); + } + } + ] + }); + throw new Error( + `Inline completion failed: ${error.type}\n${error.traceback}` + ); + } + return result.list; + } + + /** + * Stream a reply for completion identified by given `token`. + */ + async *stream(token: string): AsyncGenerator { + let done = false; + while (!done) { + const delegate = new PromiseDelegate(); + this._streamPromises.set(token, delegate); + const promise = delegate.promise; + yield promise; + done = (await promise).done; + } + } + + get schema(): ISettingRegistry.IProperty { + const knownLanguages = this.options.languageRegistry.getLanguages(); + return { + properties: { + maxPrefix: { + title: 'Maximum prefix length', + minimum: 1, + type: 'number', + description: + 'At most how many prefix characters should be provided to the model.' + }, + maxSuffix: { + title: 'Maximum suffix length', + minimum: 0, + type: 'number', + description: + 'At most how many suffix characters should be provided to the model.' + }, + disabledLanguages: { + title: 'Disabled languages', + type: 'array', + items: { + type: 'string', + oneOf: knownLanguages.map(language => { + return { const: language.name, title: displayName(language) }; + }) + }, + description: + 'Languages for which the completions should not be shown.' + }, + streaming: { + title: 'Streaming', + type: 'string', + oneOf: [ + { const: 'always', title: 'Always' }, + { const: 'manual', title: 'When invoked manually' }, + { const: 'never', title: 'Never' } + ], + description: 'Whether to show suggestions as they are generated' + } + }, + default: JupyterAIInlineProvider.DEFAULT_SETTINGS as any + }; + } + + async configure(settings: { [property: string]: JSONValue }): Promise { + this._settings = settings as unknown as JupyterAIInlineProvider.ISettings; + } + + isEnabled(): boolean { + return this._settings.enabled; + } + + isLanguageEnabled(language: string): boolean { + return !this._settings.disabledLanguages.includes(language); + } + + /** + * Process the stream chunk to make it available in the awaiting generator. + */ + private _receiveStreamChunk( + _emitter: CompletionWebsocketHandler, + chunk: StreamChunk + ) { + const token = chunk.response.token; + if (!token) { + throw Error('Stream chunks must return define `token` in `response`'); + } + const delegate = this._streamPromises.get(token); + if (!delegate) { + console.warn('Unhandled stream chunk'); + } else { + delegate.resolve(chunk); + if (chunk.done) { + this._streamPromises.delete(token); + } + } + } + + /** + * Extract prefix from request, accounting for context window limit. + */ + private _prefixFromRequest(request: CompletionHandler.IRequest): string { + const textBefore = request.text.slice(0, request.offset); + const prefix = textBefore.slice( + -Math.min(this._settings.maxPrefix, textBefore.length) + ); + return prefix; + } + + /** + * Extract suffix from request, accounting for context window limit. + */ + private _suffixFromRequest(request: CompletionHandler.IRequest): string { + const textAfter = request.text.slice(request.offset); + const prefix = textAfter.slice( + 0, + Math.min(this._settings.maxPrefix, textAfter.length) + ); + return prefix; + } + + private _resolveLanguage(language: IEditorLanguage | null) { + if (!language) { + return 'plain English'; + } + if (language.name === 'ipython') { + return 'python'; + } else if (language.name === 'ipythongfm') { + return 'markdown'; + } + return language.name; + } + + private _settings: JupyterAIInlineProvider.ISettings = + JupyterAIInlineProvider.DEFAULT_SETTINGS; + + private _streamPromises: Map> = + new Map(); + private _currentModel = ''; + private _counter = 0; +} + +export namespace JupyterAIInlineProvider { + export interface IOptions { + completionHandler: CompletionWebsocketHandler; + languageRegistry: IEditorLanguageRegistry; + } + export interface ISettings { + maxPrefix: number; + maxSuffix: number; + debouncerDelay: number; + enabled: boolean; + disabledLanguages: string[]; + streaming: 'always' | 'manual' | 'never'; + } + export const DEFAULT_SETTINGS: ISettings = { + maxPrefix: 10000, + maxSuffix: 10000, + // The debouncer delay handling is implemented upstream in JupyterLab; + // here we just increase the default from 0, as compared to kernel history + // the external AI models may have a token cost associated. + debouncerDelay: 250, + enabled: true, + // ipythongfm means "IPython GitHub Flavoured Markdown" + disabledLanguages: ['ipythongfm'], + streaming: 'manual' + }; +} + +export namespace CommandIDs { + export const toggleCompletions = 'jupyter-ai:toggle-completions'; + export const toggleLanguageCompletions = + 'jupyter-ai:toggle-language-completions'; +} + +const INLINE_COMPLETER_PLUGIN = + '@jupyterlab/completer-extension:inline-completer'; + +export const inlineCompletionProvider: JupyterFrontEndPlugin = { + id: 'jupyter_ai:inline-completions', + autoStart: true, + requires: [ + ICompletionProviderManager, + IEditorLanguageRegistry, + ISettingRegistry + ], + optional: [IJupyternautStatus], + activate: async ( + app: JupyterFrontEnd, + manager: ICompletionProviderManager, + languageRegistry: IEditorLanguageRegistry, + settingRegistry: ISettingRegistry, + statusMenu: IJupyternautStatus | null + ): Promise => { + if (typeof manager.registerInlineProvider === 'undefined') { + // Gracefully short-circuit on JupyterLab 4.0 and Notebook 7.0 + console.warn( + 'Inline completions are only supported in JupyterLab 4.1+ and Jupyter Notebook 7.1+' + ); + return; + } + const completionHandler = new CompletionWebsocketHandler(); + const provider = new JupyterAIInlineProvider({ + completionHandler, + languageRegistry + }); + await completionHandler.initialize(); + manager.registerInlineProvider(provider); + + const findCurrentLanguage = (): IEditorLanguage | null => { + const widget = app.shell.currentWidget; + const editor = getEditor(widget); + if (!editor) { + return null; + } + return languageRegistry.findByMIME(editor.model.mimeType); + }; + + let settings: ISettingRegistry.ISettings | null = null; + + settingRegistry.pluginChanged.connect(async (_emitter, plugin) => { + if (plugin === INLINE_COMPLETER_PLUGIN) { + // Only load the settings once the plugin settings were transformed + settings = await settingRegistry.load(INLINE_COMPLETER_PLUGIN); + } + }); + + app.commands.addCommand(CommandIDs.toggleCompletions, { + execute: () => { + if (!settings) { + return; + } + const providers = Object.assign({}, settings.user.providers) as any; + const ourSettings = { + ...JupyterAIInlineProvider.DEFAULT_SETTINGS, + ...providers[provider.identifier] + }; + const wasEnabled = ourSettings['enabled']; + providers[provider.identifier]['enabled'] = !wasEnabled; + settings.set('providers', providers); + }, + label: 'Enable Jupyternaut Completions', + isToggled: () => { + return provider.isEnabled(); + } + }); + + app.commands.addCommand(CommandIDs.toggleLanguageCompletions, { + execute: () => { + const language = findCurrentLanguage(); + if (!settings || !language) { + return; + } + const providers = Object.assign({}, settings.user.providers) as any; + const ourSettings = { + ...JupyterAIInlineProvider.DEFAULT_SETTINGS, + ...providers[provider.identifier] + }; + const wasDisabled = ourSettings['disabledLanguages'].includes( + language.name + ); + const disabledList: string[] = + providers[provider.identifier]['disabledLanguages']; + if (wasDisabled) { + disabledList.filter(name => name !== language.name); + } else { + disabledList.push(language.name); + } + settings.set('providers', providers); + }, + label: () => { + const language = findCurrentLanguage(); + return language + ? `Enable Completions in ${displayName(language)}` + : 'Enable Completions for Language of Current Editor'; + }, + isToggled: () => { + const language = findCurrentLanguage(); + return !!language && provider.isLanguageEnabled(language.name); + }, + isEnabled: () => { + return !!findCurrentLanguage() && provider.isEnabled(); + } + }); + + if (statusMenu) { + statusMenu.addItem({ + command: CommandIDs.toggleCompletions, + rank: 1 + }); + statusMenu.addItem({ + command: CommandIDs.toggleLanguageCompletions, + rank: 2 + }); + } + } +}; diff --git a/packages/jupyter-ai/src/completions/types.ts b/packages/jupyter-ai/src/completions/types.ts new file mode 100644 index 000000000..477c6d74b --- /dev/null +++ b/packages/jupyter-ai/src/completions/types.ts @@ -0,0 +1,67 @@ +import type { + IInlineCompletionList, + IInlineCompletionItem +} from '@jupyterlab/completer'; + +import { ServerConnection } from '@jupyterlab/services'; + +export namespace AiCompleterService { + /** + * The instantiation options for a data registry handler. + */ + export interface IOptions { + serverSettings?: ServerConnection.ISettings; + } + + export type ConnectionMessage = { + type: 'connection'; + client_id: string; + }; + + export type InlineCompletionRequest = { + number: number; + path?: string; + /* The model has to complete given prefix */ + prefix: string; + /* The model may consider the following suffix */ + suffix: string; + mime: string; + /* Whether to stream the response (if streaming is supported by the model) */ + stream: boolean; + language?: string; + cell_id?: string; + }; + + export type CompletionError = { + type: string; + traceback: string; + }; + + export type InlineCompletionReply = { + /** + * Type for this message can be skipped (`inline_completion` is presumed default). + **/ + type?: 'inline_completion'; + list: IInlineCompletionList; + reply_to: number; + error?: CompletionError; + }; + + export type InlineCompletionStreamChunk = { + type: 'stream'; + response: IInlineCompletionItem; + reply_to: number; + done: boolean; + }; + + export type InlineCompletionModelChanged = { + type: 'model_changed'; + model: string; + }; + + export type CompleterMessage = + | InlineCompletionReply + | ConnectionMessage + | InlineCompletionStreamChunk + | InlineCompletionModelChanged; +} diff --git a/packages/jupyter-ai/src/components/chat-settings.tsx b/packages/jupyter-ai/src/components/chat-settings.tsx index 583cfa9f0..9f048d827 100644 --- a/packages/jupyter-ai/src/components/chat-settings.tsx +++ b/packages/jupyter-ai/src/components/chat-settings.tsx @@ -102,12 +102,27 @@ export function ChatSettings(): JSX.Element { ) { newApiKeys[lmAuth.name] = ''; } + if (lmAuth?.type === 'multienv') { + lmAuth.names.forEach(apiKey => { + if (!server.config.api_keys.includes(apiKey)) { + newApiKeys[apiKey] = ''; + } + }); + } + if ( emAuth?.type === 'env' && !server.config.api_keys.includes(emAuth.name) ) { newApiKeys[emAuth.name] = ''; } + if (emAuth?.type === 'multienv') { + emAuth.names.forEach(apiKey => { + if (!server.config.api_keys.includes(apiKey)) { + newApiKeys[apiKey] = ''; + } + }); + } setApiKeys(newApiKeys); }, [lmProvider, emProvider, server]); diff --git a/packages/jupyter-ai/src/components/statusbar-item.tsx b/packages/jupyter-ai/src/components/statusbar-item.tsx new file mode 100644 index 000000000..f3b1f0388 --- /dev/null +++ b/packages/jupyter-ai/src/components/statusbar-item.tsx @@ -0,0 +1,92 @@ +import { Popup, showPopup } from '@jupyterlab/statusbar'; +import React from 'react'; +import { VDomModel, VDomRenderer } from '@jupyterlab/ui-components'; +import { CommandRegistry } from '@lumino/commands'; +import { MenuSvg, RankedMenu, IRankedMenu } from '@jupyterlab/ui-components'; +import { Jupyternaut } from '../icons'; +import { IJupyternautStatus } from '../tokens'; + +/** + * StatusBar item to display menu for toggling the completion. + */ +export class JupyternautStatus + extends VDomRenderer + implements IJupyternautStatus +{ + constructor(options: JupyternautStatus.IOptions) { + super(new VDomModel()); + this._commandRegistry = options.commandRegistry; + this._items = []; + + this.addClass('jp-mod-highlighted'); + this.title.caption = 'Open Jupyternaut status menu'; + this.node.addEventListener('click', this._handleClick); + } + + addItem(item: IRankedMenu.IItemOptions): void { + this._items.push(item); + } + + hasItems(): boolean { + return this._items.length !== 0; + } + + /** + * Render the status item. + */ + render(): JSX.Element | null { + if (!this.model) { + return null; + } + return ; + } + + dispose(): void { + this.node.removeEventListener('click', this._handleClick); + super.dispose(); + } + + /** + * Create a menu for viewing status and changing options. + */ + private _handleClick = () => { + if (this._popup) { + this._popup.dispose(); + } + if (this._menu) { + this._menu.dispose(); + } + this._menu = new RankedMenu({ + commands: this._commandRegistry, + renderer: MenuSvg.defaultRenderer + }); + for (const item of this._items) { + this._menu.addItem(item); + } + this._popup = showPopup({ + body: this._menu, + anchor: this, + align: 'left' + }); + }; + + private _items: IRankedMenu.IItemOptions[]; + private _commandRegistry: CommandRegistry; + private _menu: RankedMenu | null = null; + private _popup: Popup | null = null; +} + +/** + * A namespace for JupyternautStatus statics. + */ +export namespace JupyternautStatus { + /** + * Options for the JupyternautStatus item. + */ + export interface IOptions { + /** + * The application command registry. + */ + commandRegistry: CommandRegistry; + } +} diff --git a/packages/jupyter-ai/src/handler.ts b/packages/jupyter-ai/src/handler.ts index ec91c1f3f..809213b1f 100644 --- a/packages/jupyter-ai/src/handler.ts +++ b/packages/jupyter-ai/src/handler.ts @@ -135,7 +135,16 @@ export namespace AiService { type: 'aws'; }; - export type AuthStrategy = EnvAuthStrategy | AwsAuthStrategy | null; + export type MultiEnvAuthStrategy = { + type: 'multienv'; + names: string[]; + }; + + export type AuthStrategy = + | AwsAuthStrategy + | EnvAuthStrategy + | MultiEnvAuthStrategy + | null; export type TextField = { type: 'text'; diff --git a/packages/jupyter-ai/src/index.ts b/packages/jupyter-ai/src/index.ts index e48e2b211..03f8e2eb9 100644 --- a/packages/jupyter-ai/src/index.ts +++ b/packages/jupyter-ai/src/index.ts @@ -12,6 +12,8 @@ import { buildChatSidebar } from './widgets/chat-sidebar'; import { SelectionWatcher } from './selection-watcher'; import { ChatHandler } from './chat_handler'; import { buildErrorWidget } from './widgets/chat-error'; +import { inlineCompletionProvider } from './completions'; +import { jupyternautStatus } from './status'; export type DocumentTracker = IWidgetTracker; @@ -60,4 +62,4 @@ const plugin: JupyterFrontEndPlugin = { } }; -export default plugin; +export default [plugin, jupyternautStatus, inlineCompletionProvider]; diff --git a/packages/jupyter-ai/src/selection-watcher.ts b/packages/jupyter-ai/src/selection-watcher.ts index 825ee0f18..bbe1adefe 100644 --- a/packages/jupyter-ai/src/selection-watcher.ts +++ b/packages/jupyter-ai/src/selection-watcher.ts @@ -14,7 +14,9 @@ import { getCellIndex } from './utils'; /** * Gets the editor instance used by a document widget. Returns `null` if unable. */ -function getEditor(widget: Widget | null) { +export function getEditor( + widget: Widget | null +): CodeMirrorEditor | null | undefined { if (!(widget instanceof DocumentWidget)) { return null; } diff --git a/packages/jupyter-ai/src/status.ts b/packages/jupyter-ai/src/status.ts new file mode 100644 index 000000000..013b305d7 --- /dev/null +++ b/packages/jupyter-ai/src/status.ts @@ -0,0 +1,30 @@ +import { IJupyternautStatus } from './tokens'; +import { + JupyterFrontEnd, + JupyterFrontEndPlugin +} from '@jupyterlab/application'; +import { IStatusBar } from '@jupyterlab/statusbar'; +import { JupyternautStatus } from './components/statusbar-item'; + +export const jupyternautStatus: JupyterFrontEndPlugin = { + id: 'jupyter_ai:jupyternaut-status', + description: 'Adds a status indicator for jupyternaut.', + autoStart: true, + requires: [IStatusBar], + provides: IJupyternautStatus, + activate: (app: JupyterFrontEnd, statusBar: IStatusBar | null) => { + const indicator = new JupyternautStatus({ commandRegistry: app.commands }); + if (statusBar) { + // Add the status item. + statusBar.registerStatusItem('jupyter_ai:jupyternaut-status', { + item: indicator, + align: 'right', + rank: 100, + isActive: () => { + return indicator.hasItems(); + } + }); + } + return indicator; + } +}; diff --git a/packages/jupyter-ai/src/tokens.ts b/packages/jupyter-ai/src/tokens.ts new file mode 100644 index 000000000..353c925e8 --- /dev/null +++ b/packages/jupyter-ai/src/tokens.ts @@ -0,0 +1,14 @@ +import { Token } from '@lumino/coreutils'; +import type { IRankedMenu } from '@jupyterlab/ui-components'; + +export interface IJupyternautStatus { + addItem(item: IRankedMenu.IItemOptions): void; +} + +/** + * The Jupyternaut status token. + */ +export const IJupyternautStatus = new Token( + 'jupyter_ai:IJupyternautStatus', + 'Status indicator displayed in the statusbar' +); diff --git a/packages/jupyter-ai/style/icons/jupyternaut.svg b/packages/jupyter-ai/style/icons/jupyternaut.svg index d4367985d..dd800d538 100644 --- a/packages/jupyter-ai/style/icons/jupyternaut.svg +++ b/packages/jupyter-ai/style/icons/jupyternaut.svg @@ -1,15 +1,9 @@ - - + - - - - - diff --git a/yarn.lock b/yarn.lock index 3cdc4ba8b..30fb5258c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1890,20 +1890,6 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/console@npm:29.6.1" - dependencies: - "@jest/types": ^29.6.1 - "@types/node": "*" - chalk: ^4.0.0 - jest-message-util: ^29.6.1 - jest-util: ^29.6.1 - slash: ^3.0.0 - checksum: d0ab23a00947bfb4bff8c0a7e5a7afd16519de16dde3fe7e77b9f13e794c6df7043ecf7fcdde66ac0d2b5fb3262e9cab3d92eaf61f89a12d3b8e3602e06a9902 - languageName: node - linkType: hard - "@jest/console@npm:^29.6.2": version: 29.6.2 resolution: "@jest/console@npm:29.6.2" @@ -1918,47 +1904,6 @@ __metadata: languageName: node linkType: hard -"@jest/core@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/core@npm:29.6.1" - dependencies: - "@jest/console": ^29.6.1 - "@jest/reporters": ^29.6.1 - "@jest/test-result": ^29.6.1 - "@jest/transform": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/node": "*" - 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.1 - jest-haste-map: ^29.6.1 - jest-message-util: ^29.6.1 - jest-regex-util: ^29.4.3 - jest-resolve: ^29.6.1 - jest-resolve-dependencies: ^29.6.1 - jest-runner: ^29.6.1 - jest-runtime: ^29.6.1 - jest-snapshot: ^29.6.1 - jest-util: ^29.6.1 - jest-validate: ^29.6.1 - jest-watcher: ^29.6.1 - micromatch: ^4.0.4 - pretty-format: ^29.6.1 - 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: 736dcc90c6c58dd9e1d2da122103b851187719ce3b3d4167689c63e68252632cd817712955b52ddaa648eba9c6f98f86cd58677325f0db4185f76899c64d7dac - languageName: node - linkType: hard - "@jest/core@npm:^29.6.2": version: 29.6.2 resolution: "@jest/core@npm:29.6.2" @@ -2000,19 +1945,7 @@ __metadata: languageName: node linkType: hard -"@jest/environment@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/environment@npm:29.6.1" - dependencies: - "@jest/fake-timers": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/node": "*" - jest-mock: ^29.6.1 - checksum: fb671f91f27e7aa1ba04983ef87a83f0794a597aba0a57d08cbb1fcb484c2aedc2201e99f85fafe27aec9be78af6f2d1d7e6ea88267938992a1d0f9d4615f5b2 - languageName: node - linkType: hard - -"@jest/environment@npm:^29.6.2": +"@jest/environment@npm:^29.6.1, @jest/environment@npm:^29.6.2": version: 29.6.2 resolution: "@jest/environment@npm:29.6.2" dependencies: @@ -2024,15 +1957,6 @@ __metadata: languageName: node linkType: hard -"@jest/expect-utils@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/expect-utils@npm:29.6.1" - dependencies: - jest-get-type: ^29.4.3 - checksum: 037ee017eca62f7b45e1465fb5c6f9e92d5709a9ac716b8bff0bd294240a54de734e8f968fb69309cc4aef6c83b9552d5a821f3b18371af394bf04783859d706 - languageName: node - linkType: hard - "@jest/expect-utils@npm:^29.6.2": version: 29.6.2 resolution: "@jest/expect-utils@npm:29.6.2" @@ -2042,16 +1966,6 @@ __metadata: languageName: node linkType: hard -"@jest/expect@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/expect@npm:29.6.1" - dependencies: - expect: ^29.6.1 - jest-snapshot: ^29.6.1 - checksum: 5c56977b3cc8489744d97d9dc2dcb196c1dfecc83a058a7ef0fd4f63d68cf120a23d27669272d1e1b184fb4337b85e4ac1fc7f886e3988fdf243d42d73973eac - languageName: node - linkType: hard - "@jest/expect@npm:^29.6.2": version: 29.6.2 resolution: "@jest/expect@npm:29.6.2" @@ -2062,21 +1976,7 @@ __metadata: languageName: node linkType: hard -"@jest/fake-timers@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/fake-timers@npm:29.6.1" - dependencies: - "@jest/types": ^29.6.1 - "@sinonjs/fake-timers": ^10.0.2 - "@types/node": "*" - jest-message-util: ^29.6.1 - jest-mock: ^29.6.1 - jest-util: ^29.6.1 - checksum: 86991276944b7d6c2ada3703a272517f5f8f2f4e2af1fe26065f6db1dac4dc6299729a88c46bcb781dcc1b20504c1d4bbd8119fd8a0838ac81a9a4b5d2c8e429 - languageName: node - linkType: hard - -"@jest/fake-timers@npm:^29.6.2": +"@jest/fake-timers@npm:^29.6.1, @jest/fake-timers@npm:^29.6.2": version: 29.6.2 resolution: "@jest/fake-timers@npm:29.6.2" dependencies: @@ -2090,18 +1990,6 @@ __metadata: languageName: node linkType: hard -"@jest/globals@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/globals@npm:29.6.1" - dependencies: - "@jest/environment": ^29.6.1 - "@jest/expect": ^29.6.1 - "@jest/types": ^29.6.1 - jest-mock: ^29.6.1 - checksum: fcca0b970a8b4894a1cdff0f500a86b45609e72c0a4319875e9504237b839df1a46c44d2f1362c6d87fdc7a05928edcc4b5a3751c9e6648dd70a761cdab64c94 - languageName: node - linkType: hard - "@jest/globals@npm:^29.6.2": version: 29.6.2 resolution: "@jest/globals@npm:29.6.2" @@ -2114,43 +2002,6 @@ __metadata: 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": ^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.3 - graceful-fs: ^4.2.9 - istanbul-lib-coverage: ^3.0.0 - istanbul-lib-instrument: ^5.1.0 - 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 - slash: ^3.0.0 - string-length: ^4.0.1 - 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: b7dae415f3f6342b4db2671261bbee29af20a829f42135316c3dd548b9ef85290c9bb64a0e3aec4a55486596be1257ac8216a0f8d9794acd43f8b8fb686fc7e3 - languageName: node - linkType: hard - "@jest/reporters@npm:^29.6.2": version: 29.6.2 resolution: "@jest/reporters@npm:29.6.2" @@ -2208,18 +2059,6 @@ __metadata: languageName: node linkType: hard -"@jest/test-result@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/test-result@npm:29.6.1" - dependencies: - "@jest/console": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/istanbul-lib-coverage": ^2.0.0 - collect-v8-coverage: ^1.0.0 - checksum: 9397a3a3410c5df564e79297b1be4fe33807a6157a017a1f74b54a6ef14de1530f12b922299e822e66a82c53269da16661772bffde3d883a78c5eefd2cd6d1cc - languageName: node - linkType: hard - "@jest/test-result@npm:^29.6.2": version: 29.6.2 resolution: "@jest/test-result@npm:29.6.2" @@ -2232,18 +2071,6 @@ __metadata: languageName: node linkType: hard -"@jest/test-sequencer@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/test-sequencer@npm:29.6.1" - dependencies: - "@jest/test-result": ^29.6.1 - graceful-fs: ^4.2.9 - jest-haste-map: ^29.6.1 - slash: ^3.0.0 - checksum: f3437178b5dca0401ed2e990d8b69161442351856d56f5725e009a487f5232b51039f8829673884b9bea61c861120d08a53a36432f4a4b8aab38915a68f7000d - languageName: node - linkType: hard - "@jest/test-sequencer@npm:^29.6.2": version: 29.6.2 resolution: "@jest/test-sequencer@npm:29.6.2" @@ -2256,29 +2083,6 @@ __metadata: languageName: node linkType: hard -"@jest/transform@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/transform@npm:29.6.1" - dependencies: - "@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 - convert-source-map: ^2.0.0 - fast-json-stable-stringify: ^2.1.0 - graceful-fs: ^4.2.9 - jest-haste-map: ^29.6.1 - jest-regex-util: ^29.4.3 - jest-util: ^29.6.1 - micromatch: ^4.0.4 - pirates: ^4.0.4 - slash: ^3.0.0 - write-file-atomic: ^4.0.2 - checksum: 1635cd66e4b3dbba0689ecefabc6137301756c9c12d1d23e25124dd0dd9b4a6a38653d51e825e90f74faa022152ac1eaf200591fb50417aa7e1f7d1d1c2bc11d - languageName: node - linkType: hard - "@jest/transform@npm:^29.6.2": version: 29.6.2 resolution: "@jest/transform@npm:29.6.2" @@ -2351,20 +2155,13 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:1.4.14": +"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10": version: 1.4.14 resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" checksum: 61100637b6d173d3ba786a5dff019e1a74b1f394f323c1fee337ff390239f053b87266c7a948777f4b1ee68c01a8ad0ab61e5ff4abb5a012a0b091bec391ab97 languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 - languageName: node - linkType: hard - "@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.9": version: 0.3.18 resolution: "@jridgewell/trace-mapping@npm:0.3.18" @@ -2389,6 +2186,7 @@ __metadata: "@jupyterlab/cells": ^4 "@jupyterlab/codeeditor": ^4 "@jupyterlab/codemirror": ^4 + "@jupyterlab/completer": ^4.1.0-alpha.3 "@jupyterlab/coreutils": ^6 "@jupyterlab/fileeditor": ^4 "@jupyterlab/notebook": ^4 @@ -2480,9 +2278,9 @@ __metadata: languageName: node linkType: hard -"@jupyter/ydoc@npm:^1.0.2": - version: 1.0.2 - resolution: "@jupyter/ydoc@npm:1.0.2" +"@jupyter/ydoc@npm:^1.0.2, @jupyter/ydoc@npm:^1.1.1": + version: 1.1.1 + resolution: "@jupyter/ydoc@npm:1.1.1" dependencies: "@jupyterlab/nbformat": ^3.0.0 || ^4.0.0-alpha.21 || ^4.0.0 "@lumino/coreutils": ^1.11.0 || ^2.0.0 @@ -2490,7 +2288,7 @@ __metadata: "@lumino/signaling": ^1.10.0 || ^2.0.0 y-protocols: ^1.0.5 yjs: ^13.5.40 - checksum: 739f9630940466b3cfcd7b742dd06479f81772ca13f863d057af0bbb5e318829506969066ab72977e7c721644982b5c8f88cf44e1ae81955ed1c27e87632d1f2 + checksum: a239b1dd57cfc9ba36c06ac5032a1b6388849ae01a1d0db0d45094f71fdadf4d473b4bf8becbef0cfcdc85cae505361fbec0822b02da5aa48e06b66f742dd7a0 languageName: node linkType: hard @@ -2551,6 +2349,35 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/apputils@npm:^4.2.0-alpha.3": + version: 4.2.0-alpha.3 + resolution: "@jupyterlab/apputils@npm:4.2.0-alpha.3" + dependencies: + "@jupyterlab/coreutils": ^6.1.0-alpha.3 + "@jupyterlab/observables": ^5.1.0-alpha.3 + "@jupyterlab/rendermime-interfaces": ^3.9.0-alpha.2 + "@jupyterlab/services": ^7.1.0-alpha.3 + "@jupyterlab/settingregistry": ^4.1.0-alpha.3 + "@jupyterlab/statedb": ^4.1.0-alpha.3 + "@jupyterlab/statusbar": ^4.1.0-alpha.3 + "@jupyterlab/translation": ^4.1.0-alpha.3 + "@jupyterlab/ui-components": ^4.1.0-alpha.3 + "@lumino/algorithm": ^2.0.1 + "@lumino/commands": ^2.1.3 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/domutils": ^2.0.1 + "@lumino/messaging": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/virtualdom": ^2.0.1 + "@lumino/widgets": ^2.3.1-alpha.0 + "@types/react": ^18.0.26 + react: ^18.2.0 + sanitize-html: ~2.7.3 + checksum: 09b9dd0997631614884c33515dd21cb270450490c22fddb247e68049c491ed7bd369a9942e90970d32caaf10bd2da9b806a194d0cfb01a7357ec7af06e2897d4 + languageName: node + linkType: hard + "@jupyterlab/attachments@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/attachments@npm:4.0.3" @@ -2665,6 +2492,29 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/codeeditor@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/codeeditor@npm:4.1.0-alpha.3" + dependencies: + "@codemirror/state": ^6.2.0 + "@jupyter/ydoc": ^1.1.1 + "@jupyterlab/coreutils": ^6.1.0-alpha.3 + "@jupyterlab/nbformat": ^4.1.0-alpha.3 + "@jupyterlab/observables": ^5.1.0-alpha.3 + "@jupyterlab/statusbar": ^4.1.0-alpha.3 + "@jupyterlab/translation": ^4.1.0-alpha.3 + "@jupyterlab/ui-components": ^4.1.0-alpha.3 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/dragdrop": ^2.1.3 + "@lumino/messaging": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/widgets": ^2.3.1-alpha.0 + react: ^18.2.0 + checksum: 67ed499046b8bfdc88e8efde1a273fc5e5172bf1e970a77e8e7c3d0557e9331531c5f37c15f49a4313ac937cdf9b4f550ba2d5475f753e7431c65e43d7d8c94b + languageName: node + linkType: hard + "@jupyterlab/codemirror@npm:^4, @jupyterlab/codemirror@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/codemirror@npm:4.0.3" @@ -2707,6 +2557,76 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/codemirror@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/codemirror@npm:4.1.0-alpha.3" + dependencies: + "@codemirror/autocomplete": ^6.5.1 + "@codemirror/commands": ^6.2.3 + "@codemirror/lang-cpp": ^6.0.2 + "@codemirror/lang-css": ^6.1.1 + "@codemirror/lang-html": ^6.4.3 + "@codemirror/lang-java": ^6.0.1 + "@codemirror/lang-javascript": ^6.1.7 + "@codemirror/lang-json": ^6.0.1 + "@codemirror/lang-markdown": ^6.1.1 + "@codemirror/lang-php": ^6.0.1 + "@codemirror/lang-python": ^6.1.3 + "@codemirror/lang-rust": ^6.0.1 + "@codemirror/lang-sql": ^6.4.1 + "@codemirror/lang-wast": ^6.0.1 + "@codemirror/lang-xml": ^6.0.2 + "@codemirror/language": ^6.6.0 + "@codemirror/legacy-modes": ^6.3.2 + "@codemirror/search": ^6.3.0 + "@codemirror/state": ^6.2.0 + "@codemirror/view": ^6.9.6 + "@jupyter/ydoc": ^1.1.1 + "@jupyterlab/codeeditor": ^4.1.0-alpha.3 + "@jupyterlab/coreutils": ^6.1.0-alpha.3 + "@jupyterlab/documentsearch": ^4.1.0-alpha.3 + "@jupyterlab/nbformat": ^4.1.0-alpha.3 + "@jupyterlab/translation": ^4.1.0-alpha.3 + "@lezer/common": ^1.0.2 + "@lezer/generator": ^1.2.2 + "@lezer/highlight": ^1.1.4 + "@lezer/markdown": ^1.0.2 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/signaling": ^2.1.2 + yjs: ^13.5.40 + checksum: bff2538c77b32d2a29b645f84057da6aa8e8b749c68dd9a01150d15f55851255ca40163f99d21a6608907393156db8ace0bd75faf2681d4d1c2ce6fef6c433a7 + languageName: node + linkType: hard + +"@jupyterlab/completer@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/completer@npm:4.1.0-alpha.3" + dependencies: + "@codemirror/state": ^6.2.0 + "@codemirror/view": ^6.9.6 + "@jupyter/ydoc": ^1.1.1 + "@jupyterlab/apputils": ^4.2.0-alpha.3 + "@jupyterlab/codeeditor": ^4.1.0-alpha.3 + "@jupyterlab/codemirror": ^4.1.0-alpha.3 + "@jupyterlab/coreutils": ^6.1.0-alpha.3 + "@jupyterlab/rendermime": ^4.1.0-alpha.3 + "@jupyterlab/services": ^7.1.0-alpha.3 + "@jupyterlab/settingregistry": ^4.1.0-alpha.3 + "@jupyterlab/statedb": ^4.1.0-alpha.3 + "@jupyterlab/translation": ^4.1.0-alpha.3 + "@jupyterlab/ui-components": ^4.1.0-alpha.3 + "@lumino/algorithm": ^2.0.1 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/domutils": ^2.0.1 + "@lumino/messaging": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/widgets": ^2.3.1-alpha.0 + checksum: 792552354b62b3f5a9d2da2aa3df774b3ac0a90d15dcd55b18950fb0a72566fe1d6be026a64c14b846859c75db8120f211f727161b5e4a373e5028aa17a79408 + languageName: node + linkType: hard + "@jupyterlab/coreutils@npm:^6, @jupyterlab/coreutils@npm:^6.0.0, @jupyterlab/coreutils@npm:^6.0.3": version: 6.0.3 resolution: "@jupyterlab/coreutils@npm:6.0.3" @@ -2721,6 +2641,20 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/coreutils@npm:^6.1.0-alpha.3": + version: 6.1.0-alpha.3 + resolution: "@jupyterlab/coreutils@npm:6.1.0-alpha.3" + dependencies: + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/signaling": ^2.1.2 + minimist: ~1.2.0 + path-browserify: ^1.0.0 + url-parse: ~1.5.4 + checksum: d01acd11f20a9062776e341fbe6b83595aa36837e94067b0376974a4e9e818ca5dbdc36d175a1afc3031cf42f3648ef80e7bebac40fb2de4e883caee7d533960 + languageName: node + linkType: hard + "@jupyterlab/docmanager@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/docmanager@npm:4.0.3" @@ -2787,6 +2721,25 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/documentsearch@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/documentsearch@npm:4.1.0-alpha.3" + dependencies: + "@jupyterlab/apputils": ^4.2.0-alpha.3 + "@jupyterlab/translation": ^4.1.0-alpha.3 + "@jupyterlab/ui-components": ^4.1.0-alpha.3 + "@lumino/commands": ^2.1.3 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/messaging": ^2.0.1 + "@lumino/polling": ^2.1.2 + "@lumino/signaling": ^2.1.2 + "@lumino/widgets": ^2.3.1-alpha.0 + react: ^18.2.0 + checksum: 1fcffec0ea7326c30d191e916aa623b5fb65dccb039bad654ee94a49bd0dee1d86c573e68812932ac99964c70354b1a8b21fff30894ad9f9bf959d4583cf1d1a + languageName: node + linkType: hard + "@jupyterlab/filebrowser@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/filebrowser@npm:4.0.3" @@ -2870,6 +2823,15 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/nbformat@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/nbformat@npm:4.1.0-alpha.3" + dependencies: + "@lumino/coreutils": ^2.1.2 + checksum: d78df36ea04fd7c925db3db1225ccba4f0c7c7f7fcc57cc2ad28293f37a6122e56ac86fd129d20d3d1fb46bbf1ec6e44b7d2b7d36f83ed7c721a2677b4578197 + languageName: node + linkType: hard + "@jupyterlab/notebook@npm:^4, @jupyterlab/notebook@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/notebook@npm:4.0.3" @@ -2919,6 +2881,19 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/observables@npm:^5.1.0-alpha.3": + version: 5.1.0-alpha.3 + resolution: "@jupyterlab/observables@npm:5.1.0-alpha.3" + dependencies: + "@lumino/algorithm": ^2.0.1 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/messaging": ^2.0.1 + "@lumino/signaling": ^2.1.2 + checksum: 00b330415c16dd2aec043e0fd2eef91500196fd1459ec891c9a5c1d0af64fdd87d6cb65a6da99a7d47bf93ad3efcd82de4e24ee661a23120c599ec3319763008 + languageName: node + linkType: hard + "@jupyterlab/outputarea@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/outputarea@npm:4.0.3" @@ -2951,6 +2926,16 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/rendermime-interfaces@npm:^3.9.0-alpha.2": + version: 3.9.0-alpha.2 + resolution: "@jupyterlab/rendermime-interfaces@npm:3.9.0-alpha.2" + dependencies: + "@lumino/coreutils": ^1.11.0 || ^2.1.2 + "@lumino/widgets": ^1.37.2 || ^2.3.1-alpha.0 + checksum: a6b4c2134955304012ea20392be6836f3f1518a4724a701bc979109f8e67b926dd4d493705aa3af22165025d9eb3d0cae60daef901a78a47c7cfdebc5469ae7f + languageName: node + linkType: hard + "@jupyterlab/rendermime@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/rendermime@npm:4.0.3" @@ -2971,6 +2956,26 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/rendermime@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/rendermime@npm:4.1.0-alpha.3" + dependencies: + "@jupyterlab/apputils": ^4.2.0-alpha.3 + "@jupyterlab/coreutils": ^6.1.0-alpha.3 + "@jupyterlab/nbformat": ^4.1.0-alpha.3 + "@jupyterlab/observables": ^5.1.0-alpha.3 + "@jupyterlab/rendermime-interfaces": ^3.9.0-alpha.2 + "@jupyterlab/services": ^7.1.0-alpha.3 + "@jupyterlab/translation": ^4.1.0-alpha.3 + "@lumino/coreutils": ^2.1.2 + "@lumino/messaging": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/widgets": ^2.3.1-alpha.0 + lodash.escape: ^4.0.1 + checksum: 31ba6a5cde710ec740ac8568607e4aeb68bde5a03e0a41fb45929ff9ed80f73d975336eb5be37d5b4cca1dcccdec99c1577a37790af6bfd1297f4b0baef402b5 + languageName: node + linkType: hard + "@jupyterlab/services@npm:^7, @jupyterlab/services@npm:^7.0.0, @jupyterlab/services@npm:^7.0.3": version: 7.0.3 resolution: "@jupyterlab/services@npm:7.0.3" @@ -2990,6 +2995,25 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/services@npm:^7.1.0-alpha.3": + version: 7.1.0-alpha.3 + resolution: "@jupyterlab/services@npm:7.1.0-alpha.3" + dependencies: + "@jupyter/ydoc": ^1.1.1 + "@jupyterlab/coreutils": ^6.1.0-alpha.3 + "@jupyterlab/nbformat": ^4.1.0-alpha.3 + "@jupyterlab/settingregistry": ^4.1.0-alpha.3 + "@jupyterlab/statedb": ^4.1.0-alpha.3 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/polling": ^2.1.2 + "@lumino/properties": ^2.0.1 + "@lumino/signaling": ^2.1.2 + ws: ^8.11.0 + checksum: 4c2c9fefdc3dc821797274b0aba5c9f8fff10f747dfb07c7d2d8e29d149cacfca67f45e5fc305eba924221dfd0d6c3125f4b30945999f80e7cb4b7d126aa2af3 + languageName: node + linkType: hard + "@jupyterlab/settingregistry@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/settingregistry@npm:4.0.3" @@ -3009,6 +3033,25 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/settingregistry@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/settingregistry@npm:4.1.0-alpha.3" + dependencies: + "@jupyterlab/nbformat": ^4.1.0-alpha.3 + "@jupyterlab/statedb": ^4.1.0-alpha.3 + "@lumino/commands": ^2.1.3 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/signaling": ^2.1.2 + "@rjsf/utils": ^5.13.2 + ajv: ^8.12.0 + json5: ^2.2.3 + peerDependencies: + react: ">=16" + checksum: 80f077797c20bde178ebdc82bce8a0673d89798e4d79b39279d7b6489a50ca5eb2d7e6427b373f8a2c159d18d7976ae7058a16a43a14ab71b315f4392a5e0b87 + languageName: node + linkType: hard + "@jupyterlab/statedb@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/statedb@npm:4.0.3" @@ -3022,6 +3065,19 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/statedb@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/statedb@npm:4.1.0-alpha.3" + dependencies: + "@lumino/commands": ^2.1.3 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/properties": ^2.0.1 + "@lumino/signaling": ^2.1.2 + checksum: 15dfac8a3da096c1ab82dfb616234ee09a447717ee1e4cce028e7d6ae1605afbd53e6b73599f302fd59d09d8b04aa2d26a669f0f3cb2dfaa20621336d9f35098 + languageName: node + linkType: hard + "@jupyterlab/statusbar@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/statusbar@npm:4.0.3" @@ -3038,6 +3094,22 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/statusbar@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/statusbar@npm:4.1.0-alpha.3" + dependencies: + "@jupyterlab/ui-components": ^4.1.0-alpha.3 + "@lumino/algorithm": ^2.0.1 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/messaging": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/widgets": ^2.3.1-alpha.0 + react: ^18.2.0 + checksum: 37d6820b51a779fb3576d78d93289594632e25efa623087266ddd7f569cba2b9fa5e874494254bed9c458b30d787869475eafebd155e1f7caa23f13ddfa71f0b + languageName: node + linkType: hard + "@jupyterlab/testing@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/testing@npm:4.0.3" @@ -3110,6 +3182,19 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/translation@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/translation@npm:4.1.0-alpha.3" + dependencies: + "@jupyterlab/coreutils": ^6.1.0-alpha.3 + "@jupyterlab/rendermime-interfaces": ^3.9.0-alpha.2 + "@jupyterlab/services": ^7.1.0-alpha.3 + "@jupyterlab/statedb": ^4.1.0-alpha.3 + "@lumino/coreutils": ^2.1.2 + checksum: 9e7cffa59d71371bba9c4372940dce865279a66a4f48bd8cb5c5552081ee80a3584f40cc0b31b207fc6de0ad5fb5a4dc4fa0b4d58476e1584f8d9daad18def19 + languageName: node + linkType: hard + "@jupyterlab/ui-components@npm:^4, @jupyterlab/ui-components@npm:^4.0.0, @jupyterlab/ui-components@npm:^4.0.3": version: 4.0.3 resolution: "@jupyterlab/ui-components@npm:4.0.3" @@ -3139,6 +3224,35 @@ __metadata: languageName: node linkType: hard +"@jupyterlab/ui-components@npm:^4.1.0-alpha.3": + version: 4.1.0-alpha.3 + resolution: "@jupyterlab/ui-components@npm:4.1.0-alpha.3" + dependencies: + "@jupyterlab/coreutils": ^6.1.0-alpha.3 + "@jupyterlab/observables": ^5.1.0-alpha.3 + "@jupyterlab/rendermime-interfaces": ^3.9.0-alpha.2 + "@jupyterlab/translation": ^4.1.0-alpha.3 + "@lumino/algorithm": ^2.0.1 + "@lumino/commands": ^2.1.3 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/messaging": ^2.0.1 + "@lumino/polling": ^2.1.2 + "@lumino/properties": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/virtualdom": ^2.0.1 + "@lumino/widgets": ^2.3.1-alpha.0 + "@rjsf/core": ^5.13.2 + "@rjsf/utils": ^5.13.2 + react: ^18.2.0 + react-dom: ^18.2.0 + typestyle: ^2.0.4 + peerDependencies: + react: ^18.2.0 + checksum: 3b0f05f9c8bf21c3e4b62a2f1e65454eaefbae66fb79da948e4b96cf7ddef2b8c334bb28a580287d4744bfb08565ca52d548d702f17047b5fa303473457c83d3 + languageName: node + linkType: hard + "@lerna/child-process@npm:6.6.2": version: 6.6.2 resolution: "@lerna/child-process@npm:6.6.2" @@ -3389,10 +3503,10 @@ __metadata: languageName: node linkType: hard -"@lumino/algorithm@npm:^2.0.0": - version: 2.0.0 - resolution: "@lumino/algorithm@npm:2.0.0" - checksum: 663edf536e94397b449c6a2643a735e602fbb396dec86b56ad1193a768dce27c6e7da5ad0384aa90086ea44cbb64dde3f9d565e9fd81858f1eb0c6b4253f3b94 +"@lumino/algorithm@npm:^2.0.0, @lumino/algorithm@npm:^2.0.1": + version: 2.0.1 + resolution: "@lumino/algorithm@npm:2.0.1" + checksum: cbf7fcf6ee6b785ea502cdfddc53d61f9d353dcb9659343511d5cd4b4030be2ff2ca4c08daec42f84417ab0318a3d9972a17319fa5231693e109ab112dcf8000 languageName: node linkType: hard @@ -3407,133 +3521,133 @@ __metadata: languageName: node linkType: hard -"@lumino/collections@npm:^2.0.0": - version: 2.0.0 - resolution: "@lumino/collections@npm:2.0.0" +"@lumino/collections@npm:^2.0.1": + version: 2.0.1 + resolution: "@lumino/collections@npm:2.0.1" dependencies: - "@lumino/algorithm": ^2.0.0 - checksum: 4a7fc3571e92a1368a1ef01300ad7b6e0d4ff13cb78b89533d5962eea66d4a7550e15d8b80fa3ab1816b1a89382f35015f9dddf72ab04654c17e5b516b845d8f + "@lumino/algorithm": ^2.0.1 + checksum: 8a29b7973a388a33c5beda0819dcd2dc2aad51a8406dcfd4581b055a9f77a39dc5800f7a8b4ae3c0bb97ae7b56a7a869e2560ffb7a920a28e93b477ba05907d6 languageName: node linkType: hard -"@lumino/commands@npm:^2.1.1, @lumino/commands@npm:^2.1.2": - version: 2.1.2 - resolution: "@lumino/commands@npm:2.1.2" +"@lumino/commands@npm:^2.1.1, @lumino/commands@npm:^2.1.2, @lumino/commands@npm:^2.1.3, @lumino/commands@npm:^2.2.0": + version: 2.2.0 + resolution: "@lumino/commands@npm:2.2.0" dependencies: - "@lumino/algorithm": ^2.0.0 - "@lumino/coreutils": ^2.1.1 - "@lumino/disposable": ^2.1.1 - "@lumino/domutils": ^2.0.0 - "@lumino/keyboard": ^2.0.0 - "@lumino/signaling": ^2.1.1 - "@lumino/virtualdom": ^2.0.0 - checksum: c0b5ce8c5e1a86a98a90f54bb07b74742748110cf3362b86ff8328c1b5475c4dc05f1c4c9f50bf79e51c4e2ddc5cd69d6194f3d39dd5b58f357b0f30758bf35b + "@lumino/algorithm": ^2.0.1 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/domutils": ^2.0.1 + "@lumino/keyboard": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/virtualdom": ^2.0.1 + checksum: 093e9715491e5cef24bc80665d64841417b400f2fa595f9b60832a3b6340c405c94a6aa276911944a2c46d79a6229f3cc087b73f50852bba25ece805abd0fae9 languageName: node linkType: hard -"@lumino/coreutils@npm:^1.11.0 || ^2.0.0, @lumino/coreutils@npm:^1.11.0 || ^2.1.1, @lumino/coreutils@npm:^2.1.0, @lumino/coreutils@npm:^2.1.1": - version: 2.1.1 - resolution: "@lumino/coreutils@npm:2.1.1" - checksum: dfdeb2b0282caae17b6c3edfebadf4ce7c75fc879fa60cacfef9b154412f4b35e4ffd95b1833b99d8dacb99aaaa04513570129ae2024c3f33e2677a01f0576ce +"@lumino/coreutils@npm:^1.11.0 || ^2.0.0, @lumino/coreutils@npm:^1.11.0 || ^2.1.1, @lumino/coreutils@npm:^1.11.0 || ^2.1.2, @lumino/coreutils@npm:^2.1.0, @lumino/coreutils@npm:^2.1.1, @lumino/coreutils@npm:^2.1.2": + version: 2.1.2 + resolution: "@lumino/coreutils@npm:2.1.2" + checksum: 7865317ac0676b448d108eb57ab5d8b2a17c101995c0f7a7106662d9fe6c859570104525f83ee3cda12ae2e326803372206d6f4c1f415a5b59e4158a7b81066f languageName: node linkType: hard -"@lumino/disposable@npm:^1.10.0 || ^2.0.0, @lumino/disposable@npm:^2.1.0, @lumino/disposable@npm:^2.1.1": - version: 2.1.1 - resolution: "@lumino/disposable@npm:2.1.1" +"@lumino/disposable@npm:^1.10.0 || ^2.0.0, @lumino/disposable@npm:^2.1.0, @lumino/disposable@npm:^2.1.1, @lumino/disposable@npm:^2.1.2": + version: 2.1.2 + resolution: "@lumino/disposable@npm:2.1.2" dependencies: - "@lumino/signaling": ^2.1.1 - checksum: ed6cdfe13f3346178a087690d4e7baeccaed7e73ca23cb239765202409f5c01b4729a4058b4717f963462ee9ef2e5cb14ad1974e3163741267290edc3715c85c + "@lumino/signaling": ^2.1.2 + checksum: ac2fb2bf18d0b2939fda454f3db248a0ff6e8a77b401e586d1caa9293b3318f808b93a117c9c3ac27cd17aab545aea83b49108d099b9b2f5503ae2a012fbc6e2 languageName: node linkType: hard -"@lumino/domutils@npm:^2.0.0": - version: 2.0.0 - resolution: "@lumino/domutils@npm:2.0.0" - checksum: 4a146bfc1006d5fd00ccecc61d9803965d269c15c48c892fd87216336ce967f0db91f31203c5616c83d260224cddf25af4abb6704a6770757d19e44068f690bf +"@lumino/domutils@npm:^2.0.0, @lumino/domutils@npm:^2.0.1": + version: 2.0.1 + resolution: "@lumino/domutils@npm:2.0.1" + checksum: 61fa0ab226869dfbb763fc426790cf5a43b7d6f4cea1364c6dd56d61c44bff05eea188d33ff847449608ef58ed343161bee15c19b96f35410e4ee35815dc611a languageName: node linkType: hard -"@lumino/dragdrop@npm:^2.1.1, @lumino/dragdrop@npm:^2.1.2": - version: 2.1.2 - resolution: "@lumino/dragdrop@npm:2.1.2" +"@lumino/dragdrop@npm:^2.1.1, @lumino/dragdrop@npm:^2.1.3, @lumino/dragdrop@npm:^2.1.4": + version: 2.1.4 + resolution: "@lumino/dragdrop@npm:2.1.4" dependencies: - "@lumino/coreutils": ^2.1.1 - "@lumino/disposable": ^2.1.1 - checksum: 7ac64ec11423ec89fea937aa6c9ca818933ee98e775e500018a0a948f32171932033a1e302a48395cbe9bfeaa635acde2393fd935db14d7b1d569ca6a1daaa77 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + checksum: 43d82484b13b38b612e7dfb424a840ed6a38d0db778af10655c4ba235c67b5b12db1683929b35a36ab2845f77466066dfd1ee25c1c273e8e175677eba9dc560d languageName: node linkType: hard -"@lumino/keyboard@npm:^2.0.0": - version: 2.0.0 - resolution: "@lumino/keyboard@npm:2.0.0" - checksum: 3852ba51f437b1c1d7e552a0f844592a05e04dd5012070dc6e4384c58965d1ebf536c6875c1b7bae03cde3c715ddc36cd290992fcefc1a8c39094194f4689fdd +"@lumino/keyboard@npm:^2.0.1": + version: 2.0.1 + resolution: "@lumino/keyboard@npm:2.0.1" + checksum: cf33f13427a418efd7cc91061233321e860d5404f3d86397781028309bef86c8ad2d88276ffe335c1db0fe619bd9d1e60641c81f881696957a58703ee4652c3e languageName: node linkType: hard -"@lumino/messaging@npm:^2.0.0": - version: 2.0.0 - resolution: "@lumino/messaging@npm:2.0.0" +"@lumino/messaging@npm:^2.0.0, @lumino/messaging@npm:^2.0.1": + version: 2.0.1 + resolution: "@lumino/messaging@npm:2.0.1" dependencies: - "@lumino/algorithm": ^2.0.0 - "@lumino/collections": ^2.0.0 - checksum: 1e82dcf9b110834d4342dc63dfeac0ee780880fb99051bd82d00a1f83afd91b276c1cea5af85a414d92c527adc365d54f20ec780123b562f89c5a2cd3e96bf81 + "@lumino/algorithm": ^2.0.1 + "@lumino/collections": ^2.0.1 + checksum: 964c4651c374b17452b4252b7d71500b32d2ecd87c192fc5bcf5d3bd1070661d78d07edcac8eca7d1d6fd50aa25992505485e1296d6dd995691b8e349b652045 languageName: node linkType: hard -"@lumino/polling@npm:^2.1.1": - version: 2.1.1 - resolution: "@lumino/polling@npm:2.1.1" +"@lumino/polling@npm:^2.1.1, @lumino/polling@npm:^2.1.2": + version: 2.1.2 + resolution: "@lumino/polling@npm:2.1.2" dependencies: - "@lumino/coreutils": ^2.1.1 - "@lumino/disposable": ^2.1.1 - "@lumino/signaling": ^2.1.1 - checksum: 69177b26d5fc541e72533cbe7d7f7999eea541d392f1082d20dbd9e1797e7d46fba47bae9c65c06f9ccb2780cbae636e9354d9bf4423b5e1020754d4b07d4f6b + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/signaling": ^2.1.2 + checksum: fa9b401e6dbeb8f31d7e3ba485e8ef1e0c92b3f2da086239c0ed49931026f5d3528709193c93e031e35ac624fb4bbbfcdcbaa0e25eb797f36e2952e5cd91e9e3 languageName: node linkType: hard -"@lumino/properties@npm:^2.0.0": - version: 2.0.0 - resolution: "@lumino/properties@npm:2.0.0" - checksum: 81187a11a779eed4e20ff0035e77dee99bd271b0cf649096c4e8809dd6bdd06955b1a974bc1a115e536f8d2840b30183bb78a362b2c6991824477df6d17e6c59 +"@lumino/properties@npm:^2.0.0, @lumino/properties@npm:^2.0.1": + version: 2.0.1 + resolution: "@lumino/properties@npm:2.0.1" + checksum: c50173a935148cc4148fdaea119df1d323ee004ae16ab666800388d27e9730345629662d85f25591683329b39f0cdae60ee8c94e8943b4d0ef7d7370a38128d6 languageName: node linkType: hard -"@lumino/signaling@npm:^1.10.0 || ^2.0.0, @lumino/signaling@npm:^2.1.0, @lumino/signaling@npm:^2.1.1": - version: 2.1.1 - resolution: "@lumino/signaling@npm:2.1.1" +"@lumino/signaling@npm:^1.10.0 || ^2.0.0, @lumino/signaling@npm:^2.1.0, @lumino/signaling@npm:^2.1.1, @lumino/signaling@npm:^2.1.2": + version: 2.1.2 + resolution: "@lumino/signaling@npm:2.1.2" dependencies: - "@lumino/algorithm": ^2.0.0 - "@lumino/coreutils": ^2.1.1 - checksum: 283ad4239b8577f68aca3d0b2606f73cc1c775f84cab25cf49aa6cd195f0d87949ef43fdff03b38b5a49ebbf2468581c6786d5f8b6159a04b2051260be5eab86 + "@lumino/algorithm": ^2.0.1 + "@lumino/coreutils": ^2.1.2 + checksum: ad7d7153db57980da899c43e412e6130316ef30b231a70250e7af49058db16cadb018c1417a2ea8083d83c48623cfe6b705fa82bf10216b1a8949aed9f4aca4e languageName: node linkType: hard -"@lumino/virtualdom@npm:^2.0.0": - version: 2.0.0 - resolution: "@lumino/virtualdom@npm:2.0.0" +"@lumino/virtualdom@npm:^2.0.0, @lumino/virtualdom@npm:^2.0.1": + version: 2.0.1 + resolution: "@lumino/virtualdom@npm:2.0.1" dependencies: - "@lumino/algorithm": ^2.0.0 - checksum: 6fc1d88e7d4a656be7664ccfc5745eb1d4e3d2034db0b11ad6abefcc642f22d265003eef0e1d02bca2e42b6da127123118c631369006f78e88a08885a6f36c25 + "@lumino/algorithm": ^2.0.1 + checksum: cf59b6f15b430e13e9e657b7a0619b9056cd9ea7b2a87f407391d071c501b77403c302b6a66dca510382045e75b2e3fe551630bb391f1c6b33678057d4bec164 languageName: node linkType: hard -"@lumino/widgets@npm:^1.37.2 || ^2.1.1, @lumino/widgets@npm:^2.1.0, @lumino/widgets@npm:^2.1.1, @lumino/widgets@npm:^2.2.0": - version: 2.2.0 - resolution: "@lumino/widgets@npm:2.2.0" +"@lumino/widgets@npm:^1.37.2 || ^2.1.1, @lumino/widgets@npm:^1.37.2 || ^2.3.1-alpha.0, @lumino/widgets@npm:^2.1.0, @lumino/widgets@npm:^2.1.1, @lumino/widgets@npm:^2.2.0, @lumino/widgets@npm:^2.3.1-alpha.0": + version: 2.3.1 + resolution: "@lumino/widgets@npm:2.3.1" dependencies: - "@lumino/algorithm": ^2.0.0 - "@lumino/commands": ^2.1.2 - "@lumino/coreutils": ^2.1.1 - "@lumino/disposable": ^2.1.1 - "@lumino/domutils": ^2.0.0 - "@lumino/dragdrop": ^2.1.2 - "@lumino/keyboard": ^2.0.0 - "@lumino/messaging": ^2.0.0 - "@lumino/properties": ^2.0.0 - "@lumino/signaling": ^2.1.1 - "@lumino/virtualdom": ^2.0.0 - checksum: 963c0e54102b786a9cbf3467041c9f6f5c275af751afc311ebeba30d56516767c463c425e321bb389eaa66726dfc4420119a9a58573dcbf3110aba9515c80606 + "@lumino/algorithm": ^2.0.1 + "@lumino/commands": ^2.2.0 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/domutils": ^2.0.1 + "@lumino/dragdrop": ^2.1.4 + "@lumino/keyboard": ^2.0.1 + "@lumino/messaging": ^2.0.1 + "@lumino/properties": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/virtualdom": ^2.0.1 + checksum: ba7b8f8839c1cd2a41dbda13281094eb6981a270cccf4f25a0cf83686dcc526a2d8044a20204317630bb7dd4a04d65361408c7623a921549c781afca84b91c67 languageName: node linkType: hard @@ -4239,25 +4353,25 @@ __metadata: languageName: node linkType: hard -"@rjsf/core@npm:^5.1.0": - version: 5.10.0 - resolution: "@rjsf/core@npm:5.10.0" +"@rjsf/core@npm:^5.1.0, @rjsf/core@npm:^5.13.2": + version: 5.13.6 + resolution: "@rjsf/core@npm:5.13.6" dependencies: lodash: ^4.17.21 lodash-es: ^4.17.21 - markdown-to-jsx: ^7.2.1 + markdown-to-jsx: ^7.3.2 nanoid: ^3.3.6 prop-types: ^15.8.1 peerDependencies: - "@rjsf/utils": ^5.8.x + "@rjsf/utils": ^5.12.x react: ^16.14.0 || >=17 - checksum: 11ff7f07e31ba13c1c6cb5e9aee94c4a5916a3f0013cb19fdeaea9254a77b50acee05d531a70adf92ee8a2024525916b20bb1af79d7afaadbd212a6124a57e5a + checksum: 7c8782030ac661fccd36226d84bca701af8e42717cb0560fb606784d358b1724288275f7ec2f9905b2a006ab65aa51525176d180908c6817b432afff4e989bdb languageName: node linkType: hard -"@rjsf/utils@npm:^5.1.0": - version: 5.10.0 - resolution: "@rjsf/utils@npm:5.10.0" +"@rjsf/utils@npm:^5.1.0, @rjsf/utils@npm:^5.13.2": + version: 5.13.6 + resolution: "@rjsf/utils@npm:5.13.6" dependencies: json-schema-merge-allof: ^0.8.1 jsonpointer: ^5.0.1 @@ -4266,7 +4380,7 @@ __metadata: react-is: ^18.2.0 peerDependencies: react: ^16.14.0 || >=17 - checksum: 5f44334598cfee3c2bf9a9561680e9c91abce9240ddf54cdb800fbbbb69b182fa7cc1839127558b3661aadbb185fba676eb3189352c8a8b5eea83d0b46987fa7 + checksum: 1e6cdca9f547db4b96561752150c0aa4255426fa32ae84ea017b221e5816e7eb9ed985e9dbb73f1d83baaae36f892f1d10e2bf81d8a53f7e42b2bfc7df52d8e4 languageName: node linkType: hard @@ -4558,13 +4672,6 @@ __metadata: languageName: node linkType: hard -"@types/prettier@npm:^2.1.5": - version: 2.7.3 - resolution: "@types/prettier@npm:2.7.3" - checksum: 705384209cea6d1433ff6c187c80dcc0b95d99d5c5ce21a46a9a58060c527973506822e428789d842761e0280d25e3359300f017fbe77b9755bc772ab3dc2f83 - languageName: node - linkType: hard - "@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0, @types/prop-types@npm:^15.7.5": version: 15.7.5 resolution: "@types/prop-types@npm:15.7.5" @@ -5040,20 +5147,7 @@ __metadata: languageName: node linkType: hard -"abstract-leveldown@npm:^6.2.1": - version: 6.3.0 - resolution: "abstract-leveldown@npm:6.3.0" - dependencies: - buffer: ^5.5.0 - immediate: ^3.2.3 - level-concat-iterator: ~2.0.0 - level-supports: ~1.0.0 - xtend: ~4.0.0 - checksum: 121a8509d8c6a540e656c2a69e5b8d853d4df71072011afefc868b98076991bb00120550e90643de9dc18889c675f62413409eeb4c8c204663124c7d215e4ec3 - languageName: node - linkType: hard - -"abstract-leveldown@npm:~6.2.1, abstract-leveldown@npm:~6.2.3": +"abstract-leveldown@npm:^6.2.1, abstract-leveldown@npm:~6.2.1, abstract-leveldown@npm:~6.2.3": version: 6.2.3 resolution: "abstract-leveldown@npm:6.2.3" dependencies: @@ -5441,23 +5535,6 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:^29.6.1": - version: 29.6.1 - resolution: "babel-jest@npm:29.6.1" - dependencies: - "@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.9 - slash: ^3.0.0 - peerDependencies: - "@babel/core": ^7.8.0 - checksum: bc46cfba468edde91f34a8292501d4448a39fab72d80d7d95f4349feb114fa21becb01def007d6166de7933ab9633bf5b5e1b72ba6ffeaa991f7abf014a2f61d - languageName: node - linkType: hard - "babel-jest@npm:^29.6.2": version: 29.6.2 resolution: "babel-jest@npm:29.6.2" @@ -5982,20 +6059,13 @@ __metadata: languageName: node linkType: hard -"cli-spinners@npm:2.6.1": +"cli-spinners@npm:2.6.1, cli-spinners@npm:^2.5.0": version: 2.6.1 resolution: "cli-spinners@npm:2.6.1" checksum: 423409baaa7a58e5104b46ca1745fbfc5888bbd0b0c5a626e052ae1387060839c8efd512fb127e25769b3dc9562db1dc1b5add6e0b93b7ef64f477feb6416a45 languageName: node linkType: hard -"cli-spinners@npm:^2.5.0": - version: 2.9.0 - resolution: "cli-spinners@npm:2.9.0" - checksum: a9c56e1f44457d4a9f4f535364e729cb8726198efa9e98990cfd9eda9e220dfa4ba12f92808d1be5e29029cdfead781db82dc8549b97b31c907d55f96aa9b0e2 - languageName: node - linkType: hard - "cli-width@npm:^3.0.0": version: 3.0.0 resolution: "cli-width@npm:3.0.0" @@ -7371,7 +7441,7 @@ __metadata: languageName: node linkType: hard -"execa@npm:5.0.0": +"execa@npm:5.0.0, execa@npm:^5.0.0": version: 5.0.0 resolution: "execa@npm:5.0.0" dependencies: @@ -7388,23 +7458,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.0.0": - version: 5.1.1 - resolution: "execa@npm:5.1.1" - dependencies: - cross-spawn: ^7.0.3 - get-stream: ^6.0.0 - human-signals: ^2.1.0 - is-stream: ^2.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^4.0.1 - onetime: ^5.1.2 - signal-exit: ^3.0.3 - strip-final-newline: ^2.0.0 - checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 - languageName: node - linkType: hard - "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -7426,20 +7479,6 @@ __metadata: languageName: node linkType: hard -"expect@npm:^29.6.1": - version: 29.6.1 - resolution: "expect@npm:29.6.1" - dependencies: - "@jest/expect-utils": ^29.6.1 - "@types/node": "*" - jest-get-type: ^29.4.3 - jest-matcher-utils: ^29.6.1 - jest-message-util: ^29.6.1 - jest-util: ^29.6.1 - checksum: 4e712e52c90f6c54e748fd2876be33c43ada6a59088ddf6a1acb08b18b3b97b3a672124684abe32599986d2f2a438d5afad148837ee06ea386d2a4bf0348de78 - languageName: node - linkType: hard - "exponential-backoff@npm:^3.1.1": version: 3.1.1 resolution: "exponential-backoff@npm:3.1.1" @@ -7923,20 +7962,13 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:6.0.0": +"get-stream@npm:6.0.0, get-stream@npm:^6.0.0": version: 6.0.0 resolution: "get-stream@npm:6.0.0" checksum: 587e6a93127f9991b494a566f4971cf7a2645dfa78034818143480a80587027bdd8826cdcf80d0eff4a4a19de0d231d157280f24789fc9cc31492e1dcc1290cf languageName: node linkType: hard -"get-stream@npm:^6.0.0": - version: 6.0.1 - resolution: "get-stream@npm:6.0.1" - checksum: e04ecece32c92eebf5b8c940f51468cd53554dcbb0ea725b2748be583c9523d00128137966afce410b9b051eb2ef16d657cd2b120ca8edafcf5a65e81af63cad - languageName: node - linkType: hard - "get-symbol-description@npm:^1.0.0": version: 1.0.0 resolution: "get-symbol-description@npm:1.0.0" @@ -8057,17 +8089,17 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3, glob@npm:^7.1.4": - version: 7.2.3 - resolution: "glob@npm:7.2.3" +"glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:~7.1.6": + version: 7.1.7 + resolution: "glob@npm:7.1.7" dependencies: fs.realpath: ^1.0.0 inflight: ^1.0.4 inherits: 2 - minimatch: ^3.1.1 + minimatch: ^3.0.4 once: ^1.3.0 path-is-absolute: ^1.0.0 - checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 + checksum: b61f48973bbdcf5159997b0874a2165db572b368b931135832599875919c237fc05c12984e38fe828e69aa8a921eb0e8a4997266211c517c9cfaae8a93988bb8 languageName: node linkType: hard @@ -8096,20 +8128,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:~7.1.6": - version: 7.1.7 - resolution: "glob@npm:7.1.7" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.0.4 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: b61f48973bbdcf5159997b0874a2165db572b368b931135832599875919c237fc05c12984e38fe828e69aa8a921eb0e8a4997266211c517c9cfaae8a93988bb8 - languageName: node - linkType: hard - "global-modules@npm:^2.0.0": version: 2.0.0 resolution: "global-modules@npm:2.0.0" @@ -8185,20 +8203,13 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:4.2.10": +"graceful-fs@npm:4.2.10, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.10 resolution: "graceful-fs@npm:4.2.10" checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 - languageName: node - linkType: hard - "handlebars@npm:^4.7.7": version: 4.7.7 resolution: "handlebars@npm:4.7.7" @@ -8737,7 +8748,7 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:8.2.4": +"inquirer@npm:8.2.4, inquirer@npm:^8.2.4": version: 8.2.4 resolution: "inquirer@npm:8.2.4" dependencies: @@ -8760,29 +8771,6 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:^8.2.4": - version: 8.2.5 - resolution: "inquirer@npm:8.2.5" - dependencies: - ansi-escapes: ^4.2.1 - chalk: ^4.1.1 - cli-cursor: ^3.1.0 - cli-width: ^3.0.0 - external-editor: ^3.0.3 - figures: ^3.0.0 - lodash: ^4.17.21 - mute-stream: 0.0.8 - ora: ^5.4.1 - run-async: ^2.4.0 - rxjs: ^7.5.5 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - through: ^2.3.6 - wrap-ansi: ^7.0.0 - checksum: f13ee4c444187786fb393609dedf6b30870115a57b603f2e6424f29a99abc13446fd45ee22461c33c9c40a92a60a8df62d0d6b25d74fc6676fa4cb211de55b55 - languageName: node - linkType: hard - "internal-slot@npm:^1.0.5": version: 1.0.5 resolution: "internal-slot@npm:1.0.5" @@ -9081,20 +9069,13 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:2.0.0": +"is-stream@npm:2.0.0, is-stream@npm:^2.0.0": version: 2.0.0 resolution: "is-stream@npm:2.0.0" checksum: 4dc47738e26bc4f1b3be9070b6b9e39631144f204fc6f87db56961220add87c10a999ba26cf81699f9ef9610426f69cb08a4713feff8deb7d8cadac907826935 languageName: node linkType: hard -"is-stream@npm:^2.0.0": - version: 2.0.1 - resolution: "is-stream@npm:2.0.1" - checksum: b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 - languageName: node - linkType: hard - "is-string@npm:^1.0.5, is-string@npm:^1.0.7": version: 1.0.7 resolution: "is-string@npm:1.0.7" @@ -9280,34 +9261,6 @@ __metadata: languageName: node linkType: hard -"jest-circus@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-circus@npm:29.6.1" - dependencies: - "@jest/environment": ^29.6.1 - "@jest/expect": ^29.6.1 - "@jest/test-result": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/node": "*" - chalk: ^4.0.0 - co: ^4.6.0 - dedent: ^0.7.0 - is-generator-fn: ^2.0.0 - jest-each: ^29.6.1 - jest-matcher-utils: ^29.6.1 - jest-message-util: ^29.6.1 - jest-runtime: ^29.6.1 - jest-snapshot: ^29.6.1 - jest-util: ^29.6.1 - p-limit: ^3.1.0 - pretty-format: ^29.6.1 - pure-rand: ^6.0.0 - slash: ^3.0.0 - stack-utils: ^2.0.3 - checksum: f3e39a74b601929448df92037f0599978d4d7a4b8f636f64e8020533d2d2b2f669d6729c80c6efed69341ca26753e5061e9787a0acd6c70af2127a94375ebb76 - languageName: node - linkType: hard - "jest-circus@npm:^29.6.2": version: 29.6.2 resolution: "jest-circus@npm:29.6.2" @@ -9336,33 +9289,6 @@ __metadata: languageName: node linkType: hard -"jest-cli@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-cli@npm:29.6.1" - dependencies: - "@jest/core": ^29.6.1 - "@jest/test-result": ^29.6.1 - "@jest/types": ^29.6.1 - chalk: ^4.0.0 - exit: ^0.1.2 - graceful-fs: ^4.2.9 - import-local: ^3.0.2 - jest-config: ^29.6.1 - jest-util: ^29.6.1 - jest-validate: ^29.6.1 - prompts: ^2.0.1 - yargs: ^17.3.1 - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: bin/jest.js - checksum: f5854ffea977b9a12520ea71f8d0cc8a626cbb93d7e1e6eea18a2a1f2b25f70f1b6b08a89f11b4dc7dd36a1776a9ac2cf8ec5c7998086f913ee690c06c07c949 - languageName: node - linkType: hard - "jest-cli@npm:^29.6.2": version: 29.6.2 resolution: "jest-cli@npm:29.6.2" @@ -9390,44 +9316,6 @@ __metadata: languageName: node linkType: hard -"jest-config@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-config@npm:29.6.1" - dependencies: - "@babel/core": ^7.11.6 - "@jest/test-sequencer": ^29.6.1 - "@jest/types": ^29.6.1 - babel-jest: ^29.6.1 - chalk: ^4.0.0 - ci-info: ^3.2.0 - deepmerge: ^4.2.2 - glob: ^7.1.3 - graceful-fs: ^4.2.9 - jest-circus: ^29.6.1 - jest-environment-node: ^29.6.1 - jest-get-type: ^29.4.3 - jest-regex-util: ^29.4.3 - jest-resolve: ^29.6.1 - jest-runner: ^29.6.1 - jest-util: ^29.6.1 - jest-validate: ^29.6.1 - micromatch: ^4.0.4 - parse-json: ^5.2.0 - pretty-format: ^29.6.1 - 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: 3a30afeb28cc5658ef9cd95f2551ab8a29641bb6d377eb239cba8e7522eb4611c9a98cdcf173d87f5ad7b5e1ad242c3cd5434a260107bd3c7e8305d05023e05c - languageName: node - linkType: hard - "jest-config@npm:^29.6.2": version: 29.6.2 resolution: "jest-config@npm:29.6.2" @@ -9466,18 +9354,6 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-diff@npm:29.6.1" - dependencies: - chalk: ^4.0.0 - diff-sequences: ^29.4.3 - jest-get-type: ^29.4.3 - pretty-format: ^29.6.1 - checksum: c6350178ca27d92c7fd879790fb2525470c1ff1c5d29b1834a240fecd26c6904fb470ebddb98dc96dd85389c56c3b50e6965a1f5203e9236d213886ed9806219 - languageName: node - linkType: hard - "jest-diff@npm:^29.6.2": version: 29.6.2 resolution: "jest-diff@npm:29.6.2" @@ -9499,19 +9375,6 @@ __metadata: languageName: node linkType: hard -"jest-each@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-each@npm:29.6.1" - dependencies: - "@jest/types": ^29.6.1 - chalk: ^4.0.0 - jest-get-type: ^29.4.3 - jest-util: ^29.6.1 - pretty-format: ^29.6.1 - checksum: 9d2ea7ed5326ee8c22523b22c66c85fe73754ea39f9b389881956508ee441392c61072a5fbf673e39beddd31d011bb94acae3edc77053ba4f9aa5c060114a5c8 - languageName: node - linkType: hard - "jest-each@npm:^29.6.2": version: 29.6.2 resolution: "jest-each@npm:29.6.2" @@ -9546,20 +9409,6 @@ __metadata: languageName: node linkType: hard -"jest-environment-node@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-environment-node@npm:29.6.1" - dependencies: - "@jest/environment": ^29.6.1 - "@jest/fake-timers": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/node": "*" - jest-mock: ^29.6.1 - jest-util: ^29.6.1 - checksum: a50287e1ff29d131646bd09acc3222ac6ea0ad61e86bf73851d318ef2be0633a421b8558c4a15ddc67e0ffcfc32da7f6a0d8a2ddbfa85453837899dec88d256c - languageName: node - linkType: hard - "jest-environment-node@npm:^29.6.2": version: 29.6.2 resolution: "jest-environment-node@npm:29.6.2" @@ -9581,29 +9430,6 @@ __metadata: languageName: node linkType: hard -"jest-haste-map@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-haste-map@npm:29.6.1" - dependencies: - "@jest/types": ^29.6.1 - "@types/graceful-fs": ^4.1.3 - "@types/node": "*" - 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.1 - jest-worker: ^29.6.1 - micromatch: ^4.0.4 - walker: ^1.0.8 - dependenciesMeta: - fsevents: - optional: true - checksum: 7c74d5a0f6aafa9f4e60fae7949d4774770c0243fb529c24f2f4c81229db479fa318dc8b81e8d226865aef1d600af10bd8404dd208e802318434b46f75d5d869 - languageName: node - linkType: hard - "jest-haste-map@npm:^29.6.2": version: 29.6.2 resolution: "jest-haste-map@npm:29.6.2" @@ -9634,18 +9460,8 @@ __metadata: mkdirp: ^1.0.4 strip-ansi: ^6.0.1 uuid: ^8.3.2 - xml: ^1.0.1 - checksum: e8fe4d2f2ab843383ac41820a6fe495739d154ec435cd44ba590b44ec7fd62095676f3eef13f98392f81d4a3727ea58b4f4fad231fe367ac31243952b9ad716f - languageName: node - linkType: hard - -"jest-leak-detector@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-leak-detector@npm:29.6.1" - dependencies: - jest-get-type: ^29.4.3 - pretty-format: ^29.6.1 - checksum: 5122d40c248effaede4c9ee3a99046a3f30088fef7bfc4af534678b432455161399357af46deb6423de7e05c6597920d6ee8cd570e26048886a90d541334f8c8 + xml: ^1.0.1 + checksum: e8fe4d2f2ab843383ac41820a6fe495739d154ec435cd44ba590b44ec7fd62095676f3eef13f98392f81d4a3727ea58b4f4fad231fe367ac31243952b9ad716f languageName: node linkType: hard @@ -9659,18 +9475,6 @@ __metadata: languageName: node linkType: hard -"jest-matcher-utils@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-matcher-utils@npm:29.6.1" - dependencies: - chalk: ^4.0.0 - jest-diff: ^29.6.1 - jest-get-type: ^29.4.3 - pretty-format: ^29.6.1 - checksum: d2efa6aed6e4820758b732b9fefd315c7fa4508ee690da656e1c5ac4c1a0f4cee5b04c9719ee1fda9aeb883b4209186c145089ced521e715b9fa70afdfa4a9c6 - languageName: node - linkType: hard - "jest-matcher-utils@npm:^29.6.2": version: 29.6.2 resolution: "jest-matcher-utils@npm:29.6.2" @@ -9683,23 +9487,6 @@ __metadata: languageName: node linkType: hard -"jest-message-util@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-message-util@npm:29.6.1" - dependencies: - "@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.1 - slash: ^3.0.0 - stack-utils: ^2.0.3 - checksum: 3e7cb2ff087fe72255292e151d24e4fbb4cd6134885c0a67a4b302f233fe4110bf7580b176f427f05ad7550eb878ed94237209785d09d659a7d171ffa59c068f - languageName: node - linkType: hard - "jest-message-util@npm:^29.6.2": version: 29.6.2 resolution: "jest-message-util@npm:29.6.2" @@ -9717,18 +9504,7 @@ __metadata: languageName: node linkType: hard -"jest-mock@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-mock@npm:29.6.1" - dependencies: - "@jest/types": ^29.6.1 - "@types/node": "*" - jest-util: ^29.6.1 - checksum: 5e902f1a7eba1eb1a64eb6c19947fe1316834359d9869d0e2644d8979b9cad0465885dc4c9909c471888cddeea835c938cec6263d386d3d1aad720fc74e52ea1 - languageName: node - linkType: hard - -"jest-mock@npm:^29.6.2": +"jest-mock@npm:^29.6.1, jest-mock@npm:^29.6.2": version: 29.6.2 resolution: "jest-mock@npm:29.6.2" dependencies: @@ -9758,16 +9534,6 @@ __metadata: languageName: node linkType: hard -"jest-resolve-dependencies@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-resolve-dependencies@npm:29.6.1" - dependencies: - jest-regex-util: ^29.4.3 - jest-snapshot: ^29.6.1 - checksum: cee0a0fe53fd4531492a526b6ccd32377baad1eff6e6c124f04e9dc920219fd23fd39be88bb9551ee68d5fe92a3af627b423c9bc65a2aa0ac8a223c0e74dbbbb - languageName: node - linkType: hard - "jest-resolve-dependencies@npm:^29.6.2": version: 29.6.2 resolution: "jest-resolve-dependencies@npm:29.6.2" @@ -9778,23 +9544,6 @@ __metadata: languageName: node linkType: hard -"jest-resolve@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-resolve@npm:29.6.1" - dependencies: - chalk: ^4.0.0 - graceful-fs: ^4.2.9 - jest-haste-map: ^29.6.1 - jest-pnp-resolver: ^1.2.2 - jest-util: ^29.6.1 - jest-validate: ^29.6.1 - resolve: ^1.20.0 - resolve.exports: ^2.0.0 - slash: ^3.0.0 - checksum: 9ce979a0f4a751bea58caea76415112df2a3f4d58e294019872244728aadd001f0ec20c873a3c805dd8f7c762143b3c14d00f87d124ed87c9981fbf8723090ef - languageName: node - linkType: hard - "jest-resolve@npm:^29.6.2": version: 29.6.2 resolution: "jest-resolve@npm:29.6.2" @@ -9812,35 +9561,6 @@ __metadata: languageName: node linkType: hard -"jest-runner@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-runner@npm:29.6.1" - dependencies: - "@jest/console": ^29.6.1 - "@jest/environment": ^29.6.1 - "@jest/test-result": ^29.6.1 - "@jest/transform": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/node": "*" - chalk: ^4.0.0 - emittery: ^0.13.1 - graceful-fs: ^4.2.9 - jest-docblock: ^29.4.3 - jest-environment-node: ^29.6.1 - jest-haste-map: ^29.6.1 - jest-leak-detector: ^29.6.1 - jest-message-util: ^29.6.1 - jest-resolve: ^29.6.1 - jest-runtime: ^29.6.1 - jest-util: ^29.6.1 - jest-watcher: ^29.6.1 - jest-worker: ^29.6.1 - p-limit: ^3.1.0 - source-map-support: 0.5.13 - checksum: 0e4dbda26669ae31fee32f8a62b3119bba510f2d17a098d6157b48a73ed2fc9842405bf893f3045c12b3632c7c0e3399fb22684b18ab5566aff4905b26c79a9a - languageName: node - linkType: hard - "jest-runner@npm:^29.6.2": version: 29.6.2 resolution: "jest-runner@npm:29.6.2" @@ -9870,36 +9590,6 @@ __metadata: languageName: node linkType: hard -"jest-runtime@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-runtime@npm:29.6.1" - dependencies: - "@jest/environment": ^29.6.1 - "@jest/fake-timers": ^29.6.1 - "@jest/globals": ^29.6.1 - "@jest/source-map": ^29.6.0 - "@jest/test-result": ^29.6.1 - "@jest/transform": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/node": "*" - chalk: ^4.0.0 - 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.1 - jest-message-util: ^29.6.1 - jest-mock: ^29.6.1 - jest-regex-util: ^29.4.3 - jest-resolve: ^29.6.1 - jest-snapshot: ^29.6.1 - jest-util: ^29.6.1 - slash: ^3.0.0 - strip-bom: ^4.0.0 - checksum: 7c360c9694467d996f3d6d914fefa0e7bda554adda8c2b9fba31546dba663d71a64eda103ff68120a2422f3c16db8f0bc2c445923fe8fb934f37e53ef74fb429 - languageName: node - linkType: hard - "jest-runtime@npm:^29.6.2": version: 29.6.2 resolution: "jest-runtime@npm:29.6.2" @@ -9930,35 +9620,6 @@ __metadata: languageName: node linkType: hard -"jest-snapshot@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-snapshot@npm:29.6.1" - dependencies: - "@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.1 - "@jest/transform": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/prettier": ^2.1.5 - babel-preset-current-node-syntax: ^1.0.0 - chalk: ^4.0.0 - expect: ^29.6.1 - graceful-fs: ^4.2.9 - jest-diff: ^29.6.1 - jest-get-type: ^29.4.3 - jest-matcher-utils: ^29.6.1 - jest-message-util: ^29.6.1 - jest-util: ^29.6.1 - natural-compare: ^1.4.0 - pretty-format: ^29.6.1 - semver: ^7.5.3 - checksum: e8f69d1fd4a29d354d4dca9eb2a22674b300f8ef509e4f1e75337c880414a00d2bdc9d3849a6855dbb5a76bfbe74603f33435378a3877e69f0838e4cc2244350 - languageName: node - linkType: hard - "jest-snapshot@npm:^29.6.2": version: 29.6.2 resolution: "jest-snapshot@npm:29.6.2" @@ -9987,21 +9648,7 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.0.0, jest-util@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-util@npm:29.6.1" - dependencies: - "@jest/types": ^29.6.1 - "@types/node": "*" - chalk: ^4.0.0 - ci-info: ^3.2.0 - graceful-fs: ^4.2.9 - picomatch: ^2.2.3 - checksum: fc553556c1350c443449cadaba5fb9d604628e8b5ceb6ceaf4e7e08975b24277d0a14bf2e0f956024e03c23e556fcb074659423422a06fbedf2ab52978697ac7 - languageName: node - linkType: hard - -"jest-util@npm:^29.6.2": +"jest-util@npm:^29.0.0, jest-util@npm:^29.6.1, jest-util@npm:^29.6.2": version: 29.6.2 resolution: "jest-util@npm:29.6.2" dependencies: @@ -10015,20 +9662,6 @@ __metadata: languageName: node linkType: hard -"jest-validate@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-validate@npm:29.6.1" - dependencies: - "@jest/types": ^29.6.1 - camelcase: ^6.2.0 - chalk: ^4.0.0 - jest-get-type: ^29.4.3 - leven: ^3.1.0 - pretty-format: ^29.6.1 - checksum: d2491f3f33d9bbc2dcaaa6acbff26f257b59c5eeceb65a52a9c1cec2f679b836ec2a4658b7004c0ef9d90cd0d9bd664e41d5ed6900f932bea742dd8e6b85e7f1 - languageName: node - linkType: hard - "jest-validate@npm:^29.6.2": version: 29.6.2 resolution: "jest-validate@npm:29.6.2" @@ -10043,22 +9676,6 @@ __metadata: languageName: node linkType: hard -"jest-watcher@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-watcher@npm:29.6.1" - dependencies: - "@jest/test-result": ^29.6.1 - "@jest/types": ^29.6.1 - "@types/node": "*" - ansi-escapes: ^4.2.1 - chalk: ^4.0.0 - emittery: ^0.13.1 - jest-util: ^29.6.1 - string-length: ^4.0.1 - checksum: 69bd5a602284fdce6eba5486c5c57aca6b511d91cb0907c34c104d6dd931e18ce67baa7f8e280fa473e5d81ea3e7b9e7d94f712c37ab0b3b8cc2aec30676955d - languageName: node - linkType: hard - "jest-watcher@npm:^29.6.2": version: 29.6.2 resolution: "jest-watcher@npm:29.6.2" @@ -10086,18 +9703,6 @@ __metadata: languageName: node linkType: hard -"jest-worker@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-worker@npm:29.6.1" - dependencies: - "@types/node": "*" - jest-util: ^29.6.1 - merge-stream: ^2.0.0 - supports-color: ^8.0.0 - checksum: 0af309ea4db17c4c47e84a9246f907960a15577683c005fdeafc8f3c06bc455136f95a6f28fa2a3e924b767eb4dacd9b40915a7707305f88586f099af3ac27a8 - languageName: node - linkType: hard - "jest-worker@npm:^29.6.2": version: 29.6.2 resolution: "jest-worker@npm:29.6.2" @@ -10110,7 +9715,7 @@ __metadata: languageName: node linkType: hard -"jest@npm:^29": +"jest@npm:^29, jest@npm:^29.2.0": version: 29.6.2 resolution: "jest@npm:29.6.2" dependencies: @@ -10129,25 +9734,6 @@ __metadata: languageName: node linkType: hard -"jest@npm:^29.2.0": - version: 29.6.1 - resolution: "jest@npm:29.6.1" - dependencies: - "@jest/core": ^29.6.1 - "@jest/types": ^29.6.1 - import-local: ^3.0.2 - jest-cli: ^29.6.1 - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - bin: - jest: bin/jest.js - checksum: 7b8c0ca72f483e00ec19dcf9549f9a9af8ae468ab62925b148d714b58eb52d5fea9a082625193bc833d2d9b64cf65a11f3d37857636c5551af05c10aec4ce71b - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -10995,12 +10581,12 @@ __metadata: languageName: node linkType: hard -"markdown-to-jsx@npm:^7.2.1": - version: 7.2.1 - resolution: "markdown-to-jsx@npm:7.2.1" +"markdown-to-jsx@npm:^7.3.2": + version: 7.3.2 + resolution: "markdown-to-jsx@npm:7.3.2" peerDependencies: react: ">= 0.14.0" - checksum: 0c8c715229044401ea48c2fc26c2554464100074959dafacdd9e4a0e849f0a190b02f39edb373bbdd95e38b8f910074b83b63d08752b8ae6be6ddcfb40ea50a0 + checksum: 8885c6343b71570b0a7ec16cd85a49b853a830234790ee7430e2517ea5d8d361ff138bd52147f650790f3e7b3a28a15c755fc16f8856dd01ddf09a6161782e06 languageName: node linkType: hard @@ -11484,7 +11070,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:^3.0.4, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -11639,20 +11225,13 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0": +"minipass@npm:^5.0.0, minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0": version: 5.0.0 resolution: "minipass@npm:5.0.0" checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0": - version: 7.0.2 - resolution: "minipass@npm:7.0.2" - checksum: 46776de732eb7cef2c7404a15fb28c41f5c54a22be50d47b03c605bf21f5c18d61a173c0a20b49a97e7a65f78d887245066410642551e45fffe04e9ac9e325bc - languageName: node - linkType: hard - "minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": version: 2.1.2 resolution: "minizlib@npm:2.1.2" @@ -11697,20 +11276,13 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.2": +"ms@npm:2.1.2, ms@npm:^2.0.0": version: 2.1.2 resolution: "ms@npm:2.1.2" checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f languageName: node linkType: hard -"ms@npm:^2.0.0": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d - languageName: node - linkType: hard - "multimatch@npm:5.0.0": version: 5.0.0 resolution: "multimatch@npm:5.0.0" @@ -11784,7 +11356,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:2.6.7": +"node-fetch@npm:2.6.7, node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" dependencies: @@ -11798,20 +11370,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.7": - version: 2.6.12 - resolution: "node-fetch@npm:2.6.12" - dependencies: - whatwg-url: ^5.0.0 - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 3bc1655203d47ee8e313c0d96664b9673a3d4dd8002740318e9d27d14ef306693a4b2ef8d6525775056fd912a19e23f3ac0d7111ad8925877b7567b29a625592 - languageName: node - linkType: hard - "node-gyp-build@npm:^4.3.0": version: 4.6.0 resolution: "node-gyp-build@npm:4.6.0" @@ -11980,13 +11538,6 @@ __metadata: languageName: node linkType: hard -"npm-normalize-package-bin@npm:^2.0.0": - version: 2.0.0 - resolution: "npm-normalize-package-bin@npm:2.0.0" - checksum: 7c5379f9b188b564c4332c97bdd9a5d6b7b15f02b5823b00989d6a0e6fb31eb0280f02b0a924f930e1fcaf00e60fae333aec8923d2a4c7747613c7d629d8aa25 - languageName: node - linkType: hard - "npm-normalize-package-bin@npm:^3.0.0, npm-normalize-package-bin@npm:^3.0.1": version: 3.0.1 resolution: "npm-normalize-package-bin@npm:3.0.1" @@ -12064,7 +11615,7 @@ __metadata: languageName: node linkType: hard -"npm-registry-fetch@npm:14.0.3": +"npm-registry-fetch@npm:14.0.3, npm-registry-fetch@npm:^14.0.0, npm-registry-fetch@npm:^14.0.3": version: 14.0.3 resolution: "npm-registry-fetch@npm:14.0.3" dependencies: @@ -12094,21 +11645,6 @@ __metadata: languageName: node linkType: hard -"npm-registry-fetch@npm:^14.0.0, npm-registry-fetch@npm:^14.0.3": - version: 14.0.5 - resolution: "npm-registry-fetch@npm:14.0.5" - dependencies: - make-fetch-happen: ^11.0.0 - minipass: ^5.0.0 - minipass-fetch: ^3.0.0 - minipass-json-stream: ^1.0.1 - minizlib: ^2.1.2 - npm-package-arg: ^10.0.0 - proc-log: ^3.0.0 - checksum: c63649642955b424bc1baaff5955027144af312ae117ba8c24829e74484f859482591fe89687c6597d83e930c8054463eef23020ac69146097a72cc62ff10986 - languageName: node - linkType: hard - "npm-run-all@npm:^4.1.5": version: 4.1.5 resolution: "npm-run-all@npm:4.1.5" @@ -12484,7 +12020,7 @@ __metadata: languageName: node linkType: hard -"pacote@npm:15.1.1": +"pacote@npm:15.1.1, pacote@npm:^15.0.0, pacote@npm:^15.0.8": version: 15.1.1 resolution: "pacote@npm:15.1.1" dependencies: @@ -12512,34 +12048,6 @@ __metadata: languageName: node linkType: hard -"pacote@npm:^15.0.0, pacote@npm:^15.0.8": - version: 15.2.0 - resolution: "pacote@npm:15.2.0" - dependencies: - "@npmcli/git": ^4.0.0 - "@npmcli/installed-package-contents": ^2.0.1 - "@npmcli/promise-spawn": ^6.0.1 - "@npmcli/run-script": ^6.0.0 - cacache: ^17.0.0 - fs-minipass: ^3.0.0 - minipass: ^5.0.0 - npm-package-arg: ^10.0.0 - npm-packlist: ^7.0.0 - npm-pick-manifest: ^8.0.0 - npm-registry-fetch: ^14.0.0 - proc-log: ^3.0.0 - promise-retry: ^2.0.1 - read-package-json: ^6.0.0 - read-package-json-fast: ^3.0.0 - sigstore: ^1.3.0 - ssri: ^10.0.0 - tar: ^6.1.11 - bin: - pacote: lib/bin.js - checksum: c731572be2bf226b117eba076d242bd4cd8be7aa01e004af3374a304ad7ab330539e22644bc33de12d2a7d45228ccbcbf4d710f59c84414f3d09a1a95ee6f0bf - languageName: node - linkType: hard - "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -12914,25 +12422,7 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.6.1": - version: 29.6.1 - resolution: "pretty-format@npm:29.6.1" - dependencies: - "@jest/schemas": ^29.6.0 - ansi-styles: ^5.0.0 - react-is: ^18.0.0 - checksum: 6f923a2379a37a425241dc223d76f671c73c4f37dba158050575a54095867d565c068b441843afdf3d7c37bed9df4bbadf46297976e60d4149972b779474203a - languageName: node - linkType: hard - -"prismjs@npm:^1.27.0": - version: 1.29.0 - resolution: "prismjs@npm:1.29.0" - checksum: 007a8869d4456ff8049dc59404e32d5666a07d99c3b0e30a18bd3b7676dfa07d1daae9d0f407f20983865fd8da56de91d09cb08e6aa61f5bc420a27c0beeaf93 - languageName: node - linkType: hard - -"prismjs@npm:~1.27.0": +"prismjs@npm:^1.27.0, prismjs@npm:~1.27.0": version: 1.27.0 resolution: "prismjs@npm:1.27.0" checksum: 85c7f4a3e999073502cc9e1882af01e3709706369ec254b60bff1149eda701f40d02512acab956012dc7e61cfd61743a3a34c1bd0737e8dbacd79141e5698bbc @@ -13262,7 +12752,7 @@ __metadata: languageName: node linkType: hard -"read-package-json@npm:5.0.1": +"read-package-json@npm:5.0.1, read-package-json@npm:^5.0.0": version: 5.0.1 resolution: "read-package-json@npm:5.0.1" dependencies: @@ -13274,18 +12764,6 @@ __metadata: languageName: node linkType: hard -"read-package-json@npm:^5.0.0": - version: 5.0.2 - resolution: "read-package-json@npm:5.0.2" - dependencies: - glob: ^8.0.1 - json-parse-even-better-errors: ^2.3.1 - normalize-package-data: ^4.0.0 - npm-normalize-package-bin: ^2.0.0 - checksum: 0882ac9cec1bc92fb5515e9727611fb2909351e1e5c840dce3503cbb25b4cd48eb44b61071986e0fc51043208161f07d364a7336206c8609770186818753b51a - languageName: node - linkType: hard - "read-package-json@npm:^6.0.0": version: 6.0.4 resolution: "read-package-json@npm:6.0.4" @@ -13969,7 +13447,7 @@ __metadata: languageName: node linkType: hard -"sigstore@npm:^1.0.0, sigstore@npm:^1.3.0, sigstore@npm:^1.4.0": +"sigstore@npm:^1.0.0, sigstore@npm:^1.4.0": version: 1.8.0 resolution: "sigstore@npm:1.8.0" dependencies: @@ -14601,7 +14079,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:6.1.11": +"tar@npm:6.1.11, tar@npm:^6.1.11, tar@npm:^6.1.2": version: 6.1.11 resolution: "tar@npm:6.1.11" dependencies: @@ -14615,20 +14093,6 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.1.15 - resolution: "tar@npm:6.1.15" - dependencies: - chownr: ^2.0.0 - fs-minipass: ^2.0.0 - minipass: ^5.0.0 - minizlib: ^2.1.1 - mkdirp: ^1.0.3 - yallist: ^4.0.0 - checksum: f23832fceeba7578bf31907aac744ae21e74a66f4a17a9e94507acf460e48f6db598c7023882db33bab75b80e027c21f276d405e4a0322d58f51c7088d428268 - languageName: node - linkType: hard - "temp-dir@npm:1.0.0": version: 1.0.0 resolution: "temp-dir@npm:1.0.0" @@ -15048,17 +14512,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^3 || ^4": - version: 4.9.5 - resolution: "typescript@npm:4.9.5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db - languageName: node - linkType: hard - -"typescript@npm:~4.3.0": +"typescript@npm:^3 || ^4, typescript@npm:~4.3.0": version: 4.3.5 resolution: "typescript@npm:4.3.5" bin: @@ -15068,17 +14522,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@^3 || ^4#~builtin": - version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: ab417a2f398380c90a6cf5a5f74badd17866adf57f1165617d6a551f059c3ba0a3e4da0d147b3ac5681db9ac76a303c5876394b13b3de75fdd5b1eaa06181c9d - languageName: node - linkType: hard - -"typescript@patch:typescript@~4.3.0#~builtin": +"typescript@patch:typescript@^3 || ^4#~builtin, 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: @@ -16085,7 +15529,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:20.2.4": +"yargs-parser@npm:20.2.4, yargs-parser@npm:^20.2.2, yargs-parser@npm:^20.2.3": version: 20.2.4 resolution: "yargs-parser@npm:20.2.4" checksum: d251998a374b2743a20271c2fd752b9fbef24eb881d53a3b99a7caa5e8227fcafd9abf1f345ac5de46435821be25ec12189a11030c12ee6481fef6863ed8b924 @@ -16099,13 +15543,6 @@ __metadata: languageName: node linkType: hard -"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@npm:16.2.0, yargs@npm:^16.2.0": version: 16.2.0 resolution: "yargs@npm:16.2.0"