From fd00ab7de2bd955f2e4d355041dfc19963f67f68 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Fri, 20 Sep 2024 14:18:52 -0700 Subject: [PATCH 001/133] Added prototype for state changes. Visualization components do better with state handled as traces that can rewind. As such definitions and evaluation of a guidance grammar is separated here while minimizing changes needed at the grammar level. --- .gitignore | 1 + guidance/models/_model.py | 56 +++++++-- guidance/state/__init__.py | 148 +++++++++++++++++++++++ notebooks/unstable/State Debugging.ipynb | 80 ++++++++++++ tests/unit/test_decorator.py | 2 +- 5 files changed, 277 insertions(+), 10 deletions(-) create mode 100644 guidance/state/__init__.py create mode 100644 notebooks/unstable/State Debugging.ipynb diff --git a/.gitignore b/.gitignore index c590bc397..8aff96dae 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ notebooks/local_scratch __pycache__/ .vscode .vs +.idea/ /build /dist *.egg-info diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 74f3c8af0..11f8f735e 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -15,6 +15,8 @@ import numpy as np +from ..state import StateHandler, Nop, LiteralInput, EmbeddedInput, GuidanceInput, TextOutput + try: from IPython.display import clear_output, display, HTML @@ -65,6 +67,7 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False): self.tokenizer = tokenizer self.compute_log_probs = compute_log_probs self.metrics = GuidanceEngineMetrics() + self._state_handler = StateHandler() def get_chat_template(self): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? return self.tokenizer.chat_template() # Instantiate the class before returning to client for now @@ -187,6 +190,10 @@ def _report_failed_match(self, prompt): + str(prompt[-40:]) ) + @property + def state_handler(self): + return self._state_handler + class Model: """The base guidance model object, which represents a model in a given state. @@ -202,8 +209,9 @@ class Model: open_blocks: Dict["ContextBlock", None] = {} # track what context blocks are open _grammar_only = 0 # a flag that tracks when we are forced to be executing only compiled grammars (like when we are inside a select) _throttle_refresh = 0 # a flag that tracks when we can throttle our display since we know future display calls are going to happen + _id_counter = 0 # counter for model ids - def __init__(self, engine, echo=True, **kwargs): + def __init__(self, engine, echo=True, parent_id=None, **kwargs): """Build a new model object that represents a model in a given state. Note that this constructor is not meant to be used directly, since there @@ -214,6 +222,8 @@ def __init__(self, engine, echo=True, **kwargs): The inference engine to use for this model. echo : bool If true the final result of creating this model state will be displayed (as HTML in a notebook). + parent_id : int + Parent model's identifier. """ if isinstance(engine, str) and engine.startswith("http"): from ._remote import RemoteEngine @@ -237,11 +247,22 @@ def __init__(self, engine, echo=True, **kwargs): self._variables_log_probs = {} # these are the state variables stored with the model self._cache_state = {} # mutable caching state used to save computation self._state = "" # the current bytes that represent the state of the model + self._state_handler = engine.state_handler # builds state for models self._event_queue = None # TODO: these are for streaming results in code, but that needs implemented self._event_parent = None self._last_display = 0 # used to track the last display call to enable throttling self._last_event_stream = 0 # used to track the last event streaming call to enable throttling + self._id = self.__class__.gen_id() # model id needed for tracking state + self._parent_id = parent_id + self._state_handler.add_node(self._id, self._parent_id, Nop()) + + @classmethod + def gen_id(cls): + _id = cls._id_counter + cls._id_counter += 1 + return _id + @property def active_role_end(self): """The default end patterns we should use for `gen` calls. @@ -313,7 +334,11 @@ def copy(self): elif self._event_parent is not None: # otherwise if the current event que has an event parent then that is also our parent - new_lm._event_parent = self._event_parent + new_lm._event_parent = self._event_parent + + new_lm._state_handler = self._state_handler + new_lm._id = self.__class__.gen_id() + new_lm._parent_id = self._id return new_lm @@ -454,11 +479,15 @@ def __add__(self, value): # we have no embedded objects if len(parts) == 1: + self._state_handler.add_node(lm._id, lm._parent_id, LiteralInput(value)) + lm._inplace_append(value) out = lm - + self._state_handler.add_node(out._id, out._parent_id, TextOutput(value)) # if we have embedded objects we have to convert the string to a grammar tree else: + self._state_handler.add_node(lm._id, lm._parent_id, EmbeddedInput(value)) + partial_grammar = _null_grammar lm.suffix = "" for i, part in enumerate(parts): @@ -475,6 +504,7 @@ def __add__(self, value): elif part != "": partial_grammar += string(part) is_id = not is_id + out = lm + partial_grammar # if we find a null value we do nothing @@ -483,10 +513,12 @@ def __add__(self, value): # run stateless functions (grammar nodes) elif isinstance(value, GrammarFunction): + self._state_handler.add_node(lm._id, lm._parent_id, GuidanceInput(value)) out = lm._run_stateless(value) # run stateful functions else: + self._state_handler.add_node(lm._id, lm._parent_id, GuidanceInput(value)) out = value(lm) if out is None: raise Exception( @@ -497,9 +529,6 @@ def __add__(self, value): f"A guidance function did not return a model object! Did you try to add a function to a model without calling the function? For example `model + guidance_function()` is correct, while `model + guidance_function` will cause this error." ) - # this flushes the display - out._inplace_append("") - return out # def endswith(self, s): @@ -708,10 +737,19 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): if len(chunk.new_bytes) > 0: generated_value += new_text if chunk.is_generated: - lm += f"<||_html:_||>" - lm += new_text + # TODO(viz) + # lm += f"<||_html:_||>" + pass + + # TODO(nopdive): Remove old code on confirmation + # lm += new_text + lm._inplace_append(new_text) + self._state_handler.add_node(lm._id, lm._parent_id, TextOutput(new_text)) + if chunk.is_generated: - lm += "<||_html:_||>" + # TODO(viz) + # lm += "<||_html:_||>" + pass # last_is_generated = chunk.is_generated diff --git a/guidance/state/__init__.py b/guidance/state/__init__.py new file mode 100644 index 000000000..5265dfba0 --- /dev/null +++ b/guidance/state/__init__.py @@ -0,0 +1,148 @@ +"""State of models, including state tree that represents a guidance trace within Python. + +The first implementation aims for simplicity. +Once benchmark figures are out, we'll figure out what to optimize. +""" +# TODO(nopdive): Deal with weak referencing for GC + +from typing import Dict, Any +import weakref + + +class StateHandler: + def __init__(self) -> None: + self._model_node_map: Dict[int, StateNode] = {} + self._node_model_map: Dict[StateNode, int] = {} + + def add_node(self, model_id: int, parent_id: int, node: "StateNode") -> None: + self._model_node_map[model_id] = node + self._node_model_map[node] = model_id + + parent_node = self._model_node_map.get(parent_id, None) + if parent_node is not None: + parent_node.add_child(node) + +_id_counter = 0 +class StateNode: + def __init__(self) -> None: + self._id = self.__class__.gen_id() + self._parent = None + self._children = [] + + def add_child(self, child: "StateNode") -> None: + child._parent = self + self._children.append(child) + + def remove_child(self, child: "StateNode") -> None: + child._parent = None + self._children.remove(child) + + @property + def children(self): + return self._children + + @property + def parent(self): + return self._parent + + @classmethod + def gen_id(cls): + global _id_counter + _id = _id_counter + _id_counter += 1 + return _id + + +def visualize(state_builder: StateHandler, node: StateNode) -> None: + from anytree import Node, RenderTree + + def visit(node: StateNode, viz_parent=None): + nonlocal state_builder + + if viz_parent is None: + viz_node = Node(f"{state_builder._node_model_map[node]}:{node}") + else: + viz_node = Node(f"{state_builder._node_model_map[node]}:{node}", parent=viz_parent) + + for child in node.children: + visit(child, viz_node) + return viz_node + viz_root = visit(node) + + for pre, fill, node in RenderTree(viz_root): + tree_str = u"%s%s" % (pre, node.name) + print(tree_str) + + +class InputNode(StateNode): + def __init__(self) -> None: + super().__init__() + + +class OutputNode(StateNode): + def __init__(self) -> None: + super().__init__() + + +class TrackingNode(StateNode): + def __init__(self) -> None: + super().__init__() + + +class Nop(TrackingNode): + def __init__(self): + super().__init__() + + def __str__(self): + return f"{self._id}:Nop" + + +class GuidanceInput(StateNode): + def __init__(self, value: Any): + self._value = value + super().__init__() + + def __str__(self): + return f"{self._id}:{self.__class__.__name__}:{self._value.__class__.__name__}:{self._value}" + + +class LiteralInput(InputNode): + def __init__(self, value: str): + self._value = value + super().__init__() + + def __str__(self): + return f"{self._id}:{self.__class__.__name__}:{self._value}" + + +class TextOutput(OutputNode): + def __init__(self, value: str): + self._value = value + super().__init__() + + def __str__(self): + return f"{self._id}:{self.__class__.__name__}:{self._value}" + + +class EmbeddedInput(InputNode): + def __init__(self, value: str): + self._value = value + super().__init__() + + def __str__(self): + return f"{self._id}:{self.__class__.__name__}:{self._value}" + + +# class Env: +# def __init__(self, parent: Optional["Env"] = None) -> None: +# self._symbol_table = {} +# self._parent = parent +# +# def __getitem__(self, item: Any) -> Any: +# current_env = self +# while current_env._parent is not None: +# if item in current_env._symbol_table: +# return current_env[item] +# raise KeyError(item) + + diff --git a/notebooks/unstable/State Debugging.ipynb b/notebooks/unstable/State Debugging.ipynb new file mode 100644 index 000000000..b7fcc9f1c --- /dev/null +++ b/notebooks/unstable/State Debugging.ipynb @@ -0,0 +1,80 @@ +{ + "cells": [ + { + "cell_type": "code", + "id": "1ec02432-a44d-4fdb-b44c-b153529fc03d", + "metadata": {}, + "source": [ + "from guidance.models import Transformers\n", + "from guidance import gen, select" + ], + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": [ + "model_0 = Transformers(\"gpt2\")\n", + "model_1 = model_0 + f\"Hi there {gen(name='name', max_tokens=10, regex='[A-Za-z]{3,5}')}\"\n", + "model_2 = model_0 + f\"You can't stop \" + gen(name='name', max_tokens=10, regex='[A-Za-z]{3,5}')\n", + "# model_1 += f\"Hi there {gen(name='name', max_tokens=10, regex='[A-Za-z]')} {select(['!', '?'], name='punc')}\"\n", + "# model += f\"Hi there \" + gen('name', max_tokens=10, regex='[A-Za-z]') + \"!\"\n", + "# " + ], + "id": "18b70f42-4b6d-41a4-94be-a41360571901", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": [ + "from guidance.state import visualize\n", + "\n", + "\n", + "visualize(model_0._state_handler, model_0._state_handler._model_node_map[0])" + ], + "id": "b5d6e974-bc52-4bbd-a8d4-69d681c33072", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": "", + "id": "8c3a1aecf66cc31", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": "", + "id": "d4070d52b59fad", + "outputs": [], + "execution_count": null + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/unit/test_decorator.py b/tests/unit/test_decorator.py index 62042f814..ebe43f86f 100644 --- a/tests/unit/test_decorator.py +++ b/tests/unit/test_decorator.py @@ -98,7 +98,7 @@ def inconsistent_indentation(lm): # NOTE [HN]: The following two tests currently don't work, but they're fairly special/rare cases. # Some implementation thoughts for the future: -# Nested f-strings: try creating a custom handler for ast.FormattedValue in the handler? +# Nested f-strings: try creating a custom handler for state.FormattedValue in the handler? # closure functions: storing and rebinding vars referenced in func globals when recompiling? # def test_nested_fstrings(): # """Test nested f-strings.""" From 5d032e1af7d32f8d98d05489400faef173b9a951 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Thu, 26 Sep 2024 14:36:10 -0700 Subject: [PATCH 002/133] WIP state nodes now update. Probably need to have separate fields for tracking, input and output of a given node. --- guidance/library/_block.py | 1 + guidance/library/_role.py | 75 ++++++------ guidance/models/_model.py | 99 +++++++++++---- guidance/state/__init__.py | 86 +++++++++---- notebooks/unstable/State Debugging.ipynb | 147 ++++++++++++++++++----- tests/unit/test_model.py | 14 ++- 6 files changed, 307 insertions(+), 115 deletions(-) diff --git a/guidance/library/_block.py b/guidance/library/_block.py index 753e34e36..a7bc71861 100644 --- a/guidance/library/_block.py +++ b/guidance/library/_block.py @@ -12,6 +12,7 @@ def __enter__(self): def __exit__(self, exc_type, exc_value, traceback): del models.Model.open_blocks[self] + models.Model.close_blocks[self] = None def block(name=None, opener="", closer=""): diff --git a/guidance/library/_role.py b/guidance/library/_role.py index 843ed904e..9bc73db96 100644 --- a/guidance/library/_role.py +++ b/guidance/library/_role.py @@ -7,66 +7,66 @@ span_start = "<||_html:_||>" span_end = "<||_html:_||>" +# TODO(nopdive): Render needs to be moved out @guidance def role_opener(lm, role_name, **kwargs): - indent = getattr(lm, "indent_roles", True) + # indent = getattr(lm, "indent_roles", True) # Block start container (centers elements) - if indent: - lm += f"<||_html:
{role_name.lower()}
_||>" + # if indent: + # lm += f"<||_html:
{role_name.lower()}
_||>" # Start of either debug or HTML no disp block - if indent: - lm += nodisp_start - else: - lm += span_start + # if indent: + # lm += nodisp_start + # else: + # lm += span_start # TODO [HN]: Temporary change while I instrument chat_template in transformers only. # Eventually have all models use chat_template. - if hasattr(lm, "get_role_start"): - lm += lm.get_role_start(role_name, **kwargs) - elif hasattr(lm, "chat_template"): - lm += lm.chat_template.get_role_start(role_name) - else: - raise Exception( - f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" - ) + lm = lm._add_role_opener(role_name, **kwargs) + + # if hasattr(lm, "get_role_start"): + # lm += lm.get_role_start(role_name, **kwargs) + # elif hasattr(lm, "chat_template"): + # lm += lm.chat_template.get_role_start(role_name) + # else: + # raise Exception( + # f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" + # ) # End of either debug or HTML no disp block - if indent: - lm += nodisp_end - else: - lm += span_end + # if indent: + # lm += nodisp_end + # else: + # lm += span_end return lm @guidance def role_closer(lm, role_name, **kwargs): - indent = getattr(lm, "indent_roles", True) - # Start of either debug or HTML no disp block - if indent: - lm += nodisp_start - else: - lm += span_start + # indent = getattr(lm, "indent_roles", True) + # # Start of either debug or HTML no disp block + # if indent: + # lm += nodisp_start + # else: + # lm += span_start # TODO [HN]: Temporary change while I instrument chat_template in transformers only. # Eventually have all models use chat_template. - if hasattr(lm, "get_role_end"): - lm += lm.get_role_end(role_name) - elif hasattr(lm, "chat_template"): - lm += lm.chat_template.get_role_end(role_name) + lm = lm._add_role_closer(role_name, **kwargs) - # End of either debug or HTML no disp block - if indent: - lm += nodisp_end - else: - lm += span_end + # # End of either debug or HTML no disp block + # if indent: + # lm += nodisp_end + # else: + # lm += span_end - # End of top container - if indent: - lm += "<||_html:
_||>" + # # End of top container + # if indent: + # lm += "<||_html:
_||>" return lm @@ -74,6 +74,7 @@ def role_closer(lm, role_name, **kwargs): def role(role_name, text=None, **kwargs): if text is None: return block( + name=role_name, opener=role_opener(role_name, **kwargs), closer=role_closer(role_name, **kwargs), ) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 11f8f735e..97bf420d4 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -15,7 +15,7 @@ import numpy as np -from ..state import StateHandler, Nop, LiteralInput, EmbeddedInput, GuidanceInput, TextOutput +from ..state import RoleCloserInput, RoleOpenerInput, StateHandler, Tracker, LiteralInput, EmbeddedInput, StatefulGuidanceInput, StatelessGuidanceInput, TextOutput try: from IPython.display import clear_output, display, HTML @@ -195,6 +195,7 @@ def state_handler(self): return self._state_handler +_id_counter = 0 # Counter for identifiers, this has to be outside the model to handle child classes properly. class Model: """The base guidance model object, which represents a model in a given state. @@ -207,9 +208,10 @@ class Model: """ open_blocks: Dict["ContextBlock", None] = {} # track what context blocks are open + close_blocks: Dict["ContextBlock", None] = {} # track what context block is about to close + _grammar_only = 0 # a flag that tracks when we are forced to be executing only compiled grammars (like when we are inside a select) _throttle_refresh = 0 # a flag that tracks when we can throttle our display since we know future display calls are going to happen - _id_counter = 0 # counter for model ids def __init__(self, engine, echo=True, parent_id=None, **kwargs): """Build a new model object that represents a model in a given state. @@ -240,6 +242,7 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self.token_count = 0 # tracks how many tokens our byte state represents self.max_display_rate = 0.2 # this controls how frequently we are allowed to redraw the display (in seconds) self.opened_blocks = {} # what context blocks have been opened but not closed + self.closed_blocks = {} # what context blocks have been closed after open # self.compute_log_probs = compute_log_probs # private attributes @@ -255,12 +258,14 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self._id = self.__class__.gen_id() # model id needed for tracking state self._parent_id = parent_id - self._state_handler.add_node(self._id, self._parent_id, Nop()) + self._state_handler.update_node(self._id, self._parent_id, Tracker()) @classmethod def gen_id(cls): - _id = cls._id_counter - cls._id_counter += 1 + global _id_counter + + _id = _id_counter + _id_counter += 1 return _id @property @@ -324,6 +329,7 @@ def copy(self): new_lm._variables = self._variables.copy() new_lm._variables_log_probs = self._variables_log_probs.copy() new_lm.opened_blocks = self.opened_blocks.copy() + new_lm.closed_blocks = self.closed_blocks.copy() # create a new clean event queue new_lm._event_queue = None # we start with no event queue because nobody is listening to us yet @@ -339,6 +345,7 @@ def copy(self): new_lm._state_handler = self._state_handler new_lm._id = self.__class__.gen_id() new_lm._parent_id = self._id + self._state_handler.update_node(new_lm._id, new_lm._parent_id, Tracker()) return new_lm @@ -398,6 +405,40 @@ def reset(self, clear_variables=True): self._variables = {} self._variables_log_probs = {} return self + + # NOTE(nopdive): Intentionally private, consider this friend scoped. Users should never be interacting with this method directly. + def _add_role_opener(self, role_name, **kwargs): + lm = self + # self._state_handler.add_node(lm._id, lm._parent_id, RoleOpener(role_name)) + + # TODO [HN]: Temporary change while I instrument chat_template in transformers only. + # Eventually have all models use chat_template. + if hasattr(lm, "get_role_start"): + lm += lm.get_role_start(role_name, **kwargs) + elif hasattr(lm, "chat_template"): + lm += lm.chat_template.get_role_start(role_name) + else: + raise Exception( + f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" + ) + + return lm + + # NOTE(nopdive): Intentionally private, consider this friend scoped. Users should never be interacting with this method directly. + def _add_role_closer(self, role_name, **kwargs): + lm = self + + # TODO [HN]: Temporary change while I instrument chat_template in transformers only. + # Eventually have all models use chat_template. + if hasattr(lm, "get_role_end"): + lm += lm.get_role_end(role_name, **kwargs) + elif hasattr(lm, "chat_template"): + lm += lm.chat_template.get_role_end(role_name) + else: + raise Exception( + f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" + ) + return lm def _repr_html_(self): if ipython_is_imported: @@ -432,13 +473,20 @@ def __add__(self, value): with throttle_refresh(): # find what new blocks need to be applied - new_blocks = [] + enter_blocks = [] for context in Model.open_blocks: if context not in lm.opened_blocks: - new_blocks.append(context) + enter_blocks.append(context) # mark this so we don't re-add when computing the opener or closer (even though we don't know the close text yet) lm.opened_blocks[context] = (0, "") + + exit_blocks = [] + for context in Model.close_blocks: + if context not in lm.closed_blocks: + exit_blocks.append(context) + lm.closed_blocks[context] = (0, "") + # find what old blocks need to be removed old_blocks = [] @@ -449,17 +497,26 @@ def __add__(self, value): # delete this so we don't re-close when computing the opener or closer del lm.opened_blocks[context] - # close any newly closed contexts + # # close any newly closed contexts for (pos, close_text), context in old_blocks: if context.name is not None: lm._variables[context.name] = format_pattern.sub( "", lm._state[pos:] ) - lm += context.closer + # self._state_handler.add_node(lm._id, lm._parent_id, RoleCloser(context.name)) + + # TODO(nopdive): Consider removing this + # lm = lm + context.closer + + for context in exit_blocks: + self._state_handler.update_node(lm._id, lm._parent_id, RoleCloserInput(context.name)) + lm = lm + context.closer # apply any newly opened contexts (new from this object's perspective) - for context in new_blocks: - lm += context.opener + for context in enter_blocks: + self._state_handler.update_node(lm._id, lm._parent_id, RoleOpenerInput(context.name)) + lm = lm + context.opener + with grammar_only(): tmp = lm + context.closer close_text = tmp._state[len(lm._state):] # get the new state added by calling the closer @@ -479,14 +536,14 @@ def __add__(self, value): # we have no embedded objects if len(parts) == 1: - self._state_handler.add_node(lm._id, lm._parent_id, LiteralInput(value)) + self._state_handler.update_node(lm._id, lm._parent_id, LiteralInput(value)) - lm._inplace_append(value) - out = lm - self._state_handler.add_node(out._id, out._parent_id, TextOutput(value)) + out = lm.copy() + out._inplace_append(value) + self._state_handler.update_node(out._id, out._parent_id, TextOutput(value)) # if we have embedded objects we have to convert the string to a grammar tree else: - self._state_handler.add_node(lm._id, lm._parent_id, EmbeddedInput(value)) + self._state_handler.update_node(lm._id, lm._parent_id, EmbeddedInput(value)) partial_grammar = _null_grammar lm.suffix = "" @@ -513,12 +570,12 @@ def __add__(self, value): # run stateless functions (grammar nodes) elif isinstance(value, GrammarFunction): - self._state_handler.add_node(lm._id, lm._parent_id, GuidanceInput(value)) + self._state_handler.update_node(lm._id, lm._parent_id, StatelessGuidanceInput(value)) out = lm._run_stateless(value) # run stateful functions else: - self._state_handler.add_node(lm._id, lm._parent_id, GuidanceInput(value)) + self._state_handler.update_node(lm._id, lm._parent_id, StatefulGuidanceInput(value)) out = value(lm) if out is None: raise Exception( @@ -742,9 +799,9 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): pass # TODO(nopdive): Remove old code on confirmation - # lm += new_text - lm._inplace_append(new_text) - self._state_handler.add_node(lm._id, lm._parent_id, TextOutput(new_text)) + lm += new_text + # lm._inplace_append(new_text) + # self._state_handler.add_node(lm._id, lm._parent_id, TextOutput(new_text)) if chunk.is_generated: # TODO(viz) diff --git a/guidance/state/__init__.py b/guidance/state/__init__.py index 5265dfba0..bbb309480 100644 --- a/guidance/state/__init__.py +++ b/guidance/state/__init__.py @@ -13,11 +13,25 @@ class StateHandler: def __init__(self) -> None: self._model_node_map: Dict[int, StateNode] = {} self._node_model_map: Dict[StateNode, int] = {} + + def _remove_node(self, model_id: int) -> None: + node = self._model_node_map.get(model_id, None) + for child in node.children: + child.parent = None + if node.parent is not None: + node.parent.remove_child(node) + + del self._model_node_map[model_id] + del self._node_model_map[node] + + def update_node(self, model_id: int, parent_id: int, node: "StateNode") -> None: + # Replace node if required + existing_node = self._model_node_map.get(model_id, None) + if existing_node is not None: + self._remove_node(model_id) - def add_node(self, model_id: int, parent_id: int, node: "StateNode") -> None: self._model_node_map[model_id] = node self._node_model_map[node] = model_id - parent_node = self._model_node_map.get(parent_id, None) if parent_node is not None: parent_node.add_child(node) @@ -45,6 +59,10 @@ def children(self): def parent(self): return self._parent + @parent.setter + def parent(self, value): + self._parent = value + @classmethod def gen_id(cls): global _id_counter @@ -52,6 +70,18 @@ def gen_id(cls): _id_counter += 1 return _id + def __repr__(self): + return self.__str__() + + +def visualize_text(state_builder: StateHandler, node: StateNode) -> None: + def visit(node: StateNode, buffer=[]): + if node.parent is not None: + visit(node._parent) + if isinstance(node, TextOutput): + print(node._value, end='') + visit(node) + def visualize(state_builder: StateHandler, node: StateNode) -> None: from anytree import Node, RenderTree @@ -84,27 +114,31 @@ def __init__(self) -> None: super().__init__() -class TrackingNode(StateNode): - def __init__(self) -> None: +class Tracker(StateNode): + def __init__(self): super().__init__() + def __str__(self): + return f"{self._id}:Tracker" -class Nop(TrackingNode): - def __init__(self): + +class StatelessGuidanceInput(InputNode): + def __init__(self, value: Any): + self._value = value super().__init__() def __str__(self): - return f"{self._id}:Nop" + return f"{self._id}:{self.__class__.__name__}:{self._value}" -class GuidanceInput(StateNode): +class StatefulGuidanceInput(InputNode): def __init__(self, value: Any): self._value = value super().__init__() def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{self._value.__class__.__name__}:{self._value}" - + return f"{self._id}:{self.__class__.__name__}:{self._value}" + class LiteralInput(InputNode): def __init__(self, value: str): @@ -112,7 +146,7 @@ def __init__(self, value: str): super().__init__() def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{self._value}" + return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" class TextOutput(OutputNode): @@ -121,7 +155,7 @@ def __init__(self, value: str): super().__init__() def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{self._value}" + return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" class EmbeddedInput(InputNode): @@ -130,19 +164,23 @@ def __init__(self, value: str): super().__init__() def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{self._value}" + return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" + + +class RoleOpenerInput(InputNode): + def __init__(self, value: str): + self._value = value + super().__init__() + + def __str__(self): + return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" -# class Env: -# def __init__(self, parent: Optional["Env"] = None) -> None: -# self._symbol_table = {} -# self._parent = parent -# -# def __getitem__(self, item: Any) -> Any: -# current_env = self -# while current_env._parent is not None: -# if item in current_env._symbol_table: -# return current_env[item] -# raise KeyError(item) +class RoleCloserInput(InputNode): + def __init__(self, value: str): + self._value = value + super().__init__() + def __str__(self): + return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" diff --git a/notebooks/unstable/State Debugging.ipynb b/notebooks/unstable/State Debugging.ipynb index b7fcc9f1c..1e05a05d2 100644 --- a/notebooks/unstable/State Debugging.ipynb +++ b/notebooks/unstable/State Debugging.ipynb @@ -3,57 +3,140 @@ { "cell_type": "code", "id": "1ec02432-a44d-4fdb-b44c-b153529fc03d", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-26T21:31:55.029427Z", + "start_time": "2024-09-26T21:31:53.440050Z" + } + }, "source": [ "from guidance.models import Transformers\n", - "from guidance import gen, select" + "from guidance import gen, user, system" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/samueljenkins/dev/guidance-dev/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n", + " warnings.warn(\n" + ] + } + ], + "execution_count": 1 }, { - "metadata": {}, "cell_type": "code", + "id": "18b70f42-4b6d-41a4-94be-a41360571901", + "metadata": {}, "source": [ - "model_0 = Transformers(\"gpt2\")\n", - "model_1 = model_0 + f\"Hi there {gen(name='name', max_tokens=10, regex='[A-Za-z]{3,5}')}\"\n", - "model_2 = model_0 + f\"You can't stop \" + gen(name='name', max_tokens=10, regex='[A-Za-z]{3,5}')\n", - "# model_1 += f\"Hi there {gen(name='name', max_tokens=10, regex='[A-Za-z]')} {select(['!', '?'], name='punc')}\"\n", - "# model += f\"Hi there \" + gen('name', max_tokens=10, regex='[A-Za-z]') + \"!\"\n", - "# " + "m0 = Transformers(\"gpt2\")\n", + "with system():\n", + " m1 = m0 + \"You are responsible for autocompleting a sentence.\"\n", + "with user():\n", + " m2 = m1 + \"Roses are red and \" + gen(name=\"suffix\", regex='[A-Za-z]{2,5}', max_tokens=5)\n", + "\n", + "# m1 = m0 + f\"Hi there {gen(name='name', max_tokens=10, regex='[A-Za-z]{3,5}')}\"\n", + "# m2 = m0 + f\"You can't stop \" + gen(name='name', max_tokens=10, regex='[A-Za-z]{3,5}')\n", + "\n", + "# with system():\n", + "# m3 = m0 + \"You are responsible for autocompleting a sentence.\"\n", + "\n", + "# with user():\n", + "# m4 = m3 + \"The sun is rising \" + gen(name='sentence_suffix', max_tokens=3)" ], - "id": "18b70f42-4b6d-41a4-94be-a41360571901", - "outputs": [], - "execution_count": null + "execution_count": 2, + "outputs": [] }, { - "metadata": {}, "cell_type": "code", + "id": "b5d6e974-bc52-4bbd-a8d4-69d681c33072", + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-26T21:31:56.819858Z", + "start_time": "2024-09-26T21:31:56.779818Z" + } + }, "source": [ - "from guidance.state import visualize\n", - "\n", + "from guidance.state import visualize, visualize_text\n", "\n", - "visualize(model_0._state_handler, model_0._state_handler._model_node_map[0])" + "visualize(m0._state_handler, m0._state_handler._model_node_map[0])" ], - "id": "b5d6e974-bc52-4bbd-a8d4-69d681c33072", - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0:0:Tracker\n", + "└── 1:2:RoleOpenerInput:'system'\n", + " └── 2:4:StatefulGuidanceInput:{{G|5074217616|G}}\n", + " └── 3:6:LiteralInput:'<|im_start|>system\\n'\n", + " └── 4:15:LiteralInput:'You are responsible for autocompleting a sentence.'\n", + " └── 8:17:TextOutput:'You are responsible for autocompleting a sentence.'\n", + " └── 9:19:RoleCloserInput:'system'\n", + " └── 10:21:StatefulGuidanceInput:{{G|5096533584|G}}\n", + " └── 11:23:LiteralInput:'<|im_end|>\\n'\n", + " └── 12:26:RoleOpenerInput:'user'\n", + " └── 13:28:StatefulGuidanceInput:{{G|5236675744|G}}\n", + " └── 14:30:LiteralInput:'<|im_start|>user\\n'\n", + " └── 15:39:LiteralInput:'Roses are red and '\n", + " └── 19:41:TextOutput:'Roses are red and '\n", + " └── 20:43:StatelessGuidanceInput:{{G|5074674128|G}}\n", + " └── 21:45:LiteralInput:'you'\n", + " └── 22:47:TextOutput:'you'\n" + ] + } + ], + "execution_count": 3 }, { - "metadata": {}, "cell_type": "code", - "source": "", - "id": "8c3a1aecf66cc31", - "outputs": [], - "execution_count": null + "id": "d4070d52b59fad", + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-26T21:31:57.874141Z", + "start_time": "2024-09-26T21:31:57.871821Z" + } + }, + "source": [ + "visualize_text(m0._state_handler, m0._state_handler._model_node_map[22])" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "You are responsible for autocompleting a sentence.Roses are red and you" + ] + } + ], + "execution_count": 4 }, { - "metadata": {}, "cell_type": "code", - "source": "", - "id": "d4070d52b59fad", - "outputs": [], - "execution_count": null + "id": "d70ed049", + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-26T21:31:58.936929Z", + "start_time": "2024-09-26T21:31:58.933671Z" + } + }, + "source": [ + "m0._state_handler._model_node_map[3]" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "6:LiteralInput:'<|im_start|>system\\n'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 5 } ], "metadata": { @@ -72,7 +155,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.14" + "version": "3.12.5" } }, "nbformat": 4, diff --git a/tests/unit/test_model.py b/tests/unit/test_model.py index 965c48ce2..b95f31e8d 100644 --- a/tests/unit/test_model.py +++ b/tests/unit/test_model.py @@ -1,6 +1,6 @@ import pytest import guidance -from guidance import gen, models +from guidance import gen, models, user, system def test_call_embeddings(): """This tests calls embedded in strings.""" @@ -22,6 +22,18 @@ def ble(lm): assert "{{G|" not in str(model + ble()) +def test_state_handler(): + from guidance.state import visualize, visualize_text + m0 = models.Mock() + with system(): + m1 = m0 + "You are responsible for autocompleting a sentence." + with user(): + m2 = m1 + "Roses are red and " + gen(name="suffix", regex='[A-Za-z]{2,5}', max_tokens=5) + print(visualize(m0._state_handler, m0._state_handler._model_node_map[0])) + + assert m2['suffix'] is not None + + @pytest.mark.xfail( reason="llguidance currently emits an additional empty capture group when no explicit stop is provided" ) From b7c15ffdc8cf7ba0b16c56762fec3cde5542082c Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Thu, 26 Sep 2024 22:27:13 -0700 Subject: [PATCH 003/133] Added working role to trace tree. --- guidance/models/_model.py | 27 ++-- guidance/state/__init__.py | 176 ++++++++++++----------- notebooks/unstable/State Debugging.ipynb | 119 ++++----------- setup.py | 1 + tests/unit/test_model.py | 1 + 5 files changed, 131 insertions(+), 193 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 97bf420d4..527fdda2c 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -15,7 +15,7 @@ import numpy as np -from ..state import RoleCloserInput, RoleOpenerInput, StateHandler, Tracker, LiteralInput, EmbeddedInput, StatefulGuidanceInput, StatelessGuidanceInput, TextOutput +from ..state import RoleCloserInput, RoleOpenerInput, StateHandler, LiteralInput, EmbeddedInput, StatefulGuidanceInput, StatelessGuidanceInput, TextOutput try: from IPython.display import clear_output, display, HTML @@ -67,7 +67,8 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False): self.tokenizer = tokenizer self.compute_log_probs = compute_log_probs self.metrics = GuidanceEngineMetrics() - self._state_handler = StateHandler() + + self.state_handler = StateHandler() def get_chat_template(self): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? return self.tokenizer.chat_template() # Instantiate the class before returning to client for now @@ -190,10 +191,6 @@ def _report_failed_match(self, prompt): + str(prompt[-40:]) ) - @property - def state_handler(self): - return self._state_handler - _id_counter = 0 # Counter for identifiers, this has to be outside the model to handle child classes properly. class Model: @@ -258,7 +255,7 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self._id = self.__class__.gen_id() # model id needed for tracking state self._parent_id = parent_id - self._state_handler.update_node(self._id, self._parent_id, Tracker()) + self._state_handler.update_node(self._id, self._parent_id, None) @classmethod def gen_id(cls): @@ -345,7 +342,7 @@ def copy(self): new_lm._state_handler = self._state_handler new_lm._id = self.__class__.gen_id() new_lm._parent_id = self._id - self._state_handler.update_node(new_lm._id, new_lm._parent_id, Tracker()) + self._state_handler.update_node(new_lm._id, new_lm._parent_id, None) return new_lm @@ -497,25 +494,26 @@ def __add__(self, value): # delete this so we don't re-close when computing the opener or closer del lm.opened_blocks[context] - # # close any newly closed contexts + # close any newly closed contexts for (pos, close_text), context in old_blocks: if context.name is not None: lm._variables[context.name] = format_pattern.sub( "", lm._state[pos:] ) - # self._state_handler.add_node(lm._id, lm._parent_id, RoleCloser(context.name)) - # TODO(nopdive): Consider removing this # lm = lm + context.closer - + + # apply any newly closed contexts (new from this object's perspective) for context in exit_blocks: self._state_handler.update_node(lm._id, lm._parent_id, RoleCloserInput(context.name)) lm = lm + context.closer + lm = lm.copy() # apply any newly opened contexts (new from this object's perspective) for context in enter_blocks: self._state_handler.update_node(lm._id, lm._parent_id, RoleOpenerInput(context.name)) lm = lm + context.opener + lm = lm.copy() with grammar_only(): tmp = lm + context.closer @@ -538,8 +536,9 @@ def __add__(self, value): if len(parts) == 1: self._state_handler.update_node(lm._id, lm._parent_id, LiteralInput(value)) - out = lm.copy() - out._inplace_append(value) + lm._inplace_append(value) + out = lm + self._state_handler.update_node(out._id, out._parent_id, TextOutput(value)) # if we have embedded objects we have to convert the string to a grammar tree else: diff --git a/guidance/state/__init__.py b/guidance/state/__init__.py index bbb309480..c4eb07f85 100644 --- a/guidance/state/__init__.py +++ b/guidance/state/__init__.py @@ -5,7 +5,9 @@ """ # TODO(nopdive): Deal with weak referencing for GC -from typing import Dict, Any +from dataclasses import dataclass, field +from itertools import count +from typing import Dict, Any, Optional import weakref @@ -13,88 +15,76 @@ class StateHandler: def __init__(self) -> None: self._model_node_map: Dict[int, StateNode] = {} self._node_model_map: Dict[StateNode, int] = {} - - def _remove_node(self, model_id: int) -> None: + + def update_node(self, model_id: int, parent_id: int, node_attr: "NodeAttr" = None) -> None: node = self._model_node_map.get(model_id, None) - for child in node.children: - child.parent = None - if node.parent is not None: - node.parent.remove_child(node) - - del self._model_node_map[model_id] - del self._node_model_map[node] - - def update_node(self, model_id: int, parent_id: int, node: "StateNode") -> None: - # Replace node if required - existing_node = self._model_node_map.get(model_id, None) - if existing_node is not None: - self._remove_node(model_id) - - self._model_node_map[model_id] = node - self._node_model_map[node] = model_id - parent_node = self._model_node_map.get(parent_id, None) - if parent_node is not None: - parent_node.add_child(node) - -_id_counter = 0 -class StateNode: - def __init__(self) -> None: - self._id = self.__class__.gen_id() - self._parent = None - self._children = [] + if node is None: + node = StateNode() - def add_child(self, child: "StateNode") -> None: - child._parent = self - self._children.append(child) + self._model_node_map[model_id] = node + self._node_model_map[node] = model_id - def remove_child(self, child: "StateNode") -> None: - child._parent = None - self._children.remove(child) + parent_node = self._model_node_map.get(parent_id, None) + if parent_node is not None: + parent_node.add_child(node) - @property - def children(self): - return self._children + if node_attr is not None: + if isinstance(node_attr, InputAttr): + assert node.input is None + node.input = node_attr + elif isinstance(node_attr, OutputAttr): + assert node.output is None + node.output = node_attr + else: + raise ValueError(f"Unexpected node attr: {node_attr}") - @property - def parent(self): - return self._parent - @parent.setter - def parent(self, value): - self._parent = value +@dataclass +class StateNode: + identifier: int = field(default_factory=count().__next__) + parent: Optional["StateNode"] = None + children: list["StateNode"] = field(default_factory=list) + input: Optional["InputAttr"] = None + output: Optional["OutputAttr"] = None + + def add_child(self, child: "StateNode") -> None: + child.parent = self + self.children.append(child) - @classmethod - def gen_id(cls): - global _id_counter - _id = _id_counter - _id_counter += 1 - return _id + def remove_child(self, child: "StateNode") -> None: + child.parent = None + self.children.remove(child) def __repr__(self): - return self.__str__() + return f"{self.identifier}:{'' if self.input is None else repr(self.input)}:{'' if self.output is None else repr(self.output)}" + + def __hash__(self): + return hash(self.identifier) def visualize_text(state_builder: StateHandler, node: StateNode) -> None: - def visit(node: StateNode, buffer=[]): - if node.parent is not None: - visit(node._parent) - if isinstance(node, TextOutput): - print(node._value, end='') + def visit(visitor: StateNode): + if visitor.parent is not None: + visit(visitor.parent) + + if visitor.output is not None and isinstance(visitor.output, OutputAttr): + print(visitor.output._value, end='') + visit(node) def visualize(state_builder: StateHandler, node: StateNode) -> None: from anytree import Node, RenderTree - def visit(node: StateNode, viz_parent=None): + def visit(visitor: StateNode, viz_parent=None): nonlocal state_builder if viz_parent is None: - viz_node = Node(f"{state_builder._node_model_map[node]}:{node}") + viz_node = Node(f"{state_builder._node_model_map[visitor]}:{repr(visitor)}") else: - viz_node = Node(f"{state_builder._node_model_map[node]}:{node}", parent=viz_parent) + viz_node = Node(f"{state_builder._node_model_map[visitor]}:{repr(visitor)}", parent=viz_parent) - for child in node.children: + for child in visitor.children: visit(child, viz_node) return viz_node viz_root = visit(node) @@ -104,83 +94,99 @@ def visit(node: StateNode, viz_parent=None): print(tree_str) -class InputNode(StateNode): - def __init__(self) -> None: - super().__init__() +class NodeAttr: + pass -class OutputNode(StateNode): +class InputAttr(NodeAttr): def __init__(self) -> None: super().__init__() -class Tracker(StateNode): - def __init__(self): +class OutputAttr(NodeAttr): + def __init__(self) -> None: super().__init__() - def __str__(self): - return f"{self._id}:Tracker" - -class StatelessGuidanceInput(InputNode): +class StatelessGuidanceInput(InputAttr): def __init__(self, value: Any): self._value = value super().__init__() + def __repr__(self): + return f"{self.__class__.__name__}:{self._value}" + def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{self._value}" + return str(self._value) -class StatefulGuidanceInput(InputNode): +class StatefulGuidanceInput(InputAttr): def __init__(self, value: Any): self._value = value super().__init__() + def __repr__(self): + return f"{self.__class__.__name__}:{self._value}" + def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{self._value}" - + return str(self._value) -class LiteralInput(InputNode): + +class LiteralInput(InputAttr): def __init__(self, value: str): self._value = value super().__init__() + def __repr__(self): + return f"{self.__class__.__name__}:{repr(self._value)}" + def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" + return self._value -class TextOutput(OutputNode): +class TextOutput(OutputAttr): def __init__(self, value: str): self._value = value super().__init__() + def __repr__(self): + return f"{self.__class__.__name__}:{repr(self._value)}" + def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" + return self._value -class EmbeddedInput(InputNode): +class EmbeddedInput(InputAttr): def __init__(self, value: str): self._value = value super().__init__() - def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" + def __repr__(self): + return f"{self.__class__.__name__}:{repr(self._value)}" + def __str__(self): + return self._value -class RoleOpenerInput(InputNode): +class RoleOpenerInput(InputAttr): def __init__(self, value: str): self._value = value super().__init__() + def __repr__(self): + return f"{self.__class__.__name__}:{repr(self._value)}" + def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" + return self._value -class RoleCloserInput(InputNode): +class RoleCloserInput(InputAttr): def __init__(self, value: str): self._value = value super().__init__() + def __repr__(self): + return f"{self.__class__.__name__}:{repr(self._value)}" + def __str__(self): - return f"{self._id}:{self.__class__.__name__}:{repr(self._value)}" + return self._value diff --git a/notebooks/unstable/State Debugging.ipynb b/notebooks/unstable/State Debugging.ipynb index 1e05a05d2..84cc76ca0 100644 --- a/notebooks/unstable/State Debugging.ipynb +++ b/notebooks/unstable/State Debugging.ipynb @@ -3,27 +3,13 @@ { "cell_type": "code", "id": "1ec02432-a44d-4fdb-b44c-b153529fc03d", - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-26T21:31:55.029427Z", - "start_time": "2024-09-26T21:31:53.440050Z" - } - }, + "metadata": {}, "source": [ "from guidance.models import Transformers\n", "from guidance import gen, user, system" ], - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/samueljenkins/dev/guidance-dev/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n", - " warnings.warn(\n" - ] - } - ], - "execution_count": 1 + "outputs": [], + "execution_count": null }, { "cell_type": "code", @@ -45,98 +31,43 @@ "# with user():\n", "# m4 = m3 + \"The sun is rising \" + gen(name='sentence_suffix', max_tokens=3)" ], - "execution_count": 2, - "outputs": [] + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "id": "b5d6e974-bc52-4bbd-a8d4-69d681c33072", - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-26T21:31:56.819858Z", - "start_time": "2024-09-26T21:31:56.779818Z" - } - }, + "id": "5a5d668a11bda28f", + "metadata": {}, "source": [ "from guidance.state import visualize, visualize_text\n", "\n", "visualize(m0._state_handler, m0._state_handler._model_node_map[0])" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0:0:Tracker\n", - "└── 1:2:RoleOpenerInput:'system'\n", - " └── 2:4:StatefulGuidanceInput:{{G|5074217616|G}}\n", - " └── 3:6:LiteralInput:'<|im_start|>system\\n'\n", - " └── 4:15:LiteralInput:'You are responsible for autocompleting a sentence.'\n", - " └── 8:17:TextOutput:'You are responsible for autocompleting a sentence.'\n", - " └── 9:19:RoleCloserInput:'system'\n", - " └── 10:21:StatefulGuidanceInput:{{G|5096533584|G}}\n", - " └── 11:23:LiteralInput:'<|im_end|>\\n'\n", - " └── 12:26:RoleOpenerInput:'user'\n", - " └── 13:28:StatefulGuidanceInput:{{G|5236675744|G}}\n", - " └── 14:30:LiteralInput:'<|im_start|>user\\n'\n", - " └── 15:39:LiteralInput:'Roses are red and '\n", - " └── 19:41:TextOutput:'Roses are red and '\n", - " └── 20:43:StatelessGuidanceInput:{{G|5074674128|G}}\n", - " └── 21:45:LiteralInput:'you'\n", - " └── 22:47:TextOutput:'you'\n" - ] - } - ], - "execution_count": 3 + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "id": "d4070d52b59fad", - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-26T21:31:57.874141Z", - "start_time": "2024-09-26T21:31:57.871821Z" - } - }, + "id": "120427693c64ef1f", + "metadata": {}, "source": [ - "visualize_text(m0._state_handler, m0._state_handler._model_node_map[22])" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "You are responsible for autocompleting a sentence.Roses are red and you" - ] - } + "from guidance.state import visualize, visualize_text\n", + "\n", + "visualize_text(\n", + " m0._state_handler,\n", + " m0._state_handler._model_node_map[17]\n", + ")" ], - "execution_count": 4 + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "id": "d70ed049", - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-26T21:31:58.936929Z", - "start_time": "2024-09-26T21:31:58.933671Z" - } - }, - "source": [ - "m0._state_handler._model_node_map[3]" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "6:LiteralInput:'<|im_start|>system\\n'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 5 + "id": "cbbbe84572efd275", + "metadata": {}, + "source": "print(str(m2))", + "outputs": [], + "execution_count": null } ], "metadata": { @@ -155,7 +86,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.5" + "version": "3.9.6" } }, "nbformat": 4, diff --git a/setup.py b/setup.py index 72c23d468..7ab61e72a 100644 --- a/setup.py +++ b/setup.py @@ -70,6 +70,7 @@ "types-regex", "types-requests", "types-jsonschema", + "anytree", ] bench_requires = [ "pandas", diff --git a/tests/unit/test_model.py b/tests/unit/test_model.py index b95f31e8d..5b69bda64 100644 --- a/tests/unit/test_model.py +++ b/tests/unit/test_model.py @@ -29,6 +29,7 @@ def test_state_handler(): m1 = m0 + "You are responsible for autocompleting a sentence." with user(): m2 = m1 + "Roses are red and " + gen(name="suffix", regex='[A-Za-z]{2,5}', max_tokens=5) + # print(visualize_text(m0._state_handler, m0._state_handler._model_node_map[0])) print(visualize(m0._state_handler, m0._state_handler._model_node_map[0])) assert m2['suffix'] is not None From e6c84202e46efe8096a31310c723359b3da159da Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Thu, 26 Sep 2024 23:48:17 -0700 Subject: [PATCH 004/133] Clean-up of data classes for trace. --- guidance/models/_model.py | 286 +++++++++++------------ guidance/state/__init__.py | 173 +++++++------- notebooks/unstable/State Debugging.ipynb | 30 ++- tests/unit/test_model.py | 2 +- 4 files changed, 241 insertions(+), 250 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 527fdda2c..3446da0cc 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -15,7 +15,7 @@ import numpy as np -from ..state import RoleCloserInput, RoleOpenerInput, StateHandler, LiteralInput, EmbeddedInput, StatefulGuidanceInput, StatelessGuidanceInput, TextOutput +from ..state import RoleCloserInput, RoleOpenerInput, ModelTraceHandler, LiteralInput, EmbeddedInput, StatefulGuidanceInput, StatelessGuidanceInput, TextOutput try: from IPython.display import clear_output, display, HTML @@ -68,7 +68,7 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False): self.compute_log_probs = compute_log_probs self.metrics = GuidanceEngineMetrics() - self.state_handler = StateHandler() + self.trace_handler = ModelTraceHandler() def get_chat_template(self): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? return self.tokenizer.chat_template() # Instantiate the class before returning to client for now @@ -208,7 +208,6 @@ class Model: close_blocks: Dict["ContextBlock", None] = {} # track what context block is about to close _grammar_only = 0 # a flag that tracks when we are forced to be executing only compiled grammars (like when we are inside a select) - _throttle_refresh = 0 # a flag that tracks when we can throttle our display since we know future display calls are going to happen def __init__(self, engine, echo=True, parent_id=None, **kwargs): """Build a new model object that represents a model in a given state. @@ -247,7 +246,7 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self._variables_log_probs = {} # these are the state variables stored with the model self._cache_state = {} # mutable caching state used to save computation self._state = "" # the current bytes that represent the state of the model - self._state_handler = engine.state_handler # builds state for models + self._trace_handler = engine.trace_handler # builds state for models self._event_queue = None # TODO: these are for streaming results in code, but that needs implemented self._event_parent = None self._last_display = 0 # used to track the last display call to enable throttling @@ -255,7 +254,7 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self._id = self.__class__.gen_id() # model id needed for tracking state self._parent_id = parent_id - self._state_handler.update_node(self._id, self._parent_id, None) + self._trace_handler.update_node(self._id, self._parent_id, None) @classmethod def gen_id(cls): @@ -339,10 +338,10 @@ def copy(self): # otherwise if the current event que has an event parent then that is also our parent new_lm._event_parent = self._event_parent - new_lm._state_handler = self._state_handler + new_lm._trace_handler = self._trace_handler new_lm._id = self.__class__.gen_id() new_lm._parent_id = self._id - self._state_handler.update_node(new_lm._id, new_lm._parent_id, None) + self._trace_handler.update_node(new_lm._id, new_lm._parent_id, None) return new_lm @@ -354,41 +353,34 @@ def _inplace_append(self, value, force_silent=False): Parameters ---------- - value : bytes + value : bytes | str The bytes we should append to our current state. """ # update the byte state - self._state += str(value) # TODO: make _state to be bytes not a string + v = value + if not isinstance(v, str): + v = str(value) + self._state += v # see if we should update the display if not force_silent: self._update_display() # this is for programmatic streaming among other things - if Model._throttle_refresh > 0: - curr_time = time.time() - if curr_time - self._last_event_stream >= self.max_display_rate: - self._last_event_stream = curr_time - self._send_to_event_queue(self) - else: - self._send_to_event_queue(self) + self._send_to_event_queue(self) + def _update_display(self, throttle=True): + # TODO(nopdive): Remove throttle keyword as no longer in use. if self.echo: - if Model._throttle_refresh > 0: - curr_time = time.time() - if throttle and curr_time - self._last_display < self.max_display_rate: - return # we are throttling the update - else: - self._last_display = curr_time - if ipython_is_imported: clear_output(wait=True) display(HTML(self._html())) else: pprint(self._state) + def reset(self, clear_variables=True): """This resets the state of the model object. @@ -397,16 +389,17 @@ def reset(self, clear_variables=True): clear_variables : bool If we should clear all the model object's variables in addition to reseting the byte state. """ + # TODO(nopdive): This violates the immutability assumption on model class for users. Remove on confirmation. + self._state = self._state[:0] if clear_variables: self._variables = {} self._variables_log_probs = {} return self - + # NOTE(nopdive): Intentionally private, consider this friend scoped. Users should never be interacting with this method directly. def _add_role_opener(self, role_name, **kwargs): lm = self - # self._state_handler.add_node(lm._id, lm._parent_id, RoleOpener(role_name)) # TODO [HN]: Temporary change while I instrument chat_template in transformers only. # Eventually have all models use chat_template. @@ -466,124 +459,121 @@ def __add__(self, value): # (we need to do this since Model objects are immutable) lm = self.copy() - # inside this context we are free to drop display calls that come too close together - with throttle_refresh(): - - # find what new blocks need to be applied - enter_blocks = [] - for context in Model.open_blocks: - if context not in lm.opened_blocks: - enter_blocks.append(context) - - # mark this so we don't re-add when computing the opener or closer (even though we don't know the close text yet) - lm.opened_blocks[context] = (0, "") - - exit_blocks = [] - for context in Model.close_blocks: - if context not in lm.closed_blocks: - exit_blocks.append(context) - lm.closed_blocks[context] = (0, "") - - - # find what old blocks need to be removed - old_blocks = [] - for context in list(reversed(lm.opened_blocks)): - if context not in Model.open_blocks and context in lm.opened_blocks: - old_blocks.append((lm.opened_blocks[context], context)) - - # delete this so we don't re-close when computing the opener or closer - del lm.opened_blocks[context] - - # close any newly closed contexts - for (pos, close_text), context in old_blocks: - if context.name is not None: - lm._variables[context.name] = format_pattern.sub( - "", lm._state[pos:] - ) - # TODO(nopdive): Consider removing this - # lm = lm + context.closer - - # apply any newly closed contexts (new from this object's perspective) - for context in exit_blocks: - self._state_handler.update_node(lm._id, lm._parent_id, RoleCloserInput(context.name)) - lm = lm + context.closer - lm = lm.copy() - - # apply any newly opened contexts (new from this object's perspective) - for context in enter_blocks: - self._state_handler.update_node(lm._id, lm._parent_id, RoleOpenerInput(context.name)) - lm = lm + context.opener - lm = lm.copy() - - with grammar_only(): - tmp = lm + context.closer - close_text = tmp._state[len(lm._state):] # get the new state added by calling the closer - lm.opened_blocks[context] = (len(lm._state), close_text) - - # clear out names that we override - if context.name is not None: - if context.name in lm._variables: - del lm._variables[context.name] - if context.name in lm._variables_log_probs: - del lm._variables_log_probs[context.name] - - # wrap raw string values - if isinstance(value, str): - is_id = False - parts = re.split(_tag_pattern, value) - - # we have no embedded objects - if len(parts) == 1: - self._state_handler.update_node(lm._id, lm._parent_id, LiteralInput(value)) - - lm._inplace_append(value) - out = lm - - self._state_handler.update_node(out._id, out._parent_id, TextOutput(value)) - # if we have embedded objects we have to convert the string to a grammar tree - else: - self._state_handler.update_node(lm._id, lm._parent_id, EmbeddedInput(value)) - - partial_grammar = _null_grammar - lm.suffix = "" - for i, part in enumerate(parts): - if i < len(parts) - 1: - lm.suffix = parts[i + 1] - if is_id: - call = _call_pool[part] - if isinstance(call, GrammarFunction): - partial_grammar += _call_pool[part] - else: - lm += partial_grammar - lm = _call_pool[part](lm) - partial_grammar = _null_grammar - elif part != "": - partial_grammar += string(part) - is_id = not is_id - - out = lm + partial_grammar - - # if we find a null value we do nothing - elif isinstance(value, Null): + # find what new blocks need to be applied + enter_blocks = [] + for context in Model.open_blocks: + if context not in lm.opened_blocks: + enter_blocks.append(context) + + # mark this so we don't re-add when computing the opener or closer (even though we don't know the close text yet) + lm.opened_blocks[context] = (0, "") + + exit_blocks = [] + for context in Model.close_blocks: + if context not in lm.closed_blocks: + exit_blocks.append(context) + lm.closed_blocks[context] = (0, "") + + + # find what old blocks need to be removed + old_blocks = [] + for context in list(reversed(lm.opened_blocks)): + if context not in Model.open_blocks and context in lm.opened_blocks: + old_blocks.append((lm.opened_blocks[context], context)) + + # delete this so we don't re-close when computing the opener or closer + del lm.opened_blocks[context] + + # close any newly closed contexts + for (pos, close_text), context in old_blocks: + if context.name is not None: + lm._variables[context.name] = format_pattern.sub( + "", lm._state[pos:] + ) + # TODO(nopdive): Consider removing this + # lm = lm + context.closer + + # apply any newly closed contexts (new from this object's perspective) + for context in exit_blocks: + self._trace_handler.update_node(lm._id, lm._parent_id, RoleCloserInput(context.name)) + lm = lm + context.closer + lm = lm.copy() + + # apply any newly opened contexts (new from this object's perspective) + for context in enter_blocks: + self._trace_handler.update_node(lm._id, lm._parent_id, RoleOpenerInput(context.name)) + lm = lm + context.opener + lm = lm.copy() + + with grammar_only(): + tmp = lm + context.closer + close_text = tmp._state[len(lm._state):] # get the new state added by calling the closer + lm.opened_blocks[context] = (len(lm._state), close_text) + + # clear out names that we override + if context.name is not None: + if context.name in lm._variables: + del lm._variables[context.name] + if context.name in lm._variables_log_probs: + del lm._variables_log_probs[context.name] + + # wrap raw string values + if isinstance(value, str): + is_id = False + parts = re.split(_tag_pattern, value) + + # we have no embedded objects + if len(parts) == 1: + self._trace_handler.update_node(lm._id, lm._parent_id, LiteralInput(value)) + + lm._inplace_append(value) out = lm - # run stateless functions (grammar nodes) - elif isinstance(value, GrammarFunction): - self._state_handler.update_node(lm._id, lm._parent_id, StatelessGuidanceInput(value)) - out = lm._run_stateless(value) - - # run stateful functions + self._trace_handler.update_node(out._id, out._parent_id, TextOutput(value)) + # if we have embedded objects we have to convert the string to a grammar tree else: - self._state_handler.update_node(lm._id, lm._parent_id, StatefulGuidanceInput(value)) - out = value(lm) - if out is None: - raise Exception( - f"A guidance function returned `None`, not a model object! Did you forget to return the new lm at the end of your function?" - ) - if not isinstance(out, Model): - raise Exception( - f"A guidance function did not return a model object! Did you try to add a function to a model without calling the function? For example `model + guidance_function()` is correct, while `model + guidance_function` will cause this error." - ) + self._trace_handler.update_node(lm._id, lm._parent_id, EmbeddedInput(value)) + + partial_grammar = _null_grammar + lm.suffix = "" + for i, part in enumerate(parts): + if i < len(parts) - 1: + lm.suffix = parts[i + 1] + if is_id: + call = _call_pool[part] + if isinstance(call, GrammarFunction): + partial_grammar += _call_pool[part] + else: + lm += partial_grammar + lm = _call_pool[part](lm) + partial_grammar = _null_grammar + elif part != "": + partial_grammar += string(part) + is_id = not is_id + + out = lm + partial_grammar + + # if we find a null value we do nothing + elif isinstance(value, Null): + out = lm + + # run stateless functions (grammar nodes) + elif isinstance(value, GrammarFunction): + self._trace_handler.update_node(lm._id, lm._parent_id, StatelessGuidanceInput(value)) + out = lm._run_stateless(value) + + # run stateful functions + else: + self._trace_handler.update_node(lm._id, lm._parent_id, StatefulGuidanceInput(value)) + out = value(lm) + if out is None: + raise Exception( + f"A guidance function returned `None`, not a model object! Did you forget to return the new lm at the end of your function?" + ) + if not isinstance(out, Model): + raise Exception( + f"A guidance function did not return a model object! Did you try to add a function to a model without calling the function? For example `model + guidance_function()` is correct, while `model + guidance_function` will cause this error." + ) return out @@ -797,10 +787,7 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): # lm += f"<||_html:_||>" pass - # TODO(nopdive): Remove old code on confirmation lm += new_text - # lm._inplace_append(new_text) - # self._state_handler.add_node(lm._id, lm._parent_id, TextOutput(new_text)) if chunk.is_generated: # TODO(viz) @@ -983,19 +970,6 @@ def grammar_only(): return GrammarOnly() -class ThrottleRefresh: - def __enter__(self): - Model._throttle_refresh += 1 - - def __exit__(self, exc_type, exc_value, traceback): - Model._throttle_refresh -= 1 - - -def throttle_refresh(): - """Returns a context manager that allows the print statement to drop display calls above the throttle rate.""" - return ThrottleRefresh() - - class ConstraintException(Exception): def __init__(self, *args, **kwargs): self.prompt = kwargs.pop("prompt", None) diff --git a/guidance/state/__init__.py b/guidance/state/__init__.py index c4eb07f85..2b036b3b2 100644 --- a/guidance/state/__init__.py +++ b/guidance/state/__init__.py @@ -5,26 +5,60 @@ """ # TODO(nopdive): Deal with weak referencing for GC -from dataclasses import dataclass, field +from dataclasses import dataclass, field, fields from itertools import count from typing import Dict, Any, Optional import weakref -class StateHandler: - def __init__(self) -> None: - self._model_node_map: Dict[int, StateNode] = {} - self._node_model_map: Dict[StateNode, int] = {} +def _dataclass_repr(obj, target_fields=None): + if target_fields is None: + records = ( + f'{field.name}={getattr(obj, field.name)!r}' + for field in fields(obj) + if getattr(obj, field.name) != field.default + ) + else: + records = ( + f'{field.name}={getattr(obj, field.name)!r}' + for field in fields(obj) + if getattr(obj, field.name) != field.default and field.name in target_fields + ) + out = f'{type(obj).__name__}({", ".join(records)})' + return out + + +def _dataclass_str(obj, target_fields=None): + if target_fields is None: + records = ( + f'{getattr(obj, field.name)!s}' + for field in fields(obj) + if getattr(obj, field.name) != field.default + ) + else: + records = ( + f'{getattr(obj, field.name)!s}' + for field in fields(obj) + if getattr(obj, field.name) != field.default and field.name in target_fields + ) + out = ", ".join(records) + return out + + +@dataclass +class ModelTraceHandler: + model_node_map: Dict[int, "TraceNode"] = field(default_factory=dict) + node_model_map: Dict["TraceNode", int] = field(default_factory=dict) def update_node(self, model_id: int, parent_id: int, node_attr: "NodeAttr" = None) -> None: - node = self._model_node_map.get(model_id, None) + node = self.model_node_map.get(model_id, None) if node is None: - node = StateNode() + node = TraceNode() - self._model_node_map[model_id] = node - self._node_model_map[node] = model_id + self.model_node_map[model_id] = node + self.node_model_map[node] = model_id - parent_node = self._model_node_map.get(parent_id, None) + parent_node = self.model_node_map.get(parent_id, None) if parent_node is not None: parent_node.add_child(node) @@ -40,49 +74,49 @@ def update_node(self, model_id: int, parent_id: int, node_attr: "NodeAttr" = Non @dataclass -class StateNode: +class TraceNode: identifier: int = field(default_factory=count().__next__) - parent: Optional["StateNode"] = None - children: list["StateNode"] = field(default_factory=list) + parent: Optional["TraceNode"] = None + children: list["TraceNode"] = field(default_factory=list) input: Optional["InputAttr"] = None output: Optional["OutputAttr"] = None - def add_child(self, child: "StateNode") -> None: + def add_child(self, child: "TraceNode") -> None: child.parent = self self.children.append(child) - def remove_child(self, child: "StateNode") -> None: + def remove_child(self, child: "TraceNode") -> None: child.parent = None self.children.remove(child) def __repr__(self): - return f"{self.identifier}:{'' if self.input is None else repr(self.input)}:{'' if self.output is None else repr(self.output)}" + return _dataclass_repr(self, ["identifier", "input", "output"]) def __hash__(self): return hash(self.identifier) -def visualize_text(state_builder: StateHandler, node: StateNode) -> None: - def visit(visitor: StateNode): +def visualize_text(state_builder: ModelTraceHandler, node: TraceNode) -> None: + def visit(visitor: TraceNode): if visitor.parent is not None: visit(visitor.parent) if visitor.output is not None and isinstance(visitor.output, OutputAttr): - print(visitor.output._value, end='') + print(visitor.output, end='') visit(node) -def visualize(state_builder: StateHandler, node: StateNode) -> None: +def visualize(state_builder: ModelTraceHandler, node: TraceNode) -> None: from anytree import Node, RenderTree - def visit(visitor: StateNode, viz_parent=None): + def visit(visitor: TraceNode, viz_parent=None): nonlocal state_builder if viz_parent is None: - viz_node = Node(f"{state_builder._node_model_map[visitor]}:{repr(visitor)}") + viz_node = Node(f"{state_builder.node_model_map[visitor]}:{visitor !r}") else: - viz_node = Node(f"{state_builder._node_model_map[visitor]}:{repr(visitor)}", parent=viz_parent) + viz_node = Node(f"{state_builder.node_model_map[visitor]}:{visitor !r}", parent=viz_parent) for child in visitor.children: visit(child, viz_node) @@ -94,99 +128,58 @@ def visit(visitor: StateNode, viz_parent=None): print(tree_str) +@dataclass(frozen=True) class NodeAttr: - pass + def __repr__(self): + return _dataclass_repr(self) + + def __str__(self): + return _dataclass_str(self) +@dataclass(frozen=True) class InputAttr(NodeAttr): - def __init__(self) -> None: - super().__init__() + pass +@dataclass(frozen=True) class OutputAttr(NodeAttr): - def __init__(self) -> None: - super().__init__() + pass +@dataclass(frozen=True) class StatelessGuidanceInput(InputAttr): - def __init__(self, value: Any): - self._value = value - super().__init__() - - def __repr__(self): - return f"{self.__class__.__name__}:{self._value}" - - def __str__(self): - return str(self._value) + value: Any +@dataclass(frozen=True) class StatefulGuidanceInput(InputAttr): - def __init__(self, value: Any): - self._value = value - super().__init__() + value: Any def __repr__(self): - return f"{self.__class__.__name__}:{self._value}" - - def __str__(self): - return str(self._value) + return f"{self.__class__.__name__}({repr(self.value)})" +@dataclass(frozen=True) class LiteralInput(InputAttr): - def __init__(self, value: str): - self._value = value - super().__init__() - - def __repr__(self): - return f"{self.__class__.__name__}:{repr(self._value)}" - - def __str__(self): - return self._value - - -class TextOutput(OutputAttr): - def __init__(self, value: str): - self._value = value - super().__init__() - - def __repr__(self): - return f"{self.__class__.__name__}:{repr(self._value)}" - - def __str__(self): - return self._value + value: str +@dataclass(frozen=True) class EmbeddedInput(InputAttr): - def __init__(self, value: str): - self._value = value - super().__init__() - - def __repr__(self): - return f"{self.__class__.__name__}:{repr(self._value)}" + value: str - def __str__(self): - return self._value +@dataclass(frozen=True) class RoleOpenerInput(InputAttr): - def __init__(self, value: str): - self._value = value - super().__init__() - - def __repr__(self): - return f"{self.__class__.__name__}:{repr(self._value)}" - - def __str__(self): - return self._value + value: str +@dataclass(frozen=True) class RoleCloserInput(InputAttr): - def __init__(self, value: str): - self._value = value - super().__init__() + value: str - def __repr__(self): - return f"{self.__class__.__name__}:{repr(self._value)}" - - def __str__(self): - return self._value +@dataclass(frozen=True) +class TextOutput(OutputAttr): + value: str diff --git a/notebooks/unstable/State Debugging.ipynb b/notebooks/unstable/State Debugging.ipynb index 84cc76ca0..637955049 100644 --- a/notebooks/unstable/State Debugging.ipynb +++ b/notebooks/unstable/State Debugging.ipynb @@ -41,7 +41,7 @@ "source": [ "from guidance.state import visualize, visualize_text\n", "\n", - "visualize(m0._state_handler, m0._state_handler._model_node_map[0])" + "visualize(m0._trace_handler, m0._trace_handler.model_node_map[0])" ], "outputs": [], "execution_count": null @@ -54,8 +54,8 @@ "from guidance.state import visualize, visualize_text\n", "\n", "visualize_text(\n", - " m0._state_handler,\n", - " m0._state_handler._model_node_map[17]\n", + " m0._trace_handler,\n", + " m0._trace_handler.model_node_map[17]\n", ")" ], "outputs": [], @@ -68,6 +68,30 @@ "source": "print(str(m2))", "outputs": [], "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": "print(m2._state)\n", + "id": "122ce6b1eabe6166", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": "", + "id": "e5efe7e2bdf97b8f", + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "code", + "source": "", + "id": "bf3c03805957a631", + "outputs": [], + "execution_count": null } ], "metadata": { diff --git a/tests/unit/test_model.py b/tests/unit/test_model.py index 5b69bda64..b40a65443 100644 --- a/tests/unit/test_model.py +++ b/tests/unit/test_model.py @@ -30,7 +30,7 @@ def test_state_handler(): with user(): m2 = m1 + "Roses are red and " + gen(name="suffix", regex='[A-Za-z]{2,5}', max_tokens=5) # print(visualize_text(m0._state_handler, m0._state_handler._model_node_map[0])) - print(visualize(m0._state_handler, m0._state_handler._model_node_map[0])) + print(visualize(m0._trace_handler, m0._trace_handler._model_node_map[0])) assert m2['suffix'] is not None From 6429d97f0ac66633496a2e7ed31af24ade47a5dc Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Fri, 27 Sep 2024 14:30:51 -0700 Subject: [PATCH 005/133] Various trace updates. Trace can now handle capture groups. State module moved to trace module. --- guidance/_grammar.py | 6 +- guidance/_utils.py | 34 +++++ guidance/models/_model.py | 68 ++++++--- guidance/state/__init__.py | 185 ----------------------- guidance/trace/__init__.py | 157 +++++++++++++++++++ notebooks/unstable/State Debugging.ipynb | 149 +++++++++++++----- 6 files changed, 354 insertions(+), 245 deletions(-) delete mode 100644 guidance/state/__init__.py create mode 100644 guidance/trace/__init__.py diff --git a/guidance/_grammar.py b/guidance/_grammar.py index 85a94b227..d690cf33f 100644 --- a/guidance/_grammar.py +++ b/guidance/_grammar.py @@ -14,7 +14,7 @@ class StatefulException(Exception): - """This is raised when we try and use the state of a grammar object like it was a live model. + """This is raised when we try and use the trace of a grammar object like it was a live model. Note that eventually it would be nice to support stateful parser/grammar constructs directly, but such "parser combinators" cannot be run effciently in Python. So we use a traditional parser and @@ -163,7 +163,7 @@ def __radd__(self, value): return value.__add__(self) def __getitem__(self, value): - raise StatefulException("GrammarFunctions can't access state!") + raise StatefulException("GrammarFunctions can't access trace!") def match( self, @@ -414,7 +414,7 @@ def replace_model_variables(grammar, model, allowed_vars=None): def unreplace_model_variables(replacements): - """This restores a grammar back to its original state, ready for another execution.""" + """This restores a grammar back to its original trace, ready for another execution.""" for grammar, i, orig_value in replacements: grammar.values[i] = orig_value diff --git a/guidance/_utils.py b/guidance/_utils.py index 093873da9..b225016c2 100644 --- a/guidance/_utils.py +++ b/guidance/_utils.py @@ -232,3 +232,37 @@ def softmax(array: np.ndarray, axis: int = -1) -> np.ndarray: array_maxs = np.amax(array, axis=axis, keepdims=True) exp_x_shifted = np.exp(array - array_maxs) return exp_x_shifted / np.sum(exp_x_shifted, axis=axis, keepdims=True) + + +def pydantic_no_default_repr(obj, target_fields=None): + if target_fields is None: + records = ( + f'{getattr(obj, name)!r}' + for name, field in obj.model_fields.items() + if getattr(obj, name) != field.default + ) + else: + records = ( + f'{getattr(obj, name)!r}' + for name, field in obj.model_fields.items() + if getattr(obj, name) != field.default and name in target_fields + ) + out = f'{type(obj).__name__}:{":".join(records)}' + return out + + +def pydantic_no_default_str(obj, target_fields=None): + if target_fields is None: + records = ( + f'{getattr(obj, name)!s}' + for name, field in obj.model_fields.items() + if getattr(obj, name) != field.default + ) + else: + records = ( + f'{getattr(obj, name)!s}' + for name, field in obj.model_fields.items() + if getattr(obj, name) != field.default and name in target_fields + ) + out = "\n".join(records) + return out diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 3446da0cc..3099174bf 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -15,7 +15,8 @@ import numpy as np -from ..state import RoleCloserInput, RoleOpenerInput, ModelTraceHandler, LiteralInput, EmbeddedInput, StatefulGuidanceInput, StatelessGuidanceInput, TextOutput +from ..trace import RoleCloserInput, RoleOpenerInput, TraceHandler, LiteralInput, EmbeddedInput, \ + StatefulGuidanceInput, StatelessGuidanceInput, TextOutput, CaptureOutput try: from IPython.display import clear_output, display, HTML @@ -67,8 +68,7 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False): self.tokenizer = tokenizer self.compute_log_probs = compute_log_probs self.metrics = GuidanceEngineMetrics() - - self.trace_handler = ModelTraceHandler() + self.trace_handler = TraceHandler() def get_chat_template(self): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? return self.tokenizer.chat_template() # Instantiate the class before returning to client for now @@ -106,7 +106,7 @@ def start(self, prompt, grammar, ensure_bos_token=True) -> TokenParser: prompt = bytes(prompt, encoding="utf8") elif isinstance(prompt, TokenParser): raise NotImplementedError( - "Still need to implement support for extending a full Parser state." + "Still need to implement support for extending a full Parser trace." ) else: raise Exception("The passed prompt is of an unknown type!") @@ -487,27 +487,29 @@ def __add__(self, value): # close any newly closed contexts for (pos, close_text), context in old_blocks: if context.name is not None: - lm._variables[context.name] = format_pattern.sub( - "", lm._state[pos:] + v = format_pattern.sub("", lm._state[pos:]) + lm._variables[context.name] = v + self._trace_handler.update_node( + lm._id, lm._parent_id, CaptureOutput(name=context.name, value=v) ) # TODO(nopdive): Consider removing this # lm = lm + context.closer # apply any newly closed contexts (new from this object's perspective) for context in exit_blocks: - self._trace_handler.update_node(lm._id, lm._parent_id, RoleCloserInput(context.name)) - lm = lm + context.closer + self._trace_handler.update_node(lm._id, lm._parent_id, RoleCloserInput(name=context.name)) + lm += context.closer lm = lm.copy() # apply any newly opened contexts (new from this object's perspective) for context in enter_blocks: - self._trace_handler.update_node(lm._id, lm._parent_id, RoleOpenerInput(context.name)) - lm = lm + context.opener + self._trace_handler.update_node(lm._id, lm._parent_id, RoleOpenerInput(name=context.name)) + lm += context.opener lm = lm.copy() with grammar_only(): tmp = lm + context.closer - close_text = tmp._state[len(lm._state):] # get the new state added by calling the closer + close_text = tmp._state[len(lm._state):] # get the new trace added by calling the closer lm.opened_blocks[context] = (len(lm._state), close_text) # clear out names that we override @@ -517,22 +519,30 @@ def __add__(self, value): if context.name in lm._variables_log_probs: del lm._variables_log_probs[context.name] - # wrap raw string values - if isinstance(value, str): + if isinstance(value, TextOutput): + lm._inplace_append(value.value) + out = lm + self._trace_handler.update_node(out._id, out._parent_id, value) + elif isinstance(value, CaptureOutput): + self._trace_handler.update_node(lm._id, lm._parent_id, value) + out = lm + elif isinstance(value, str): + # wrap raw string values + is_id = False parts = re.split(_tag_pattern, value) # we have no embedded objects if len(parts) == 1: - self._trace_handler.update_node(lm._id, lm._parent_id, LiteralInput(value)) + self._trace_handler.update_node(lm._id, lm._parent_id, LiteralInput(value=value)) lm._inplace_append(value) out = lm - self._trace_handler.update_node(out._id, out._parent_id, TextOutput(value)) + self._trace_handler.update_node(out._id, out._parent_id, TextOutput(value=value)) # if we have embedded objects we have to convert the string to a grammar tree else: - self._trace_handler.update_node(lm._id, lm._parent_id, EmbeddedInput(value)) + self._trace_handler.update_node(lm._id, lm._parent_id, EmbeddedInput(value=value)) partial_grammar = _null_grammar lm.suffix = "" @@ -559,12 +569,12 @@ def __add__(self, value): # run stateless functions (grammar nodes) elif isinstance(value, GrammarFunction): - self._trace_handler.update_node(lm._id, lm._parent_id, StatelessGuidanceInput(value)) + self._trace_handler.update_node(lm._id, lm._parent_id, StatelessGuidanceInput(value=value)) out = lm._run_stateless(value) # run stateful functions else: - self._trace_handler.update_node(lm._id, lm._parent_id, StatefulGuidanceInput(value)) + self._trace_handler.update_node(lm._id, lm._parent_id, StatefulGuidanceInput(value=value)) out = value(lm) if out is None: raise Exception( @@ -787,7 +797,12 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): # lm += f"<||_html:_||>" pass - lm += new_text + lm += TextOutput( + value=new_text, + is_generated=chunk.is_generated, + token_count=chunk.new_token_count, + prob=chunk.new_bytes_prob, + ) if chunk.is_generated: # TODO(viz) @@ -816,13 +831,20 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): if k not in lm or not isinstance(lm._variables[k], list): lm._variables[k] = [] + lm += CaptureOutput(name=k) if k not in lm._variables_log_probs or not isinstance(lm._variables_log_probs[k], list): lm._variables_log_probs[k] = [] - + lm._variables[k].append(inner_v) lm._variables_log_probs[k].append( chunk.capture_group_log_probs[k][i] ) + lm += CaptureOutput( + name=k, + value=inner_v, + is_append=True, + log_probs=lm._variables_log_probs[k][i], + ) # ...or standard assignment mode else: @@ -832,8 +854,14 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): v = v.decode("utf8") if isinstance(v, bytes) else v except UnicodeDecodeError: pass + lm._variables[k] = v lm._variables_log_probs[k] = chunk.capture_group_log_probs[k] + lm += CaptureOutput( + name=k, + value=v, + log_probs=chunk.capture_group_log_probs[k], + ) # if len(chunk.capture_groups) > 0: # for k in chunk.capture_groups: diff --git a/guidance/state/__init__.py b/guidance/state/__init__.py deleted file mode 100644 index 2b036b3b2..000000000 --- a/guidance/state/__init__.py +++ /dev/null @@ -1,185 +0,0 @@ -"""State of models, including state tree that represents a guidance trace within Python. - -The first implementation aims for simplicity. -Once benchmark figures are out, we'll figure out what to optimize. -""" -# TODO(nopdive): Deal with weak referencing for GC - -from dataclasses import dataclass, field, fields -from itertools import count -from typing import Dict, Any, Optional -import weakref - - -def _dataclass_repr(obj, target_fields=None): - if target_fields is None: - records = ( - f'{field.name}={getattr(obj, field.name)!r}' - for field in fields(obj) - if getattr(obj, field.name) != field.default - ) - else: - records = ( - f'{field.name}={getattr(obj, field.name)!r}' - for field in fields(obj) - if getattr(obj, field.name) != field.default and field.name in target_fields - ) - out = f'{type(obj).__name__}({", ".join(records)})' - return out - - -def _dataclass_str(obj, target_fields=None): - if target_fields is None: - records = ( - f'{getattr(obj, field.name)!s}' - for field in fields(obj) - if getattr(obj, field.name) != field.default - ) - else: - records = ( - f'{getattr(obj, field.name)!s}' - for field in fields(obj) - if getattr(obj, field.name) != field.default and field.name in target_fields - ) - out = ", ".join(records) - return out - - -@dataclass -class ModelTraceHandler: - model_node_map: Dict[int, "TraceNode"] = field(default_factory=dict) - node_model_map: Dict["TraceNode", int] = field(default_factory=dict) - - def update_node(self, model_id: int, parent_id: int, node_attr: "NodeAttr" = None) -> None: - node = self.model_node_map.get(model_id, None) - if node is None: - node = TraceNode() - - self.model_node_map[model_id] = node - self.node_model_map[node] = model_id - - parent_node = self.model_node_map.get(parent_id, None) - if parent_node is not None: - parent_node.add_child(node) - - if node_attr is not None: - if isinstance(node_attr, InputAttr): - assert node.input is None - node.input = node_attr - elif isinstance(node_attr, OutputAttr): - assert node.output is None - node.output = node_attr - else: - raise ValueError(f"Unexpected node attr: {node_attr}") - - -@dataclass -class TraceNode: - identifier: int = field(default_factory=count().__next__) - parent: Optional["TraceNode"] = None - children: list["TraceNode"] = field(default_factory=list) - input: Optional["InputAttr"] = None - output: Optional["OutputAttr"] = None - - def add_child(self, child: "TraceNode") -> None: - child.parent = self - self.children.append(child) - - def remove_child(self, child: "TraceNode") -> None: - child.parent = None - self.children.remove(child) - - def __repr__(self): - return _dataclass_repr(self, ["identifier", "input", "output"]) - - def __hash__(self): - return hash(self.identifier) - - -def visualize_text(state_builder: ModelTraceHandler, node: TraceNode) -> None: - def visit(visitor: TraceNode): - if visitor.parent is not None: - visit(visitor.parent) - - if visitor.output is not None and isinstance(visitor.output, OutputAttr): - print(visitor.output, end='') - - visit(node) - - -def visualize(state_builder: ModelTraceHandler, node: TraceNode) -> None: - from anytree import Node, RenderTree - - def visit(visitor: TraceNode, viz_parent=None): - nonlocal state_builder - - if viz_parent is None: - viz_node = Node(f"{state_builder.node_model_map[visitor]}:{visitor !r}") - else: - viz_node = Node(f"{state_builder.node_model_map[visitor]}:{visitor !r}", parent=viz_parent) - - for child in visitor.children: - visit(child, viz_node) - return viz_node - viz_root = visit(node) - - for pre, fill, node in RenderTree(viz_root): - tree_str = u"%s%s" % (pre, node.name) - print(tree_str) - - -@dataclass(frozen=True) -class NodeAttr: - def __repr__(self): - return _dataclass_repr(self) - - def __str__(self): - return _dataclass_str(self) - - -@dataclass(frozen=True) -class InputAttr(NodeAttr): - pass - - -@dataclass(frozen=True) -class OutputAttr(NodeAttr): - pass - - -@dataclass(frozen=True) -class StatelessGuidanceInput(InputAttr): - value: Any - - -@dataclass(frozen=True) -class StatefulGuidanceInput(InputAttr): - value: Any - - def __repr__(self): - return f"{self.__class__.__name__}({repr(self.value)})" - - -@dataclass(frozen=True) -class LiteralInput(InputAttr): - value: str - - -@dataclass(frozen=True) -class EmbeddedInput(InputAttr): - value: str - - -@dataclass(frozen=True) -class RoleOpenerInput(InputAttr): - value: str - - -@dataclass(frozen=True) -class RoleCloserInput(InputAttr): - value: str - - -@dataclass(frozen=True) -class TextOutput(OutputAttr): - value: str diff --git a/guidance/trace/__init__.py b/guidance/trace/__init__.py new file mode 100644 index 000000000..33be5b6eb --- /dev/null +++ b/guidance/trace/__init__.py @@ -0,0 +1,157 @@ +"""Trace tree of inputs & outputs generated from a guidance program. + +The first implementation aims for simplicity. +Once benchmark figures are out, we'll figure out what to optimize. +""" +# TODO(nopdive): Deal with weak referencing for GC + +from pydantic import BaseModel, Field +from itertools import count +from typing import Dict, Any, Optional +from guidance._utils import pydantic_no_default_repr, pydantic_no_default_str + + +class NodeAttr(BaseModel): + def __repr__(self): + return pydantic_no_default_repr(self) + + def __str__(self): + return pydantic_no_default_str(self) + + +class InputAttr(NodeAttr): + pass + + +class OutputAttr(NodeAttr): + pass + + +class StatelessGuidanceInput(InputAttr): + value: Any + + def __repr__(self): + return f"{self.__class__.__name__}({self.value})" + + +class StatefulGuidanceInput(InputAttr): + value: Any + + def __repr__(self): + return f"{self.__class__.__name__}({self.value})" + + +class LiteralInput(InputAttr): + value: str + + +class EmbeddedInput(InputAttr): + value: str + + +class RoleOpenerInput(InputAttr): + name: str + + +class RoleCloserInput(InputAttr): + name: str + + +class TextOutput(OutputAttr): + value: str + is_generated: bool = False + token_count: int = 0 + prob: float = 0.0 + + +class CaptureOutput(OutputAttr): + name: str + value: Optional[str] = None + is_append: bool = False + log_probs: float = 0.0 + + def __str__(self): + return f"{self.name}{'+=' if self.is_append else '='}{self.value.__str__()}" + + +class TraceNode(BaseModel): + identifier: int = Field(default_factory=count().__next__) + parent: Optional["TraceNode"] = None + children: list["TraceNode"] = [] + input: Optional[InputAttr] = None + output: Optional[OutputAttr] = None + + def add_child(self, child: "TraceNode") -> None: + child.parent = self + self.children.append(child) + + def remove_child(self, child: "TraceNode") -> None: + child.parent = None + self.children.remove(child) + + def __repr__(self): + return f"{self.identifier}:{self.input!r}:{self.output!r}" + + def __hash__(self): + return hash(self.identifier) + + +class TraceHandler(BaseModel): + id_node_map: Dict[int, "TraceNode"] = {} + node_id_map: Dict["TraceNode", int] = {} + + def update_node(self, identifier: int, parent_id: int, node_attr: "NodeAttr" = None) -> None: + node = self.id_node_map.get(identifier, None) + if node is None: + node = TraceNode() + + self.id_node_map[identifier] = node + self.node_id_map[node] = identifier + + parent_node = self.id_node_map.get(parent_id, None) + if parent_node is not None: + parent_node.add_child(node) + + if node_attr is not None: + if isinstance(node_attr, InputAttr): + assert node.input is None + node.input = node_attr + elif isinstance(node_attr, OutputAttr): + assert node.output is None + node.output = node_attr + else: + raise ValueError(f"Unexpected node attr: {node_attr}") + + +def visualize_text(state_builder: TraceHandler, node: TraceNode) -> None: + def visit(visitor: TraceNode): + if visitor.parent is not None: + visit(visitor.parent) + + if visitor.output is not None and isinstance(visitor.output, OutputAttr): + print(visitor.output, end='') + + visit(node) + + +def visualize(state_builder: TraceHandler, node: TraceNode) -> None: + from anytree import Node, RenderTree + + def visit(visitor: TraceNode, viz_parent=None): + nonlocal state_builder + + if viz_parent is None: + viz_node = Node(f"{state_builder.node_id_map[visitor]}:{visitor!r}") + else: + viz_node = Node(f"{state_builder.node_id_map[visitor]}:{visitor!r}", parent=viz_parent) + + for child in visitor.children: + visit(child, viz_node) + return viz_node + viz_root = visit(node) + + for pre, fill, node in RenderTree(viz_root): + tree_str = u"%s%s" % (pre, node.name) + print(tree_str) + + diff --git a/notebooks/unstable/State Debugging.ipynb b/notebooks/unstable/State Debugging.ipynb index 637955049..c899f0956 100644 --- a/notebooks/unstable/State Debugging.ipynb +++ b/notebooks/unstable/State Debugging.ipynb @@ -3,13 +3,27 @@ { "cell_type": "code", "id": "1ec02432-a44d-4fdb-b44c-b153529fc03d", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-27T21:14:42.017246Z", + "start_time": "2024-09-27T21:14:40.405816Z" + } + }, "source": [ "from guidance.models import Transformers\n", "from guidance import gen, user, system" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/samueljenkins/dev/guidance-dev/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n", + " warnings.warn(\n" + ] + } + ], + "execution_count": 1 }, { "cell_type": "code", @@ -20,7 +34,9 @@ "with system():\n", " m1 = m0 + \"You are responsible for autocompleting a sentence.\"\n", "with user():\n", - " m2 = m1 + \"Roses are red and \" + gen(name=\"suffix\", regex='[A-Za-z]{2,5}', max_tokens=5)\n", + " m2 = m1 + \"Roses are red and \" + gen(name=\"suffix\", regex=r'[\\w\\s]{15,20}', max_tokens=20)\n", + "# with user():\n", + "# m3 = m2 + \"\\nWhat can I do?\"\n", "\n", "# m1 = m0 + f\"Hi there {gen(name='name', max_tokens=10, regex='[A-Za-z]{3,5}')}\"\n", "# m2 = m0 + f\"You can't stop \" + gen(name='name', max_tokens=10, regex='[A-Za-z]{3,5}')\n", @@ -31,65 +47,124 @@ "# with user():\n", "# m4 = m3 + \"The sun is rising \" + gen(name='sentence_suffix', max_tokens=3)" ], - "outputs": [], - "execution_count": null + "execution_count": 2, + "outputs": [] }, { "cell_type": "code", "id": "5a5d668a11bda28f", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-27T21:14:43.448473Z", + "start_time": "2024-09-27T21:14:43.439539Z" + } + }, "source": [ - "from guidance.state import visualize, visualize_text\n", + "from guidance.trace import visualize, visualize_text\n", "\n", - "visualize(m0._trace_handler, m0._trace_handler.model_node_map[0])" + "visualize(m0._trace_handler, m0._trace_handler.id_node_map[0])" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0:0:None:None\n", + "└── 1:1:RoleOpenerInput:'system':None\n", + " └── 2:2:StatefulGuidanceInput({{G|4970396064|G}}):None\n", + " └── 3:3:LiteralInput:'<|im_start|>system\\n':TextOutput:'<|im_start|>system\\n'\n", + " └── 4:4:LiteralInput:'You are responsible for autocompleting a sentence.':TextOutput:'You are responsible for autocompleting a sentence.'\n", + " ├── 5:5:StatefulGuidanceInput({{G|4988006464|G}}):None\n", + " │ └── 6:6:LiteralInput:'<|im_end|>\\n':TextOutput:'<|im_end|>\\n'\n", + " └── 7:7:RoleCloserInput:'system':CaptureOutput:'system':'You are responsible for autocompleting a sentence.'\n", + " └── 8:8:StatefulGuidanceInput({{G|4988006464|G}}):None\n", + " └── 9:9:LiteralInput:'<|im_end|>\\n':TextOutput:'<|im_end|>\\n'\n", + " └── 10:10:RoleOpenerInput:'user':None\n", + " └── 11:11:StatefulGuidanceInput({{G|4985004736|G}}):None\n", + " └── 12:12:LiteralInput:'<|im_start|>user\\n':TextOutput:'<|im_start|>user\\n'\n", + " └── 13:13:LiteralInput:'Roses are red and ':TextOutput:'Roses are red and '\n", + " ├── 14:14:StatefulGuidanceInput({{G|4984996144|G}}):None\n", + " │ └── 15:15:LiteralInput:'<|im_end|>\\n':TextOutput:'<|im_end|>\\n'\n", + " └── 16:16:StatelessGuidanceInput({{G|4540775456|G}}):None\n", + " └── 17:17:None:TextOutput:'you':True:1\n", + " └── 18:18:None:TextOutput:' are':True:1\n", + " └── 19:19:None:TextOutput:' responsible':True:1\n", + " └── 20:20:None:CaptureOutput:'suffix':'you are responsible'\n" + ] + } + ], + "execution_count": 3 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "", + "id": "956e746e986f1960" }, { "cell_type": "code", "id": "120427693c64ef1f", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-27T21:14:43.512452Z", + "start_time": "2024-09-27T21:14:43.510569Z" + } + }, "source": [ - "from guidance.state import visualize, visualize_text\n", + "from guidance.trace import visualize, visualize_text\n", "\n", "visualize_text(\n", " m0._trace_handler,\n", - " m0._trace_handler.model_node_map[17]\n", + " m0._trace_handler.id_node_map[7]\n", ")" ], - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<|im_start|>system\n", + "You are responsible for autocompleting a sentence.system=You are responsible for autocompleting a sentence." + ] + } + ], + "execution_count": 4 }, { "cell_type": "code", "id": "cbbbe84572efd275", - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-27T21:14:43.588468Z", + "start_time": "2024-09-27T21:14:43.586539Z" + } + }, "source": "print(str(m2))", - "outputs": [], - "execution_count": null - }, - { - "metadata": {}, - "cell_type": "code", - "source": "print(m2._state)\n", - "id": "122ce6b1eabe6166", - "outputs": [], - "execution_count": null - }, - { - "metadata": {}, - "cell_type": "code", - "source": "", - "id": "e5efe7e2bdf97b8f", - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<|im_start|>system\n", + "You are responsible for autocompleting a sentence.<|im_end|>\n", + "<|im_start|>user\n", + "Roses are red and you are responsible<|im_end|>\n", + "\n" + ] + } + ], + "execution_count": 5 }, { - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2024-09-27T21:14:43.735794Z", + "start_time": "2024-09-27T19:57:25.432034Z" + } + }, "cell_type": "code", "source": "", - "id": "bf3c03805957a631", + "id": "d63b10cd7e2c64e7", "outputs": [], "execution_count": null } From e95d4f7163131d05e41f1965998eb81bf82bf382 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Fri, 27 Sep 2024 15:16:58 -0700 Subject: [PATCH 006/133] Clean-up of trace module. Documentation added and some type changes. --- guidance/models/_model.py | 7 +- guidance/trace/__init__.py | 91 +++++++++++++++-- notebooks/unstable/State Debugging.ipynb | 122 ++++------------------- 3 files changed, 99 insertions(+), 121 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 3099174bf..1614c67fa 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -4,13 +4,10 @@ import logging import queue import re -import textwrap import threading -import time -import warnings from pprint import pprint -from typing import Any, Dict, Iterator, List, Optional, Union, TYPE_CHECKING +from typing import Dict, Iterator, Optional, TYPE_CHECKING import numpy as np @@ -492,8 +489,6 @@ def __add__(self, value): self._trace_handler.update_node( lm._id, lm._parent_id, CaptureOutput(name=context.name, value=v) ) - # TODO(nopdive): Consider removing this - # lm = lm + context.closer # apply any newly closed contexts (new from this object's perspective) for context in exit_blocks: diff --git a/guidance/trace/__init__.py b/guidance/trace/__init__.py index 33be5b6eb..136f7af59 100644 --- a/guidance/trace/__init__.py +++ b/guidance/trace/__init__.py @@ -2,8 +2,12 @@ The first implementation aims for simplicity. Once benchmark figures are out, we'll figure out what to optimize. + +The most critical class is the trace handler. See its documentation for trace design & motivations. """ -# TODO(nopdive): Deal with weak referencing for GC +# TODO(nopdive): Deal with weak referencing for GC. Take care of cyclical dependencies from parent & children fields. +# TODO(nopdive): Benchmark (expected heap fragmentation issue). Likely need memory pooling (via rust/ctypes/Cython). +# NOTE(nopdive): Should we be explicit on capture variables? Right now they are within guidance grammars. from pydantic import BaseModel, Field from itertools import count @@ -12,6 +16,8 @@ class NodeAttr(BaseModel): + """Attributes of a trace node.""" + def __repr__(self): return pydantic_no_default_repr(self) @@ -20,14 +26,17 @@ def __str__(self): class InputAttr(NodeAttr): + """Input for a guidance program (i.e. literal or guidance grammar).""" pass class OutputAttr(NodeAttr): + """Output for a guidance program (i.e. text output).""" pass class StatelessGuidanceInput(InputAttr): + """Stateless guidance input (light wrapper).""" value: Any def __repr__(self): @@ -35,6 +44,7 @@ def __repr__(self): class StatefulGuidanceInput(InputAttr): + """Stateful guidance input (light wrapper).""" value: Any def __repr__(self): @@ -42,22 +52,33 @@ def __repr__(self): class LiteralInput(InputAttr): + """Text string as a literal.""" value: str class EmbeddedInput(InputAttr): + """Text string with embedded guidance input.""" value: str class RoleOpenerInput(InputAttr): + """Appears when a role is opened (i.e. user / system). + + This usually occurs as a role context and __enter__ is called. + """ name: str class RoleCloserInput(InputAttr): + """Appears when a role is closed (i.e. user / system). + + This usually occurs as a role context and __exit__ is called. + """ name: str class TextOutput(OutputAttr): + """Text string.""" value: str is_generated: bool = False token_count: int = 0 @@ -65,6 +86,10 @@ class TextOutput(OutputAttr): class CaptureOutput(OutputAttr): + """Capture variable output as a string. + + If `value` is set to None, this means it's a reset (needed for append capture group outputs). + """ name: str value: Optional[str] = None is_append: bool = False @@ -75,6 +100,7 @@ def __str__(self): class TraceNode(BaseModel): + """Trace node which associates inputs and outputs of a guidance program.""" identifier: int = Field(default_factory=count().__next__) parent: Optional["TraceNode"] = None children: list["TraceNode"] = [] @@ -82,10 +108,20 @@ class TraceNode(BaseModel): output: Optional[OutputAttr] = None def add_child(self, child: "TraceNode") -> None: + """ Add a child node to the trace node. + + Args: + child: The child node to add. + """ child.parent = self self.children.append(child) def remove_child(self, child: "TraceNode") -> None: + """ Remove a child node from the trace node. + + Args: + child: The child node to remove. + """ child.parent = None self.children.remove(child) @@ -97,10 +133,29 @@ def __hash__(self): class TraceHandler(BaseModel): - id_node_map: Dict[int, "TraceNode"] = {} - node_id_map: Dict["TraceNode", int] = {} + """Trace handler that will own a tree of trace nodes. + + This will primarily be owned by a model's engine. + Each guidance model corresponds to one trace node. + All guidance models emitted from an engine is to be included as their own paths within the tree. - def update_node(self, identifier: int, parent_id: int, node_attr: "NodeAttr" = None) -> None: + The requirement for holding all live traces ensures downstream consumers such as UI providers + can do near-real-time partial updates. + """ + id_node_map: Dict[int, TraceNode] = {} + node_id_map: Dict[TraceNode, int] = {} + + def update_node(self, identifier: int, parent_id: int, node_attr: NodeAttr = None) -> None: + """ Update the trace node with the given identifier. + + If the trace node does not exist, it will be created. + Both parent id and node attributes can be updated only once until further notice. + + Args: + identifier: User-defined identifier for the trace node. + parent_id: User-defined parent identifier for the trace node. + node_attr: Input or output node attribute to be updated on the trace node. + """ node = self.id_node_map.get(identifier, None) if node is None: node = TraceNode() @@ -123,27 +178,41 @@ def update_node(self, identifier: int, parent_id: int, node_attr: "NodeAttr" = N raise ValueError(f"Unexpected node attr: {node_attr}") -def visualize_text(state_builder: TraceHandler, node: TraceNode) -> None: +def visualize_output(node: TraceNode) -> None: + """ Visualize output attributes of a trace node up to the root. + + Users should not be accessing this function. For debugging purposes. + + Args: + node: The trace node to visualize. + """ def visit(visitor: TraceNode): if visitor.parent is not None: visit(visitor.parent) - if visitor.output is not None and isinstance(visitor.output, OutputAttr): + if visitor.output is not None and isinstance(visitor.output, TextOutput): print(visitor.output, end='') - visit(node) -def visualize(state_builder: TraceHandler, node: TraceNode) -> None: +def visualize(trace_handler: TraceHandler, node: TraceNode) -> None: + """ Visualize tree of a trace node going down to all its leaves. + + Users should not be accessing this function. For debugging purposes. + + Args: + trace_handler: Trace handler needed to pull user-defined identifiers of trace nodes. + node: Trace node that will function as the root. + """ from anytree import Node, RenderTree def visit(visitor: TraceNode, viz_parent=None): - nonlocal state_builder + nonlocal trace_handler if viz_parent is None: - viz_node = Node(f"{state_builder.node_id_map[visitor]}:{visitor!r}") + viz_node = Node(f"{trace_handler.node_id_map[visitor]}:{visitor!r}") else: - viz_node = Node(f"{state_builder.node_id_map[visitor]}:{visitor!r}", parent=viz_parent) + viz_node = Node(f"{trace_handler.node_id_map[visitor]}:{visitor!r}", parent=viz_parent) for child in visitor.children: visit(child, viz_node) diff --git a/notebooks/unstable/State Debugging.ipynb b/notebooks/unstable/State Debugging.ipynb index c899f0956..ab076380e 100644 --- a/notebooks/unstable/State Debugging.ipynb +++ b/notebooks/unstable/State Debugging.ipynb @@ -3,27 +3,13 @@ { "cell_type": "code", "id": "1ec02432-a44d-4fdb-b44c-b153529fc03d", - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-27T21:14:42.017246Z", - "start_time": "2024-09-27T21:14:40.405816Z" - } - }, + "metadata": {}, "source": [ "from guidance.models import Transformers\n", "from guidance import gen, user, system" ], - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/samueljenkins/dev/guidance-dev/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n", - " warnings.warn(\n" - ] - } - ], - "execution_count": 1 + "outputs": [], + "execution_count": null }, { "cell_type": "code", @@ -47,53 +33,20 @@ "# with user():\n", "# m4 = m3 + \"The sun is rising \" + gen(name='sentence_suffix', max_tokens=3)" ], - "execution_count": 2, - "outputs": [] + "outputs": [], + "execution_count": null }, { "cell_type": "code", "id": "5a5d668a11bda28f", - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-27T21:14:43.448473Z", - "start_time": "2024-09-27T21:14:43.439539Z" - } - }, + "metadata": {}, "source": [ - "from guidance.trace import visualize, visualize_text\n", + "from guidance.trace import visualize, visualize_output\n", "\n", "visualize(m0._trace_handler, m0._trace_handler.id_node_map[0])" ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0:0:None:None\n", - "└── 1:1:RoleOpenerInput:'system':None\n", - " └── 2:2:StatefulGuidanceInput({{G|4970396064|G}}):None\n", - " └── 3:3:LiteralInput:'<|im_start|>system\\n':TextOutput:'<|im_start|>system\\n'\n", - " └── 4:4:LiteralInput:'You are responsible for autocompleting a sentence.':TextOutput:'You are responsible for autocompleting a sentence.'\n", - " ├── 5:5:StatefulGuidanceInput({{G|4988006464|G}}):None\n", - " │ └── 6:6:LiteralInput:'<|im_end|>\\n':TextOutput:'<|im_end|>\\n'\n", - " └── 7:7:RoleCloserInput:'system':CaptureOutput:'system':'You are responsible for autocompleting a sentence.'\n", - " └── 8:8:StatefulGuidanceInput({{G|4988006464|G}}):None\n", - " └── 9:9:LiteralInput:'<|im_end|>\\n':TextOutput:'<|im_end|>\\n'\n", - " └── 10:10:RoleOpenerInput:'user':None\n", - " └── 11:11:StatefulGuidanceInput({{G|4985004736|G}}):None\n", - " └── 12:12:LiteralInput:'<|im_start|>user\\n':TextOutput:'<|im_start|>user\\n'\n", - " └── 13:13:LiteralInput:'Roses are red and ':TextOutput:'Roses are red and '\n", - " ├── 14:14:StatefulGuidanceInput({{G|4984996144|G}}):None\n", - " │ └── 15:15:LiteralInput:'<|im_end|>\\n':TextOutput:'<|im_end|>\\n'\n", - " └── 16:16:StatelessGuidanceInput({{G|4540775456|G}}):None\n", - " └── 17:17:None:TextOutput:'you':True:1\n", - " └── 18:18:None:TextOutput:' are':True:1\n", - " └── 19:19:None:TextOutput:' responsible':True:1\n", - " └── 20:20:None:CaptureOutput:'suffix':'you are responsible'\n" - ] - } - ], - "execution_count": 3 + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -104,64 +57,25 @@ { "cell_type": "code", "id": "120427693c64ef1f", - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-27T21:14:43.512452Z", - "start_time": "2024-09-27T21:14:43.510569Z" - } - }, + "metadata": {}, "source": [ - "from guidance.trace import visualize, visualize_text\n", + "from guidance.trace import visualize, visualize_output\n", "\n", - "visualize_text(\n", - " m0._trace_handler,\n", - " m0._trace_handler.id_node_map[7]\n", - ")" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "<|im_start|>system\n", - "You are responsible for autocompleting a sentence.system=You are responsible for autocompleting a sentence." - ] - } + "visualize_output(m0._trace_handler.id_node_map[7])" ], - "execution_count": 4 + "outputs": [], + "execution_count": null }, { "cell_type": "code", "id": "cbbbe84572efd275", - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-27T21:14:43.588468Z", - "start_time": "2024-09-27T21:14:43.586539Z" - } - }, + "metadata": {}, "source": "print(str(m2))", - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "<|im_start|>system\n", - "You are responsible for autocompleting a sentence.<|im_end|>\n", - "<|im_start|>user\n", - "Roses are red and you are responsible<|im_end|>\n", - "\n" - ] - } - ], - "execution_count": 5 + "outputs": [], + "execution_count": null }, { - "metadata": { - "ExecuteTime": { - "end_time": "2024-09-27T21:14:43.735794Z", - "start_time": "2024-09-27T19:57:25.432034Z" - } - }, + "metadata": {}, "cell_type": "code", "source": "", "id": "d63b10cd7e2c64e7", From b69582edc39f3a5d2568de06f36467cf271c9d5a Mon Sep 17 00:00:00 2001 From: nopdive Date: Fri, 27 Sep 2024 15:22:02 -0700 Subject: [PATCH 007/133] Revert some documentation word swaps. --- guidance/_grammar.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/guidance/_grammar.py b/guidance/_grammar.py index d690cf33f..85a94b227 100644 --- a/guidance/_grammar.py +++ b/guidance/_grammar.py @@ -14,7 +14,7 @@ class StatefulException(Exception): - """This is raised when we try and use the trace of a grammar object like it was a live model. + """This is raised when we try and use the state of a grammar object like it was a live model. Note that eventually it would be nice to support stateful parser/grammar constructs directly, but such "parser combinators" cannot be run effciently in Python. So we use a traditional parser and @@ -163,7 +163,7 @@ def __radd__(self, value): return value.__add__(self) def __getitem__(self, value): - raise StatefulException("GrammarFunctions can't access trace!") + raise StatefulException("GrammarFunctions can't access state!") def match( self, @@ -414,7 +414,7 @@ def replace_model_variables(grammar, model, allowed_vars=None): def unreplace_model_variables(replacements): - """This restores a grammar back to its original trace, ready for another execution.""" + """This restores a grammar back to its original state, ready for another execution.""" for grammar, i, orig_value in replacements: grammar.values[i] = orig_value From 6652b90834109859d0fb1fef048fbd581d943957 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Fri, 27 Sep 2024 23:21:09 -0700 Subject: [PATCH 008/133] Adding basic HTML renderer. Adjustments to trace. Trace nodes have light adjustments. HTML renderer is connected but fully working yet due to role closers. --- guidance/models/_model.py | 81 +++++---- guidance/trace/__init__.py | 221 +---------------------- guidance/trace/_trace.py | 188 +++++++++++++++++++ guidance/visual/__init__.py | 6 + guidance/visual/_message.py | 22 +++ guidance/visual/_renderer.py | 142 +++++++++++++++ guidance/visual/_trace.py | 52 ++++++ notebooks/unstable/State Debugging.ipynb | 52 +++++- 8 files changed, 500 insertions(+), 264 deletions(-) create mode 100644 guidance/trace/_trace.py create mode 100644 guidance/visual/__init__.py create mode 100644 guidance/visual/_message.py create mode 100644 guidance/visual/_renderer.py create mode 100644 guidance/visual/_trace.py diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 1614c67fa..7b6ea754e 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -6,14 +6,14 @@ import re import threading -from pprint import pprint from typing import Dict, Iterator, Optional, TYPE_CHECKING import numpy as np -from ..trace import RoleCloserInput, RoleOpenerInput, TraceHandler, LiteralInput, EmbeddedInput, \ - StatefulGuidanceInput, StatelessGuidanceInput, TextOutput, CaptureOutput +from ..trace import NodeAttr, StatelessGuidanceInput, StatefulGuidanceInput, LiteralInput, EmbeddedInput, \ + RoleOpenerInput, RoleCloserInput, TextOutput, CaptureOutput, TraceHandler +from ..visual import TraceMessage, AutoRenderer, trace_node_to_str try: from IPython.display import clear_output, display, HTML @@ -65,7 +65,9 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False): self.tokenizer = tokenizer self.compute_log_probs = compute_log_probs self.metrics = GuidanceEngineMetrics() + self.trace_handler = TraceHandler() + self.renderer = AutoRenderer(self.trace_handler) def get_chat_template(self): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? return self.tokenizer.chat_template() # Instantiate the class before returning to client for now @@ -231,6 +233,7 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self.engine = engine self.chat_template = engine.get_chat_template() # TODO [HN]: Should this be a method or attr? + # NOTE(nopdive): `echo` seems to be better on the engine, when is there an opportunity to turn echo off midway? self.echo = echo self.token_count = 0 # tracks how many tokens our byte state represents self.max_display_rate = 0.2 # this controls how frequently we are allowed to redraw the display (in seconds) @@ -244,6 +247,10 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self._cache_state = {} # mutable caching state used to save computation self._state = "" # the current bytes that represent the state of the model self._trace_handler = engine.trace_handler # builds state for models + if self.echo: + self._renderer = engine.renderer # renderer for display + else: + self._renderer = None # no renderer if echo is false self._event_queue = None # TODO: these are for streaming results in code, but that needs implemented self._event_parent = None self._last_display = 0 # used to track the last display call to enable throttling @@ -251,7 +258,7 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self._id = self.__class__.gen_id() # model id needed for tracking state self._parent_id = parent_id - self._trace_handler.update_node(self._id, self._parent_id, None) + self._update_trace_node(self._id, self._parent_id, None) @classmethod def gen_id(cls): @@ -335,10 +342,9 @@ def copy(self): # otherwise if the current event que has an event parent then that is also our parent new_lm._event_parent = self._event_parent - new_lm._trace_handler = self._trace_handler new_lm._id = self.__class__.gen_id() new_lm._parent_id = self._id - self._trace_handler.update_node(new_lm._id, new_lm._parent_id, None) + self._update_trace_node(new_lm._id, new_lm._parent_id, None) return new_lm @@ -360,24 +366,10 @@ def _inplace_append(self, value, force_silent=False): v = str(value) self._state += v - # see if we should update the display - if not force_silent: - self._update_display() - # this is for programmatic streaming among other things self._send_to_event_queue(self) - def _update_display(self, throttle=True): - # TODO(nopdive): Remove throttle keyword as no longer in use. - if self.echo: - if ipython_is_imported: - clear_output(wait=True) - display(HTML(self._html())) - else: - pprint(self._state) - - def reset(self, clear_variables=True): """This resets the state of the model object. @@ -436,12 +428,28 @@ def _current_prompt(self): """The current prompt in bytes (which is the state without the context close tags).""" return format_pattern.sub("", self._state) + def _update_trace_node(self, identifier: int, parent_id: Optional[int], node_attr: Optional[NodeAttr]): + """Updates trace node that corresponds to this model.""" + + trace_node = self._trace_handler.update_node(identifier, parent_id, node_attr) + if self._renderer is not None: + self._renderer.update( + TraceMessage( + trace_id=identifier, + parent_trace_id=parent_id, + trace_node=trace_node, + node_attr=node_attr, + ) + ) + def __str__(self): """A string representation of the current model object (that includes context closers).""" - out = self._current_prompt() - for context in reversed(self.opened_blocks): - out += format_pattern.sub("", self.opened_blocks[context][1]) - return out + # out = self._current_prompt() + # for context in reversed(self.opened_blocks): + # out += format_pattern.sub("", self.opened_blocks[context][1]) + # return out + return trace_node_to_str(self._trace_handler.id_node_map[self._id]) + def __add__(self, value): """Adding is the primary mechanism for extending model state. @@ -486,19 +494,19 @@ def __add__(self, value): if context.name is not None: v = format_pattern.sub("", lm._state[pos:]) lm._variables[context.name] = v - self._trace_handler.update_node( - lm._id, lm._parent_id, CaptureOutput(name=context.name, value=v) - ) + self._update_trace_node(lm._id, lm._parent_id, CaptureOutput(name=context.name, value=v)) # apply any newly closed contexts (new from this object's perspective) for context in exit_blocks: - self._trace_handler.update_node(lm._id, lm._parent_id, RoleCloserInput(name=context.name)) + self._update_trace_node(lm._id, lm._parent_id, RoleCloserInput(name=context.name)) + lm += context.closer lm = lm.copy() # apply any newly opened contexts (new from this object's perspective) for context in enter_blocks: - self._trace_handler.update_node(lm._id, lm._parent_id, RoleOpenerInput(name=context.name)) + self._update_trace_node(lm._id, lm._parent_id, RoleOpenerInput(name=context.name)) + lm += context.opener lm = lm.copy() @@ -517,9 +525,9 @@ def __add__(self, value): if isinstance(value, TextOutput): lm._inplace_append(value.value) out = lm - self._trace_handler.update_node(out._id, out._parent_id, value) + self._update_trace_node(out._id, out._parent_id, value) elif isinstance(value, CaptureOutput): - self._trace_handler.update_node(lm._id, lm._parent_id, value) + self._update_trace_node(lm._id, lm._parent_id, value) out = lm elif isinstance(value, str): # wrap raw string values @@ -529,15 +537,16 @@ def __add__(self, value): # we have no embedded objects if len(parts) == 1: - self._trace_handler.update_node(lm._id, lm._parent_id, LiteralInput(value=value)) + self._update_trace_node(lm._id, lm._parent_id, LiteralInput(value=value)) lm._inplace_append(value) out = lm - self._trace_handler.update_node(out._id, out._parent_id, TextOutput(value=value)) + self._update_trace_node(out._id, out._parent_id, TextOutput(value=value)) + # if we have embedded objects we have to convert the string to a grammar tree else: - self._trace_handler.update_node(lm._id, lm._parent_id, EmbeddedInput(value=value)) + self._update_trace_node(lm._id, lm._parent_id, EmbeddedInput(value=value)) partial_grammar = _null_grammar lm.suffix = "" @@ -564,12 +573,12 @@ def __add__(self, value): # run stateless functions (grammar nodes) elif isinstance(value, GrammarFunction): - self._trace_handler.update_node(lm._id, lm._parent_id, StatelessGuidanceInput(value=value)) + self._update_trace_node(lm._id, lm._parent_id, StatelessGuidanceInput(value=value)) out = lm._run_stateless(value) # run stateful functions else: - self._trace_handler.update_node(lm._id, lm._parent_id, StatefulGuidanceInput(value=value)) + self._update_trace_node(lm._id, lm._parent_id, StatefulGuidanceInput(value=value)) out = value(lm) if out is None: raise Exception( diff --git a/guidance/trace/__init__.py b/guidance/trace/__init__.py index 136f7af59..da958cfb3 100644 --- a/guidance/trace/__init__.py +++ b/guidance/trace/__init__.py @@ -5,222 +5,7 @@ The most critical class is the trace handler. See its documentation for trace design & motivations. """ -# TODO(nopdive): Deal with weak referencing for GC. Take care of cyclical dependencies from parent & children fields. -# TODO(nopdive): Benchmark (expected heap fragmentation issue). Likely need memory pooling (via rust/ctypes/Cython). -# NOTE(nopdive): Should we be explicit on capture variables? Right now they are within guidance grammars. - -from pydantic import BaseModel, Field -from itertools import count -from typing import Dict, Any, Optional -from guidance._utils import pydantic_no_default_repr, pydantic_no_default_str - - -class NodeAttr(BaseModel): - """Attributes of a trace node.""" - - def __repr__(self): - return pydantic_no_default_repr(self) - - def __str__(self): - return pydantic_no_default_str(self) - - -class InputAttr(NodeAttr): - """Input for a guidance program (i.e. literal or guidance grammar).""" - pass - - -class OutputAttr(NodeAttr): - """Output for a guidance program (i.e. text output).""" - pass - - -class StatelessGuidanceInput(InputAttr): - """Stateless guidance input (light wrapper).""" - value: Any - - def __repr__(self): - return f"{self.__class__.__name__}({self.value})" - - -class StatefulGuidanceInput(InputAttr): - """Stateful guidance input (light wrapper).""" - value: Any - - def __repr__(self): - return f"{self.__class__.__name__}({self.value})" - - -class LiteralInput(InputAttr): - """Text string as a literal.""" - value: str - - -class EmbeddedInput(InputAttr): - """Text string with embedded guidance input.""" - value: str - - -class RoleOpenerInput(InputAttr): - """Appears when a role is opened (i.e. user / system). - - This usually occurs as a role context and __enter__ is called. - """ - name: str - - -class RoleCloserInput(InputAttr): - """Appears when a role is closed (i.e. user / system). - - This usually occurs as a role context and __exit__ is called. - """ - name: str - - -class TextOutput(OutputAttr): - """Text string.""" - value: str - is_generated: bool = False - token_count: int = 0 - prob: float = 0.0 - - -class CaptureOutput(OutputAttr): - """Capture variable output as a string. - - If `value` is set to None, this means it's a reset (needed for append capture group outputs). - """ - name: str - value: Optional[str] = None - is_append: bool = False - log_probs: float = 0.0 - - def __str__(self): - return f"{self.name}{'+=' if self.is_append else '='}{self.value.__str__()}" - - -class TraceNode(BaseModel): - """Trace node which associates inputs and outputs of a guidance program.""" - identifier: int = Field(default_factory=count().__next__) - parent: Optional["TraceNode"] = None - children: list["TraceNode"] = [] - input: Optional[InputAttr] = None - output: Optional[OutputAttr] = None - - def add_child(self, child: "TraceNode") -> None: - """ Add a child node to the trace node. - - Args: - child: The child node to add. - """ - child.parent = self - self.children.append(child) - - def remove_child(self, child: "TraceNode") -> None: - """ Remove a child node from the trace node. - - Args: - child: The child node to remove. - """ - child.parent = None - self.children.remove(child) - - def __repr__(self): - return f"{self.identifier}:{self.input!r}:{self.output!r}" - - def __hash__(self): - return hash(self.identifier) - - -class TraceHandler(BaseModel): - """Trace handler that will own a tree of trace nodes. - - This will primarily be owned by a model's engine. - Each guidance model corresponds to one trace node. - All guidance models emitted from an engine is to be included as their own paths within the tree. - - The requirement for holding all live traces ensures downstream consumers such as UI providers - can do near-real-time partial updates. - """ - id_node_map: Dict[int, TraceNode] = {} - node_id_map: Dict[TraceNode, int] = {} - - def update_node(self, identifier: int, parent_id: int, node_attr: NodeAttr = None) -> None: - """ Update the trace node with the given identifier. - - If the trace node does not exist, it will be created. - Both parent id and node attributes can be updated only once until further notice. - - Args: - identifier: User-defined identifier for the trace node. - parent_id: User-defined parent identifier for the trace node. - node_attr: Input or output node attribute to be updated on the trace node. - """ - node = self.id_node_map.get(identifier, None) - if node is None: - node = TraceNode() - - self.id_node_map[identifier] = node - self.node_id_map[node] = identifier - - parent_node = self.id_node_map.get(parent_id, None) - if parent_node is not None: - parent_node.add_child(node) - - if node_attr is not None: - if isinstance(node_attr, InputAttr): - assert node.input is None - node.input = node_attr - elif isinstance(node_attr, OutputAttr): - assert node.output is None - node.output = node_attr - else: - raise ValueError(f"Unexpected node attr: {node_attr}") - - -def visualize_output(node: TraceNode) -> None: - """ Visualize output attributes of a trace node up to the root. - - Users should not be accessing this function. For debugging purposes. - - Args: - node: The trace node to visualize. - """ - def visit(visitor: TraceNode): - if visitor.parent is not None: - visit(visitor.parent) - - if visitor.output is not None and isinstance(visitor.output, TextOutput): - print(visitor.output, end='') - visit(node) - - -def visualize(trace_handler: TraceHandler, node: TraceNode) -> None: - """ Visualize tree of a trace node going down to all its leaves. - - Users should not be accessing this function. For debugging purposes. - - Args: - trace_handler: Trace handler needed to pull user-defined identifiers of trace nodes. - node: Trace node that will function as the root. - """ - from anytree import Node, RenderTree - - def visit(visitor: TraceNode, viz_parent=None): - nonlocal trace_handler - - if viz_parent is None: - viz_node = Node(f"{trace_handler.node_id_map[visitor]}:{visitor!r}") - else: - viz_node = Node(f"{trace_handler.node_id_map[visitor]}:{visitor!r}", parent=viz_parent) - - for child in visitor.children: - visit(child, viz_node) - return viz_node - viz_root = visit(node) - - for pre, fill, node in RenderTree(viz_root): - tree_str = u"%s%s" % (pre, node.name) - print(tree_str) - +from ._trace import NodeAttr, InputAttr, OutputAttr, StatefulGuidanceInput, StatelessGuidanceInput +from ._trace import LiteralInput, EmbeddedInput, RoleCloserInput, RoleOpenerInput +from ._trace import TextOutput, CaptureOutput, TraceNode, TraceHandler \ No newline at end of file diff --git a/guidance/trace/_trace.py b/guidance/trace/_trace.py new file mode 100644 index 000000000..484ab6dee --- /dev/null +++ b/guidance/trace/_trace.py @@ -0,0 +1,188 @@ +# TODO(nopdive): Deal with weak referencing for GC. Take care of cyclical dependencies from parent & children fields. +# TODO(nopdive): Benchmark (expected heap fragmentation issue). Likely need memory pooling (via rust/ctypes/Cython). +# NOTE(nopdive): Should we be explicit on capture variables? Right now they are within guidance grammars. + +from itertools import count +from typing import Any, Optional, Generator, Dict +from pydantic import BaseModel, Field +from .._utils import pydantic_no_default_repr, pydantic_no_default_str + + +class NodeAttr(BaseModel): + """Attributes of a trace node.""" + + def __repr__(self): + return pydantic_no_default_repr(self) + + def __str__(self): + return pydantic_no_default_str(self) + + +class InputAttr(NodeAttr): + """Input for a guidance program (i.e. literal or guidance grammar).""" + pass + + +class OutputAttr(NodeAttr): + """Output for a guidance program (i.e. text output).""" + pass + + +class StatelessGuidanceInput(InputAttr): + """Stateless guidance input (light wrapper).""" + value: Any + + def __repr__(self): + return f"{self.__class__.__name__}({self.value})" + + +class StatefulGuidanceInput(InputAttr): + """Stateful guidance input (light wrapper).""" + value: Any + + def __repr__(self): + return f"{self.__class__.__name__}({self.value})" + + +class LiteralInput(InputAttr): + """Text string as a literal.""" + value: str + + +class EmbeddedInput(InputAttr): + """Text string with embedded guidance input.""" + value: str + + +class RoleOpenerInput(InputAttr): + """Appears when a role is opened (i.e. user / system). + + This usually occurs as a role context and __enter__ is called. + """ + name: str + + +class RoleCloserInput(InputAttr): + """Appears when a role is closed (i.e. user / system). + + This usually occurs as a role context and __exit__ is called. + """ + name: str + + +class TextOutput(OutputAttr): + """Text string.""" + value: str + is_generated: bool = False + token_count: int = 0 + prob: float = 0.0 + + def __str__(self): + return self.value + + +class CaptureOutput(OutputAttr): + """Capture variable output as a string. + + If `value` is set to None, this means it's a reset (needed for append capture group outputs). + """ + name: str + value: Optional[str] = None + is_append: bool = False + log_probs: float = 0.0 + + def __str__(self): + return f"{self.name}{'+=' if self.is_append else '='}{self.value.__str__()}" + + +class TraceNode(BaseModel): + """Trace node which associates inputs and outputs of a guidance program.""" + identifier: int = Field(default_factory=count().__next__) + parent: Optional["TraceNode"] = None + children: list["TraceNode"] = [] + input: Optional[InputAttr] = None + output: Optional[OutputAttr] = None + + def add_child(self, child: "TraceNode") -> None: + """ Add a child node to the trace node. + + Args: + child: The child node to add. + """ + child.parent = self + self.children.append(child) + + def remove_child(self, child: "TraceNode") -> None: + """ Remove a child node from the trace node. + + Args: + child: The child node to remove. + """ + child.parent = None + self.children.remove(child) + + def ancestors(self) -> Generator["TraceNode", None, None]: + """ Yields ancestor trace nodes ending with root. + + Yields: + Ancestor trace nodes. + """ + node = self + while node.parent is not None: + yield node.parent + node = node.parent + + def __repr__(self): + return f"{self.identifier}:{self.input!r}:{self.output!r}" + + def __hash__(self): + return hash(self.identifier) + + +class TraceHandler(BaseModel): + """Trace handler that will own a tree of trace nodes. + + This will primarily be owned by a model's engine. + Each guidance model corresponds to one trace node. + All guidance models emitted from an engine is to be included as their own paths within the tree. + + The requirement for holding all live traces ensures downstream consumers such as UI providers + can do near-real-time partial updates. + """ + id_node_map: Dict[int, TraceNode] = {} + node_id_map: Dict[TraceNode, int] = {} + + def update_node(self, identifier: int, parent_id: Optional[int], node_attr: Optional[NodeAttr] = None) -> TraceNode: + """ Update the trace node with the given identifier. + + If the trace node does not exist, it will be created. + Both parent id and node attributes can be updated only once until further notice. + + Args: + identifier: User-defined identifier for the trace node. + parent_id: User-defined parent identifier for the trace node. + node_attr: Input or output node attribute to be updated on the trace node. + """ + node = self.id_node_map.get(identifier, None) + if node is None: + node = TraceNode() + + self.id_node_map[identifier] = node + self.node_id_map[node] = identifier + + if parent_id is not None: + parent_node = self.id_node_map.get(parent_id, None) + if parent_node is not None: + parent_node.add_child(node) + + if node_attr is not None: + if isinstance(node_attr, InputAttr): + assert node.input is None + node.input = node_attr + elif isinstance(node_attr, OutputAttr): + assert node.output is None + node.output = node_attr + else: + raise ValueError(f"Unexpected node attr: {node_attr}") + + return node diff --git a/guidance/visual/__init__.py b/guidance/visual/__init__.py new file mode 100644 index 000000000..40fc16db1 --- /dev/null +++ b/guidance/visual/__init__.py @@ -0,0 +1,6 @@ +"""User interface and other visual UX considerations.""" +# TODO(nopdive): implement stdout renderer + +from ._message import Message, TraceMessage, ResetDisplayMessage +from ._renderer import AutoRenderer, JupyterHtmlRenderer +from ._trace import trace_node_to_str, trace_node_to_tree \ No newline at end of file diff --git a/guidance/visual/_message.py b/guidance/visual/_message.py new file mode 100644 index 000000000..6f7866d55 --- /dev/null +++ b/guidance/visual/_message.py @@ -0,0 +1,22 @@ +from typing import Optional +from pydantic import BaseModel +from ..trace import NodeAttr, TraceNode + + +class Message(BaseModel): + message_type: str = "" + + def __init__(self, **kwargs): + kwargs["message_type"] = self.__class__.__name__ + super().__init__(**kwargs) + + +class TraceMessage(Message): + trace_id: int + parent_trace_id: Optional[int] + trace_node: TraceNode + node_attr: Optional[NodeAttr] + + +class ResetDisplayMessage(Message): + pass diff --git a/guidance/visual/_renderer.py b/guidance/visual/_renderer.py new file mode 100644 index 000000000..6485af5a8 --- /dev/null +++ b/guidance/visual/_renderer.py @@ -0,0 +1,142 @@ +import html +import logging +from typing import Optional +from pydantic import BaseModel +from ..trace import RoleOpenerInput, RoleCloserInput, TextOutput, TraceHandler +from ..visual import Message, TraceMessage, ResetDisplayMessage + +logger = logging.getLogger(__name__) + +try: + from IPython.display import clear_output, display, HTML + from IPython import get_ipython + + ipython_imported = True +except ImportError: + ipython_imported = False + + +class RenderUpdate(BaseModel): + messages: list = [] + need_new_display: bool = False + + +class UpdateController: + def __init__(self, trace_handler: TraceHandler): + self._trace_handler = trace_handler + self._messages: list[Message] = [] + + self._prev_trace_id: Optional[int] = None + self._prev_cell_msg_id: Optional[int] = None + self._prev_cell_exec_count: Optional[int] = None + + def update(self, message: Message) -> RenderUpdate: + if not isinstance(message, TraceMessage): + return RenderUpdate() + + # if type(message.node_attr) not in [TextOutput, RoleOpenerInput, RoleCloserInput]: + # return RenderUpdate() + + trace_node = message.trace_node + need_reset = False + need_new_display = False + + if len(self._messages) == 0: + # If no messages, reset + logger.debug("NEED_RESET:empty") + need_reset = True + need_new_display = True + else: + # If we diverge from the model path, truncate and reset + last_trace_message = next(x for x in reversed(self._messages) if isinstance(x, TraceMessage)) + last_trace_node = last_trace_message.trace_node + + if trace_node != last_trace_node and last_trace_node not in trace_node.ancestors(): + logger.debug(f"NEED_RESET:divergence:{last_trace_node}:{trace_node}") + need_reset = True + + # Truncate path that is no longer used by current trace node + ancestor_idx = -1 + ancestors = set(trace_node.ancestors()) + for idx, prev_message in enumerate(self._messages): + if isinstance(prev_message, TraceMessage): + if prev_message.trace_node in ancestors: + ancestor_idx = idx + if ancestor_idx == -1: + logger.debug(f"PARENT_NOT_FOUND:{trace_node}") + self._messages.clear() + else: + self._messages = self._messages[:ancestor_idx] + + # If we are in a new Jupyter cell or execution, reset + if ipython_imported: + ipy = get_ipython() + cell_msg_id = ipy.get_parent()['msg_id'] + cell_exec_count = ipy.execution_count + if cell_msg_id != self._prev_cell_msg_id or cell_exec_count != self._prev_cell_exec_count: + need_reset = True + need_new_display = True + logger.debug(f"NEED_RESET:jupyter:{cell_msg_id}|{cell_exec_count}") + self._prev_cell_msg_id = cell_msg_id + self._prev_cell_exec_count = cell_exec_count + self._messages = [] + + out_messages = [] + # Add previous messages if reset required + if need_reset: + out_messages.append(ResetDisplayMessage()) + out_messages.extend(self._messages) + # Add current message + out_messages.append(message) + self._messages.append(message) + + return RenderUpdate(messages=out_messages, need_new_display=need_new_display) + + +class Renderer: + """Renders guidance model to a visual medium.""" + + def update(self, message: Message) -> None: + raise NotImplementedError('Update not implemented.') + + +class JupyterHtmlRenderer(Renderer): + def __init__(self, trace_handler: TraceHandler) -> None: + self._update_controller = UpdateController(trace_handler) + self._formatted = [] + + def update(self, message: Message) -> None: + render_update = self._update_controller.update(message) + + formatted = [] + for out_message in render_update.messages: + if isinstance(out_message, ResetDisplayMessage): + self._formatted.clear() + formatted.clear() + elif isinstance(out_message, TraceMessage): + if isinstance(out_message.node_attr, TextOutput): + x = out_message.node_attr + fmt = f"{html.escape(x.value)}" + formatted.append(fmt) + elif isinstance(out_message.node_attr, RoleOpenerInput): + # TODO(nopdive): Implement HTML for role opener + pass + elif isinstance(out_message.node_attr, RoleCloserInput): + # TODO(nopdive): Implement HTML for role closer. Looks like there's a bug somewhere on order of trace nodes (text-output for closer is after role-closer-input). + pass + self._formatted.extend(formatted) + + # For Jupyter HTML rendering, there are no partial updates. + if len(self._formatted) > 0: + clear_output(wait=True) + display(HTML("".join(self._formatted))) + + +class AutoRenderer(Renderer): + def __init__(self, trace_handler: TraceHandler): + # TODO(nopdive): Add autodetect logic. + self._renderer = JupyterHtmlRenderer(trace_handler=trace_handler) + + def update(self, message: Message) -> None: + if self._renderer is not None: + self._renderer.update(message) diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py new file mode 100644 index 000000000..24793e3ec --- /dev/null +++ b/guidance/visual/_trace.py @@ -0,0 +1,52 @@ +from ..trace import TextOutput, TraceNode, TraceHandler + + +def trace_node_to_str(node: TraceNode) -> str: + """ Visualize output attributes of a trace node up to the root. + + Users should not be accessing this function. For debugging purposes. + + Args: + node: The trace node to visualize. + Returns: + Output as string. + """ + def visit(visitor: TraceNode, buffer: list): + if visitor.parent is not None: + visit(visitor.parent, buffer) + + if visitor.output is not None and isinstance(visitor.output, TextOutput): + buffer.append(str(visitor.output)) + + results = [] + visit(node, results) + return ''.join(results) + + +def trace_node_to_tree(trace_handler: TraceHandler, node: TraceNode) -> None: + """ Visualize tree of a trace node going down to all its leaves. + + Users should not be accessing this function. For debugging purposes. + + Args: + trace_handler: Trace handler needed to pull user-defined identifiers of trace nodes. + node: Trace node that will function as the root. + """ + from anytree import Node, RenderTree + + def visit(visitor: TraceNode, viz_parent=None): + nonlocal trace_handler + + if viz_parent is None: + viz_node = Node(f"{trace_handler.node_id_map[visitor]}:{visitor!r}") + else: + viz_node = Node(f"{trace_handler.node_id_map[visitor]}:{visitor!r}", parent=viz_parent) + + for child in visitor.children: + visit(child, viz_node) + return viz_node + viz_root = visit(node) + + for pre, fill, node in RenderTree(viz_root): + tree_str = u"%s%s" % (pre, node.name) + print(tree_str) diff --git a/notebooks/unstable/State Debugging.ipynb b/notebooks/unstable/State Debugging.ipynb index ab076380e..146c51338 100644 --- a/notebooks/unstable/State Debugging.ipynb +++ b/notebooks/unstable/State Debugging.ipynb @@ -11,6 +11,18 @@ "outputs": [], "execution_count": null }, + { + "cell_type": "code", + "id": "4f43aabe74c4fc8c", + "metadata": {}, + "source": [ + "import logging\n", + "logging.basicConfig()\n", + "logging.getLogger().setLevel(logging.DEBUG)" + ], + "outputs": [], + "execution_count": null + }, { "cell_type": "code", "id": "18b70f42-4b6d-41a4-94be-a41360571901", @@ -37,22 +49,30 @@ "execution_count": null }, { + "metadata": {}, "cell_type": "code", - "id": "5a5d668a11bda28f", + "source": "print(m2)", + "id": "3698a47825dd2396", + "outputs": [], + "execution_count": null + }, + { "metadata": {}, + "cell_type": "code", "source": [ - "from guidance.trace import visualize, visualize_output\n", + "from guidance.visual import trace_node_to_str, trace_node_to_tree\n", "\n", - "visualize(m0._trace_handler, m0._trace_handler.id_node_map[0])" + "trace_node_to_tree(m0._trace_handler, m0._trace_handler.id_node_map[0])" ], + "id": "5a5d668a11bda28f", "outputs": [], "execution_count": null }, { - "metadata": {}, "cell_type": "markdown", - "source": "", - "id": "956e746e986f1960" + "id": "956e746e986f1960", + "metadata": {}, + "source": [] }, { "cell_type": "code", @@ -61,7 +81,7 @@ "source": [ "from guidance.trace import visualize, visualize_output\n", "\n", - "visualize_output(m0._trace_handler.id_node_map[7])" + "visualize_output(m0._trace_handler.id_node_map[20])" ], "outputs": [], "execution_count": null @@ -70,15 +90,27 @@ "cell_type": "code", "id": "cbbbe84572efd275", "metadata": {}, - "source": "print(str(m2))", + "source": [ + "print(str(m2))" + ], "outputs": [], "execution_count": null }, { + "cell_type": "code", + "id": "97fba3134abb4900", "metadata": {}, + "source": [ + "m2" + ], + "outputs": [], + "execution_count": null + }, + { "cell_type": "code", - "source": "", - "id": "d63b10cd7e2c64e7", + "id": "2ed742e0fdbe6dd6", + "metadata": {}, + "source": [], "outputs": [], "execution_count": null } From 43820d6f4fd07d523d963ea77ea1b37dfd4ee2fa Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Sat, 28 Sep 2024 16:57:06 -0700 Subject: [PATCH 009/133] Working basic visualization. Old HTML display now fully replaced. Fixed some roles issues as well. --- guidance/library/_block.py | 5 +- guidance/library/_role.py | 61 +---------- guidance/models/_model.py | 126 ++++++++--------------- guidance/trace/__init__.py | 4 +- guidance/trace/_trace.py | 73 +++++++++++++ guidance/visual/__init__.py | 2 +- guidance/visual/_renderer.py | 34 ++---- guidance/visual/_trace.py | 110 +++++++++++++++----- notebooks/unstable/State Debugging.ipynb | 68 +++--------- 9 files changed, 230 insertions(+), 253 deletions(-) diff --git a/guidance/library/_block.py b/guidance/library/_block.py index a7bc71861..0fc559f0c 100644 --- a/guidance/library/_block.py +++ b/guidance/library/_block.py @@ -8,11 +8,10 @@ def __init__(self, opener, closer, name=None): self.name = name def __enter__(self): - models.Model.open_blocks[self] = None + models.Model.global_active_blocks.append(self) def __exit__(self, exc_type, exc_value, traceback): - del models.Model.open_blocks[self] - models.Model.close_blocks[self] = None + models.Model.global_active_blocks.remove(self) def block(name=None, opener="", closer=""): diff --git a/guidance/library/_role.py b/guidance/library/_role.py index 9bc73db96..3ecc8a03a 100644 --- a/guidance/library/_role.py +++ b/guidance/library/_role.py @@ -2,74 +2,19 @@ from ._block import block from ._set_attribute import set_attribute -nodisp_start = "<||_#NODISP_||>" -nodisp_end = "<||_/NODISP_||>" -span_start = "<||_html:_||>" -span_end = "<||_html:_||>" -# TODO(nopdive): Render needs to be moved out @guidance def role_opener(lm, role_name, **kwargs): - # indent = getattr(lm, "indent_roles", True) - - - # Block start container (centers elements) - # if indent: - # lm += f"<||_html:
{role_name.lower()}
_||>" - - # Start of either debug or HTML no disp block - # if indent: - # lm += nodisp_start - # else: - # lm += span_start - - # TODO [HN]: Temporary change while I instrument chat_template in transformers only. - # Eventually have all models use chat_template. - lm = lm._add_role_opener(role_name, **kwargs) - - # if hasattr(lm, "get_role_start"): - # lm += lm.get_role_start(role_name, **kwargs) - # elif hasattr(lm, "chat_template"): - # lm += lm.chat_template.get_role_start(role_name) - # else: - # raise Exception( - # f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" - # ) - - # End of either debug or HTML no disp block - # if indent: - # lm += nodisp_end - # else: - # lm += span_end - + lm += lm.role_opener(role_name, **kwargs) return lm @guidance def role_closer(lm, role_name, **kwargs): - # indent = getattr(lm, "indent_roles", True) - # # Start of either debug or HTML no disp block - # if indent: - # lm += nodisp_start - # else: - # lm += span_start - - # TODO [HN]: Temporary change while I instrument chat_template in transformers only. - # Eventually have all models use chat_template. - lm = lm._add_role_closer(role_name, **kwargs) - - # # End of either debug or HTML no disp block - # if indent: - # lm += nodisp_end - # else: - # lm += span_end - - # # End of top container - # if indent: - # lm += "<||_html:
_||>" - + lm += lm.role_closer(role_name, **kwargs) return lm + # TODO HN: Add a docstring to better describe arbitrary role functions def role(role_name, text=None, **kwargs): if text is None: diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 7b6ea754e..370a87ed8 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -1,19 +1,17 @@ -import base64 import copy -import html import logging import queue import re import threading -from typing import Dict, Iterator, Optional, TYPE_CHECKING +from typing import Iterator, Optional, TYPE_CHECKING import numpy as np from ..trace import NodeAttr, StatelessGuidanceInput, StatefulGuidanceInput, LiteralInput, EmbeddedInput, \ RoleOpenerInput, RoleCloserInput, TextOutput, CaptureOutput, TraceHandler -from ..visual import TraceMessage, AutoRenderer, trace_node_to_str +from ..visual import TraceMessage, AutoRenderer, trace_node_to_str, trace_node_to_html try: from IPython.display import clear_output, display, HTML @@ -203,9 +201,8 @@ class Model: .. automethod:: __add__ """ - open_blocks: Dict["ContextBlock", None] = {} # track what context blocks are open - close_blocks: Dict["ContextBlock", None] = {} # track what context block is about to close - + global_active_blocks: list["ContextBlock"] = [] # track what context blocks are globally active + _grammar_only = 0 # a flag that tracks when we are forced to be executing only compiled grammars (like when we are inside a select) def __init__(self, engine, echo=True, parent_id=None, **kwargs): @@ -238,7 +235,6 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self.token_count = 0 # tracks how many tokens our byte state represents self.max_display_rate = 0.2 # this controls how frequently we are allowed to redraw the display (in seconds) self.opened_blocks = {} # what context blocks have been opened but not closed - self.closed_blocks = {} # what context blocks have been closed after open # self.compute_log_probs = compute_log_probs # private attributes @@ -288,24 +284,11 @@ def active_role_end(self): def _html(self): """Generate HTML that displays the model object.""" - display_out = self._state - for context in reversed(self.opened_blocks): - display_out += self.opened_blocks[context][1] - display_out = html.escape(display_out) - display_out = nodisp_pattern.sub("", display_out) - display_out = html_pattern.sub(lambda x: html.unescape(x.group(1)), display_out) - display_out = image_pattern.sub( - lambda x: '', - display_out, - ) - display_out = ( - "
"
-            + display_out
-            + "
" + + return trace_node_to_html( + self._trace_handler.id_node_map[self._id], + hasattr(self, "indent_roles") ) - return display_out def _send_to_event_queue(self, value): """For streaming in code. @@ -329,7 +312,6 @@ def copy(self): new_lm._variables = self._variables.copy() new_lm._variables_log_probs = self._variables_log_probs.copy() new_lm.opened_blocks = self.opened_blocks.copy() - new_lm.closed_blocks = self.closed_blocks.copy() # create a new clean event queue new_lm._event_queue = None # we start with no event queue because nobody is listening to us yet @@ -386,38 +368,32 @@ def reset(self, clear_variables=True): self._variables_log_probs = {} return self - # NOTE(nopdive): Intentionally private, consider this friend scoped. Users should never be interacting with this method directly. - def _add_role_opener(self, role_name, **kwargs): - lm = self + def role_opener(self, role_name, **kwargs): # TODO [HN]: Temporary change while I instrument chat_template in transformers only. # Eventually have all models use chat_template. - if hasattr(lm, "get_role_start"): - lm += lm.get_role_start(role_name, **kwargs) - elif hasattr(lm, "chat_template"): - lm += lm.chat_template.get_role_start(role_name) + if hasattr(self, "get_role_start"): + return self.get_role_start(role_name, **kwargs) + elif hasattr(self, "chat_template"): + return self.chat_template.get_role_start(role_name) else: raise Exception( f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" ) - return lm - - # NOTE(nopdive): Intentionally private, consider this friend scoped. Users should never be interacting with this method directly. - def _add_role_closer(self, role_name, **kwargs): - lm = self + def role_closer(self, role_name, **kwargs): # TODO [HN]: Temporary change while I instrument chat_template in transformers only. # Eventually have all models use chat_template. - if hasattr(lm, "get_role_end"): - lm += lm.get_role_end(role_name, **kwargs) - elif hasattr(lm, "chat_template"): - lm += lm.chat_template.get_role_end(role_name) + if hasattr(self, "get_role_end"): + return self.get_role_end(role_name, **kwargs) + elif hasattr(self, "chat_template"): + return self.chat_template.get_role_end(role_name) else: raise Exception( f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" ) - return lm + def _repr_html_(self): if ipython_is_imported: @@ -426,7 +402,7 @@ def _repr_html_(self): def _current_prompt(self): """The current prompt in bytes (which is the state without the context close tags).""" - return format_pattern.sub("", self._state) + return trace_node_to_str(self._trace_handler.id_node_map[self._id]) def _update_trace_node(self, identifier: int, parent_id: Optional[int], node_attr: Optional[NodeAttr]): """Updates trace node that corresponds to this model.""" @@ -442,12 +418,11 @@ def _update_trace_node(self, identifier: int, parent_id: Optional[int], node_att ) ) + def __str__(self): """A string representation of the current model object (that includes context closers).""" - # out = self._current_prompt() - # for context in reversed(self.opened_blocks): - # out += format_pattern.sub("", self.opened_blocks[context][1]) - # return out + + # TODO(nopdive): Ensure context closers or no? return trace_node_to_str(self._trace_handler.id_node_map[self._id]) @@ -464,58 +439,49 @@ def __add__(self, value): # (we need to do this since Model objects are immutable) lm = self.copy() - # find what new blocks need to be applied + # find blocks that are now active, but haven't been opened by lm yet enter_blocks = [] - for context in Model.open_blocks: + for context in Model.global_active_blocks: if context not in lm.opened_blocks: enter_blocks.append(context) - - # mark this so we don't re-add when computing the opener or closer (even though we don't know the close text yet) lm.opened_blocks[context] = (0, "") + # find opened blocks by lm, but are no longer active exit_blocks = [] - for context in Model.close_blocks: - if context not in lm.closed_blocks: + for context in list(reversed(lm.opened_blocks.keys())): + if context not in Model.global_active_blocks: exit_blocks.append(context) - lm.closed_blocks[context] = (0, "") + # finish any exiting blocks + for context in exit_blocks: + pos, close_text = lm.opened_blocks[context] + del lm.opened_blocks[context] - # find what old blocks need to be removed - old_blocks = [] - for context in list(reversed(lm.opened_blocks)): - if context not in Model.open_blocks and context in lm.opened_blocks: - old_blocks.append((lm.opened_blocks[context], context)) - - # delete this so we don't re-close when computing the opener or closer - del lm.opened_blocks[context] - - # close any newly closed contexts - for (pos, close_text), context in old_blocks: + # handle variables if context.name is not None: + # TODO(nopdive): Replace with trace traversal. v = format_pattern.sub("", lm._state[pos:]) lm._variables[context.name] = v self._update_trace_node(lm._id, lm._parent_id, CaptureOutput(name=context.name, value=v)) - # apply any newly closed contexts (new from this object's perspective) - for context in exit_blocks: + # add closer self._update_trace_node(lm._id, lm._parent_id, RoleCloserInput(name=context.name)) - lm += context.closer lm = lm.copy() - # apply any newly opened contexts (new from this object's perspective) + # start any entering blocks for context in enter_blocks: + # add opener self._update_trace_node(lm._id, lm._parent_id, RoleOpenerInput(name=context.name)) - lm += context.opener lm = lm.copy() - with grammar_only(): - tmp = lm + context.closer - close_text = tmp._state[len(lm._state):] # get the new trace added by calling the closer + # store closer for state extraction later + close_text = self.role_closer(context.name) lm.opened_blocks[context] = (len(lm._state), close_text) - # clear out names that we override + # handle variables + # NOTE(nopdive): No stack for variables, this process removes shadowed variables? if context.name is not None: if context.name in lm._variables: del lm._variables[context.name] @@ -796,10 +762,6 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): if len(chunk.new_bytes) > 0: generated_value += new_text - if chunk.is_generated: - # TODO(viz) - # lm += f"<||_html:_||>" - pass lm += TextOutput( value=new_text, @@ -808,13 +770,7 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): prob=chunk.new_bytes_prob, ) - if chunk.is_generated: - # TODO(viz) - # lm += "<||_html:_||>" - pass - # last_is_generated = chunk.is_generated - if len(chunk.capture_groups) > 0: for k in chunk.capture_groups: v = chunk.capture_groups[k] diff --git a/guidance/trace/__init__.py b/guidance/trace/__init__.py index da958cfb3..52e626401 100644 --- a/guidance/trace/__init__.py +++ b/guidance/trace/__init__.py @@ -7,5 +7,5 @@ """ from ._trace import NodeAttr, InputAttr, OutputAttr, StatefulGuidanceInput, StatelessGuidanceInput -from ._trace import LiteralInput, EmbeddedInput, RoleCloserInput, RoleOpenerInput -from ._trace import TextOutput, CaptureOutput, TraceNode, TraceHandler \ No newline at end of file +from ._trace import LiteralInput, EmbeddedInput, ImageInput, RoleCloserInput, RoleOpenerInput +from ._trace import TextOutput, ImageOutput, CaptureOutput, TraceNode, TraceHandler \ No newline at end of file diff --git a/guidance/trace/_trace.py b/guidance/trace/_trace.py index 484ab6dee..b6ff3a6d0 100644 --- a/guidance/trace/_trace.py +++ b/guidance/trace/_trace.py @@ -1,9 +1,11 @@ # TODO(nopdive): Deal with weak referencing for GC. Take care of cyclical dependencies from parent & children fields. # TODO(nopdive): Benchmark (expected heap fragmentation issue). Likely need memory pooling (via rust/ctypes/Cython). +# TODO(nopdive): Integrate images when PR for multimodal is in. # NOTE(nopdive): Should we be explicit on capture variables? Right now they are within guidance grammars. from itertools import count from typing import Any, Optional, Generator, Dict + from pydantic import BaseModel, Field from .._utils import pydantic_no_default_repr, pydantic_no_default_str @@ -49,6 +51,12 @@ class LiteralInput(InputAttr): value: str +# NOTE(nopdive): Placeholder, needs to be filled once multimodal PR is in. +class ImageInput(InputAttr): + """Image input.""" + value: bytes + + class EmbeddedInput(InputAttr): """Text string with embedded guidance input.""" value: str @@ -81,6 +89,12 @@ def __str__(self): return self.value +# NOTE(nopdive): Placeholder, needs to be filled once multimodal PR is in. +class ImageOutput(OutputAttr): + """Image as bytes.""" + value: bytes + + class CaptureOutput(OutputAttr): """Capture variable output as a string. @@ -132,6 +146,48 @@ def ancestors(self) -> Generator["TraceNode", None, None]: yield node.parent node = node.parent + + def path(self) -> Generator["TraceNode", None, None]: + """ Yields path of from root to self inclusively. + + Yields: + Trace nodes from root to self. + """ + yield from reversed(list(self.ancestors())) + yield self + + def root(self) -> "TraceNode": + """ Returns root by traversing parents of self. + + Returns: + Root of tree self is part of. + """ + if self.parent is None: + root = self + else: + *_, root = self.ancestors() + return root + + def traverse(self, bfs: bool = True): + """ Traverse the trace nodes starting with self. + + Args: + bfs: Use breadth-first-search, otherwise depth-first-search. + + Yields: + Trace nodes in traversal order. + """ + queue = [self] + while queue: + node = queue.pop(0) + yield node + + if bfs: + queue.extend(node.children) + else: + # NOTE(nopdive): Analogous to extend but at front of list. + queue[0:0] = node.children + def __repr__(self): return f"{self.identifier}:{self.input!r}:{self.output!r}" @@ -186,3 +242,20 @@ def update_node(self, identifier: int, parent_id: Optional[int], node_attr: Opti raise ValueError(f"Unexpected node attr: {node_attr}") return node + + def root(self) -> TraceNode: + """ Returns root node of trace handler. + + Raises: + Exception: If root cannot be found. + + Returns: Root trace node. + """ + root = None + for _, node in self.id_node_map.items(): + if node.parent is None: + root = node + break + if root is None: + raise Exception("No root in trace handler.") + return root diff --git a/guidance/visual/__init__.py b/guidance/visual/__init__.py index 40fc16db1..1dd9c82cc 100644 --- a/guidance/visual/__init__.py +++ b/guidance/visual/__init__.py @@ -3,4 +3,4 @@ from ._message import Message, TraceMessage, ResetDisplayMessage from ._renderer import AutoRenderer, JupyterHtmlRenderer -from ._trace import trace_node_to_str, trace_node_to_tree \ No newline at end of file +from ._trace import trace_node_to_str, display_trace_tree, trace_node_to_html \ No newline at end of file diff --git a/guidance/visual/_renderer.py b/guidance/visual/_renderer.py index 6485af5a8..2d6e48986 100644 --- a/guidance/visual/_renderer.py +++ b/guidance/visual/_renderer.py @@ -1,9 +1,10 @@ -import html import logging from typing import Optional from pydantic import BaseModel -from ..trace import RoleOpenerInput, RoleCloserInput, TextOutput, TraceHandler + +from ..trace import TraceHandler from ..visual import Message, TraceMessage, ResetDisplayMessage +from ._trace import trace_node_to_html logger = logging.getLogger(__name__) @@ -51,7 +52,7 @@ def update(self, message: Message) -> RenderUpdate: last_trace_message = next(x for x in reversed(self._messages) if isinstance(x, TraceMessage)) last_trace_node = last_trace_message.trace_node - if trace_node != last_trace_node and last_trace_node not in trace_node.ancestors(): + if trace_node not in last_trace_node.path(): logger.debug(f"NEED_RESET:divergence:{last_trace_node}:{trace_node}") need_reset = True @@ -108,28 +109,15 @@ def __init__(self, trace_handler: TraceHandler) -> None: def update(self, message: Message) -> None: render_update = self._update_controller.update(message) - formatted = [] + last_trace_node = None for out_message in render_update.messages: - if isinstance(out_message, ResetDisplayMessage): - self._formatted.clear() - formatted.clear() - elif isinstance(out_message, TraceMessage): - if isinstance(out_message.node_attr, TextOutput): - x = out_message.node_attr - fmt = f"{html.escape(x.value)}" - formatted.append(fmt) - elif isinstance(out_message.node_attr, RoleOpenerInput): - # TODO(nopdive): Implement HTML for role opener - pass - elif isinstance(out_message.node_attr, RoleCloserInput): - # TODO(nopdive): Implement HTML for role closer. Looks like there's a bug somewhere on order of trace nodes (text-output for closer is after role-closer-input). - pass - self._formatted.extend(formatted) - - # For Jupyter HTML rendering, there are no partial updates. - if len(self._formatted) > 0: + if isinstance(out_message, TraceMessage): + last_trace_node = out_message.trace_node + + + if last_trace_node is not None: clear_output(wait=True) - display(HTML("".join(self._formatted))) + display(HTML(trace_node_to_html(last_trace_node, prettify_roles=False))) class AutoRenderer(Renderer): diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index 24793e3ec..89264e38e 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -1,4 +1,68 @@ -from ..trace import TextOutput, TraceNode, TraceHandler +import base64 +from typing import Optional, Dict + +from ..trace import TextOutput, TraceNode, TraceHandler, RoleOpenerInput, RoleCloserInput, ImageOutput +import html + +span_start = "" +span_end = "" + + +def trace_node_to_html(node: TraceNode, prettify_roles=False) -> str: + """ Represents trace path as html string. + + Args: + node: Trace node that designates the end of a trace path for HTML output. + prettify_roles: Enables prettier formatting for roles. + + Returns: + HTML string of trace path as html. + """ + buffer = [] + node_path = list(node.path()) + active_role: Optional[TraceNode] = None + + for i, node in enumerate(node_path): + if isinstance(node.input, RoleOpenerInput): + active_role = node + elif isinstance(node.input, RoleCloserInput): + active_role = node + + if isinstance(node.output, TextOutput): + if active_role is not None: + if isinstance(active_role.input, RoleOpenerInput) and prettify_roles: + role_name = active_role.input.name + fmt = f"
{role_name.lower()}
" + buffer.append(fmt) + if not prettify_roles: + buffer.append(span_start) + + if not (active_role and prettify_roles): + attr = node.output + if attr.is_generated: + fmt = f"{html.escape(attr.value)}" + else: + fmt = f"{html.escape(attr.value)}" + buffer.append(fmt) + + if active_role is not None: + if not prettify_roles: + buffer.append(span_end) + if isinstance(active_role.input, RoleCloserInput) and prettify_roles: + buffer.append(f"
") + active_role = None + elif isinstance(node.output, ImageOutput): + encoded = base64.b64encode(node.output.value).decode() + buffer.append( + f'' + ) + + buffer.insert( + 0, + "
"
+    )
+    buffer.append("
") + return "".join(buffer) def trace_node_to_str(node: TraceNode) -> str: @@ -11,42 +75,34 @@ def trace_node_to_str(node: TraceNode) -> str: Returns: Output as string. """ - def visit(visitor: TraceNode, buffer: list): - if visitor.parent is not None: - visit(visitor.parent, buffer) - - if visitor.output is not None and isinstance(visitor.output, TextOutput): - buffer.append(str(visitor.output)) + buffer = [] + for node in node.path(): + if isinstance(node.output, TextOutput): + buffer.append(str(node.output)) + return ''.join(buffer) - results = [] - visit(node, results) - return ''.join(results) - -def trace_node_to_tree(trace_handler: TraceHandler, node: TraceNode) -> None: +def display_trace_tree(trace_handler: TraceHandler) -> None: """ Visualize tree of a trace node going down to all its leaves. - Users should not be accessing this function. For debugging purposes. + Users should not normally be accessing this function. For debugging purposes. Args: trace_handler: Trace handler needed to pull user-defined identifiers of trace nodes. - node: Trace node that will function as the root. """ from anytree import Node, RenderTree - def visit(visitor: TraceNode, viz_parent=None): - nonlocal trace_handler - - if viz_parent is None: - viz_node = Node(f"{trace_handler.node_id_map[visitor]}:{visitor!r}") - else: - viz_node = Node(f"{trace_handler.node_id_map[visitor]}:{visitor!r}", parent=viz_parent) - - for child in visitor.children: - visit(child, viz_node) - return viz_node - viz_root = visit(node) + root = trace_handler.root() + trace_viz_map: Dict[TraceNode, Node] = {} + for node in root.traverse(bfs=False): + viz_parent = trace_viz_map.get(node.parent, None) + viz_node = Node( + f"{trace_handler.node_id_map[node]}:{node!r}", + parent=viz_parent + ) + trace_viz_map[node] = viz_node + viz_root = trace_viz_map[root] for pre, fill, node in RenderTree(viz_root): tree_str = u"%s%s" % (pre, node.name) - print(tree_str) + print(tree_str) \ No newline at end of file diff --git a/notebooks/unstable/State Debugging.ipynb b/notebooks/unstable/State Debugging.ipynb index 146c51338..d08bd0f41 100644 --- a/notebooks/unstable/State Debugging.ipynb +++ b/notebooks/unstable/State Debugging.ipynb @@ -6,19 +6,11 @@ "metadata": {}, "source": [ "from guidance.models import Transformers\n", - "from guidance import gen, user, system" - ], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "code", - "id": "4f43aabe74c4fc8c", - "metadata": {}, - "source": [ - "import logging\n", - "logging.basicConfig()\n", - "logging.getLogger().setLevel(logging.DEBUG)" + "from guidance import gen, user, system\n", + "\n", + "# import logging\n", + "# logging.basicConfig()\n", + "# logging.getLogger().setLevel(logging.DEBUG)" ], "outputs": [], "execution_count": null @@ -29,10 +21,14 @@ "metadata": {}, "source": [ "m0 = Transformers(\"gpt2\")\n", + "# m1 = m0 + \"Alms for the \" + gen(name=\"suffix\", max_tokens=5, stop='\\n')\n", + "\n", "with system():\n", " m1 = m0 + \"You are responsible for autocompleting a sentence.\"\n", "with user():\n", " m2 = m1 + \"Roses are red and \" + gen(name=\"suffix\", regex=r'[\\w\\s]{15,20}', max_tokens=20)\n", + "m3 = m2 + \">:(\"\n", + "\n", "# with user():\n", "# m3 = m2 + \"\\nWhat can I do?\"\n", "\n", @@ -49,66 +45,30 @@ "execution_count": null }, { - "metadata": {}, "cell_type": "code", - "source": "print(m2)", "id": "3698a47825dd2396", - "outputs": [], - "execution_count": null - }, - { "metadata": {}, - "cell_type": "code", "source": [ - "from guidance.visual import trace_node_to_str, trace_node_to_tree\n", - "\n", - "trace_node_to_tree(m0._trace_handler, m0._trace_handler.id_node_map[0])" + "print(m2)" ], - "id": "5a5d668a11bda28f", "outputs": [], "execution_count": null }, - { - "cell_type": "markdown", - "id": "956e746e986f1960", - "metadata": {}, - "source": [] - }, { "cell_type": "code", - "id": "120427693c64ef1f", + "id": "5a5d668a11bda28f", "metadata": {}, "source": [ - "from guidance.trace import visualize, visualize_output\n", + "from guidance.visual import display_trace_tree\n", "\n", - "visualize_output(m0._trace_handler.id_node_map[20])" - ], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "code", - "id": "cbbbe84572efd275", - "metadata": {}, - "source": [ - "print(str(m2))" - ], - "outputs": [], - "execution_count": null - }, - { - "cell_type": "code", - "id": "97fba3134abb4900", - "metadata": {}, - "source": [ - "m2" + "display_trace_tree(m0._trace_handler)" ], "outputs": [], "execution_count": null }, { "cell_type": "code", - "id": "2ed742e0fdbe6dd6", + "id": "37ce3ed8-698e-4115-8c6b-ba6663f6e2ad", "metadata": {}, "source": [], "outputs": [], From 0dc10148a669136b0f23ee771b08ab5bddcb47fa Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Sat, 28 Sep 2024 17:04:39 -0700 Subject: [PATCH 010/133] Black format on visual and trace module. --- guidance/trace/__init__.py | 2 +- guidance/trace/_trace.py | 35 +++++++++++++++++++++++++---------- guidance/visual/__init__.py | 3 ++- guidance/visual/_renderer.py | 14 +++++++++----- guidance/visual/_trace.py | 28 ++++++++++++++++------------ 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/guidance/trace/__init__.py b/guidance/trace/__init__.py index 52e626401..f70829da7 100644 --- a/guidance/trace/__init__.py +++ b/guidance/trace/__init__.py @@ -8,4 +8,4 @@ from ._trace import NodeAttr, InputAttr, OutputAttr, StatefulGuidanceInput, StatelessGuidanceInput from ._trace import LiteralInput, EmbeddedInput, ImageInput, RoleCloserInput, RoleOpenerInput -from ._trace import TextOutput, ImageOutput, CaptureOutput, TraceNode, TraceHandler \ No newline at end of file +from ._trace import TextOutput, ImageOutput, CaptureOutput, TraceNode, TraceHandler diff --git a/guidance/trace/_trace.py b/guidance/trace/_trace.py index b6ff3a6d0..e49e37e38 100644 --- a/guidance/trace/_trace.py +++ b/guidance/trace/_trace.py @@ -22,16 +22,19 @@ def __str__(self): class InputAttr(NodeAttr): """Input for a guidance program (i.e. literal or guidance grammar).""" + pass class OutputAttr(NodeAttr): """Output for a guidance program (i.e. text output).""" + pass class StatelessGuidanceInput(InputAttr): """Stateless guidance input (light wrapper).""" + value: Any def __repr__(self): @@ -40,6 +43,7 @@ def __repr__(self): class StatefulGuidanceInput(InputAttr): """Stateful guidance input (light wrapper).""" + value: Any def __repr__(self): @@ -48,17 +52,20 @@ def __repr__(self): class LiteralInput(InputAttr): """Text string as a literal.""" + value: str # NOTE(nopdive): Placeholder, needs to be filled once multimodal PR is in. class ImageInput(InputAttr): """Image input.""" + value: bytes class EmbeddedInput(InputAttr): """Text string with embedded guidance input.""" + value: str @@ -67,6 +74,7 @@ class RoleOpenerInput(InputAttr): This usually occurs as a role context and __enter__ is called. """ + name: str @@ -75,11 +83,13 @@ class RoleCloserInput(InputAttr): This usually occurs as a role context and __exit__ is called. """ + name: str class TextOutput(OutputAttr): """Text string.""" + value: str is_generated: bool = False token_count: int = 0 @@ -92,6 +102,7 @@ def __str__(self): # NOTE(nopdive): Placeholder, needs to be filled once multimodal PR is in. class ImageOutput(OutputAttr): """Image as bytes.""" + value: bytes @@ -100,6 +111,7 @@ class CaptureOutput(OutputAttr): If `value` is set to None, this means it's a reset (needed for append capture group outputs). """ + name: str value: Optional[str] = None is_append: bool = False @@ -111,6 +123,7 @@ def __str__(self): class TraceNode(BaseModel): """Trace node which associates inputs and outputs of a guidance program.""" + identifier: int = Field(default_factory=count().__next__) parent: Optional["TraceNode"] = None children: list["TraceNode"] = [] @@ -118,7 +131,7 @@ class TraceNode(BaseModel): output: Optional[OutputAttr] = None def add_child(self, child: "TraceNode") -> None: - """ Add a child node to the trace node. + """Add a child node to the trace node. Args: child: The child node to add. @@ -127,7 +140,7 @@ def add_child(self, child: "TraceNode") -> None: self.children.append(child) def remove_child(self, child: "TraceNode") -> None: - """ Remove a child node from the trace node. + """Remove a child node from the trace node. Args: child: The child node to remove. @@ -136,7 +149,7 @@ def remove_child(self, child: "TraceNode") -> None: self.children.remove(child) def ancestors(self) -> Generator["TraceNode", None, None]: - """ Yields ancestor trace nodes ending with root. + """Yields ancestor trace nodes ending with root. Yields: Ancestor trace nodes. @@ -146,9 +159,8 @@ def ancestors(self) -> Generator["TraceNode", None, None]: yield node.parent node = node.parent - def path(self) -> Generator["TraceNode", None, None]: - """ Yields path of from root to self inclusively. + """Yields path of from root to self inclusively. Yields: Trace nodes from root to self. @@ -157,7 +169,7 @@ def path(self) -> Generator["TraceNode", None, None]: yield self def root(self) -> "TraceNode": - """ Returns root by traversing parents of self. + """Returns root by traversing parents of self. Returns: Root of tree self is part of. @@ -169,7 +181,7 @@ def root(self) -> "TraceNode": return root def traverse(self, bfs: bool = True): - """ Traverse the trace nodes starting with self. + """Traverse the trace nodes starting with self. Args: bfs: Use breadth-first-search, otherwise depth-first-search. @@ -205,11 +217,14 @@ class TraceHandler(BaseModel): The requirement for holding all live traces ensures downstream consumers such as UI providers can do near-real-time partial updates. """ + id_node_map: Dict[int, TraceNode] = {} node_id_map: Dict[TraceNode, int] = {} - def update_node(self, identifier: int, parent_id: Optional[int], node_attr: Optional[NodeAttr] = None) -> TraceNode: - """ Update the trace node with the given identifier. + def update_node( + self, identifier: int, parent_id: Optional[int], node_attr: Optional[NodeAttr] = None + ) -> TraceNode: + """Update the trace node with the given identifier. If the trace node does not exist, it will be created. Both parent id and node attributes can be updated only once until further notice. @@ -244,7 +259,7 @@ def update_node(self, identifier: int, parent_id: Optional[int], node_attr: Opti return node def root(self) -> TraceNode: - """ Returns root node of trace handler. + """Returns root node of trace handler. Raises: Exception: If root cannot be found. diff --git a/guidance/visual/__init__.py b/guidance/visual/__init__.py index 1dd9c82cc..b51d7b81c 100644 --- a/guidance/visual/__init__.py +++ b/guidance/visual/__init__.py @@ -1,6 +1,7 @@ """User interface and other visual UX considerations.""" + # TODO(nopdive): implement stdout renderer from ._message import Message, TraceMessage, ResetDisplayMessage from ._renderer import AutoRenderer, JupyterHtmlRenderer -from ._trace import trace_node_to_str, display_trace_tree, trace_node_to_html \ No newline at end of file +from ._trace import trace_node_to_str, display_trace_tree, trace_node_to_html diff --git a/guidance/visual/_renderer.py b/guidance/visual/_renderer.py index 2d6e48986..e5bc91050 100644 --- a/guidance/visual/_renderer.py +++ b/guidance/visual/_renderer.py @@ -49,7 +49,9 @@ def update(self, message: Message) -> RenderUpdate: need_new_display = True else: # If we diverge from the model path, truncate and reset - last_trace_message = next(x for x in reversed(self._messages) if isinstance(x, TraceMessage)) + last_trace_message = next( + x for x in reversed(self._messages) if isinstance(x, TraceMessage) + ) last_trace_node = last_trace_message.trace_node if trace_node not in last_trace_node.path(): @@ -72,9 +74,12 @@ def update(self, message: Message) -> RenderUpdate: # If we are in a new Jupyter cell or execution, reset if ipython_imported: ipy = get_ipython() - cell_msg_id = ipy.get_parent()['msg_id'] + cell_msg_id = ipy.get_parent()["msg_id"] cell_exec_count = ipy.execution_count - if cell_msg_id != self._prev_cell_msg_id or cell_exec_count != self._prev_cell_exec_count: + if ( + cell_msg_id != self._prev_cell_msg_id + or cell_exec_count != self._prev_cell_exec_count + ): need_reset = True need_new_display = True logger.debug(f"NEED_RESET:jupyter:{cell_msg_id}|{cell_exec_count}") @@ -98,7 +103,7 @@ class Renderer: """Renders guidance model to a visual medium.""" def update(self, message: Message) -> None: - raise NotImplementedError('Update not implemented.') + raise NotImplementedError("Update not implemented.") class JupyterHtmlRenderer(Renderer): @@ -114,7 +119,6 @@ def update(self, message: Message) -> None: if isinstance(out_message, TraceMessage): last_trace_node = out_message.trace_node - if last_trace_node is not None: clear_output(wait=True) display(HTML(trace_node_to_html(last_trace_node, prettify_roles=False))) diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index 89264e38e..736566b33 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -1,7 +1,14 @@ import base64 from typing import Optional, Dict -from ..trace import TextOutput, TraceNode, TraceHandler, RoleOpenerInput, RoleCloserInput, ImageOutput +from ..trace import ( + TextOutput, + TraceNode, + TraceHandler, + RoleOpenerInput, + RoleCloserInput, + ImageOutput, +) import html span_start = "" @@ -9,7 +16,7 @@ def trace_node_to_html(node: TraceNode, prettify_roles=False) -> str: - """ Represents trace path as html string. + """Represents trace path as html string. Args: node: Trace node that designates the end of a trace path for HTML output. @@ -59,14 +66,14 @@ def trace_node_to_html(node: TraceNode, prettify_roles=False) -> str: buffer.insert( 0, - "
"
+        "
",
     )
     buffer.append("
") return "".join(buffer) def trace_node_to_str(node: TraceNode) -> str: - """ Visualize output attributes of a trace node up to the root. + """Visualize output attributes of a trace node up to the root. Users should not be accessing this function. For debugging purposes. @@ -79,11 +86,11 @@ def trace_node_to_str(node: TraceNode) -> str: for node in node.path(): if isinstance(node.output, TextOutput): buffer.append(str(node.output)) - return ''.join(buffer) + return "".join(buffer) def display_trace_tree(trace_handler: TraceHandler) -> None: - """ Visualize tree of a trace node going down to all its leaves. + """Visualize tree of a trace node going down to all its leaves. Users should not normally be accessing this function. For debugging purposes. @@ -96,13 +103,10 @@ def display_trace_tree(trace_handler: TraceHandler) -> None: trace_viz_map: Dict[TraceNode, Node] = {} for node in root.traverse(bfs=False): viz_parent = trace_viz_map.get(node.parent, None) - viz_node = Node( - f"{trace_handler.node_id_map[node]}:{node!r}", - parent=viz_parent - ) + viz_node = Node(f"{trace_handler.node_id_map[node]}:{node!r}", parent=viz_parent) trace_viz_map[node] = viz_node viz_root = trace_viz_map[root] for pre, fill, node in RenderTree(viz_root): - tree_str = u"%s%s" % (pre, node.name) - print(tree_str) \ No newline at end of file + tree_str = "%s%s" % (pre, node.name) + print(tree_str) From 7ac9f979acbba90fd97f78be5465027ad3aecc10 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 30 Sep 2024 10:23:18 -0700 Subject: [PATCH 011/133] Added client skeletal for Jupyter rendering. Uses stitch for kernel to client communication. Need to redesign and hook in instrumentation. --- .gitignore | 1 - client/graphpaper-inline/.gitignore | 3 + client/graphpaper-inline/TODO.txt | 2 + client/graphpaper-inline/dist/.gitignore | 2 + client/graphpaper-inline/package.json | 37 + client/graphpaper-inline/pnpm-lock.yaml | 3298 +++++++++++++++++ client/graphpaper-inline/postcss.config.js | 7 + client/graphpaper-inline/rollup.config.mjs | 56 + client/graphpaper-inline/src/App.svelte | 163 + client/graphpaper-inline/src/Minibar.svelte | 38 + .../src/ResizeListener.svelte | 32 + .../src/StitchHandler.svelte | 30 + client/graphpaper-inline/src/Tokengrid.svelte | 95 + client/graphpaper-inline/src/main.css | 3 + client/graphpaper-inline/src/main.js | 7 + client/graphpaper-inline/src/stitch.ts | 26 + client/graphpaper-inline/src/template.html | 12 + client/graphpaper-inline/tailwind.config.js | 21 + client/graphpaper-inline/tsconfig.json | 15 + 19 files changed, 3847 insertions(+), 1 deletion(-) create mode 100644 client/graphpaper-inline/.gitignore create mode 100644 client/graphpaper-inline/TODO.txt create mode 100644 client/graphpaper-inline/dist/.gitignore create mode 100644 client/graphpaper-inline/package.json create mode 100644 client/graphpaper-inline/pnpm-lock.yaml create mode 100644 client/graphpaper-inline/postcss.config.js create mode 100644 client/graphpaper-inline/rollup.config.mjs create mode 100644 client/graphpaper-inline/src/App.svelte create mode 100644 client/graphpaper-inline/src/Minibar.svelte create mode 100644 client/graphpaper-inline/src/ResizeListener.svelte create mode 100644 client/graphpaper-inline/src/StitchHandler.svelte create mode 100644 client/graphpaper-inline/src/Tokengrid.svelte create mode 100644 client/graphpaper-inline/src/main.css create mode 100644 client/graphpaper-inline/src/main.js create mode 100644 client/graphpaper-inline/src/stitch.ts create mode 100644 client/graphpaper-inline/src/template.html create mode 100644 client/graphpaper-inline/tailwind.config.js create mode 100644 client/graphpaper-inline/tsconfig.json diff --git a/.gitignore b/.gitignore index 8aff96dae..2e6406a1f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ __pycache__/ *.diskcache .ipynb_checkpoints node_modules -/client .eggs/ .env .DS_Store diff --git a/client/graphpaper-inline/.gitignore b/client/graphpaper-inline/.gitignore new file mode 100644 index 000000000..7fd339b0f --- /dev/null +++ b/client/graphpaper-inline/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +build/ +.DS_Store diff --git a/client/graphpaper-inline/TODO.txt b/client/graphpaper-inline/TODO.txt new file mode 100644 index 000000000..9289726e0 --- /dev/null +++ b/client/graphpaper-inline/TODO.txt @@ -0,0 +1,2 @@ +- Remove CDN font links (googlefonts) +- Connect non-generated tokens, images etc. \ No newline at end of file diff --git a/client/graphpaper-inline/dist/.gitignore b/client/graphpaper-inline/dist/.gitignore new file mode 100644 index 000000000..c96a04f00 --- /dev/null +++ b/client/graphpaper-inline/dist/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/client/graphpaper-inline/package.json b/client/graphpaper-inline/package.json new file mode 100644 index 000000000..f590ae321 --- /dev/null +++ b/client/graphpaper-inline/package.json @@ -0,0 +1,37 @@ +{ + "name": "graphpaper", + "version": "0.0.1", + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv dist" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^26.0.1", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^11.1.6", + "@types/d3-scale": "^4.0.8", + "@types/d3-scale-chromatic": "^3.0.3", + "autoprefixer": "^10.4.20", + "cssnano": "^7.0.5", + "postcss": "^8.4.41", + "rollup": "^4.21.0", + "rollup-plugin-copy": "^3.5.0", + "rollup-plugin-html-bundle": "^0.0.3", + "rollup-plugin-livereload": "^2.0.5", + "rollup-plugin-postcss": "^4.0.2", + "rollup-plugin-serve": "^1.1.1", + "rollup-plugin-svelte": "^7.2.2", + "sirv-cli": "^2.0.2", + "svelte": "^4.2.18", + "svelte-preprocess": "^6.0.2", + "tailwindcss": "^3.4.10", + "tslib": "^2.6.3", + "typescript": "^5.5.4" + }, + "dependencies": { + "d3-scale": "^4.0.2", + "d3-scale-chromatic": "^3.1.0" + } +} \ No newline at end of file diff --git a/client/graphpaper-inline/pnpm-lock.yaml b/client/graphpaper-inline/pnpm-lock.yaml new file mode 100644 index 000000000..f7dac1004 --- /dev/null +++ b/client/graphpaper-inline/pnpm-lock.yaml @@ -0,0 +1,3298 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + d3-scale: + specifier: ^4.0.2 + version: 4.0.2 + d3-scale-chromatic: + specifier: ^3.1.0 + version: 3.1.0 + devDependencies: + '@rollup/plugin-commonjs': + specifier: ^26.0.1 + version: 26.0.1(rollup@4.21.0) + '@rollup/plugin-node-resolve': + specifier: ^15.2.3 + version: 15.2.3(rollup@4.21.0) + '@rollup/plugin-terser': + specifier: ^0.4.4 + version: 0.4.4(rollup@4.21.0) + '@rollup/plugin-typescript': + specifier: ^11.1.6 + version: 11.1.6(rollup@4.21.0)(tslib@2.6.3)(typescript@5.5.4) + '@types/d3-scale': + specifier: ^4.0.8 + version: 4.0.8 + '@types/d3-scale-chromatic': + specifier: ^3.0.3 + version: 3.0.3 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.4.41) + cssnano: + specifier: ^7.0.5 + version: 7.0.5(postcss@8.4.41) + postcss: + specifier: ^8.4.41 + version: 8.4.41 + rollup: + specifier: ^4.21.0 + version: 4.21.0 + rollup-plugin-copy: + specifier: ^3.5.0 + version: 3.5.0 + rollup-plugin-html-bundle: + specifier: ^0.0.3 + version: 0.0.3 + rollup-plugin-livereload: + specifier: ^2.0.5 + version: 2.0.5 + rollup-plugin-postcss: + specifier: ^4.0.2 + version: 4.0.2(postcss@8.4.41) + rollup-plugin-serve: + specifier: ^1.1.1 + version: 1.1.1 + rollup-plugin-svelte: + specifier: ^7.2.2 + version: 7.2.2(rollup@4.21.0)(svelte@4.2.18) + sirv-cli: + specifier: ^2.0.2 + version: 2.0.2 + svelte: + specifier: ^4.2.18 + version: 4.2.18 + svelte-preprocess: + specifier: ^6.0.2 + version: 6.0.2(postcss-load-config@4.0.2(postcss@8.4.41))(postcss@8.4.41)(svelte@4.2.18)(typescript@5.5.4) + tailwindcss: + specifier: ^3.4.10 + version: 3.4.10 + tslib: + specifier: ^2.6.3 + version: 2.6.3 + typescript: + specifier: ^5.5.4 + version: 5.5.4 + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@polka/url@1.0.0-next.25': + resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} + + '@rollup/plugin-commonjs@26.0.1': + resolution: {integrity: sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@15.2.3': + resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-terser@0.4.4': + resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-typescript@11.1.6': + resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.14.0||^3.0.0||^4.0.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + + '@rollup/pluginutils@4.2.1': + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + + '@rollup/pluginutils@5.1.0': + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.21.0': + resolution: {integrity: sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.21.0': + resolution: {integrity: sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.21.0': + resolution: {integrity: sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.21.0': + resolution: {integrity: sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.21.0': + resolution: {integrity: sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.21.0': + resolution: {integrity: sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.21.0': + resolution: {integrity: sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.21.0': + resolution: {integrity: sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.0': + resolution: {integrity: sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.21.0': + resolution: {integrity: sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.21.0': + resolution: {integrity: sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.21.0': + resolution: {integrity: sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.21.0': + resolution: {integrity: sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.21.0': + resolution: {integrity: sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.21.0': + resolution: {integrity: sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.21.0': + resolution: {integrity: sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==} + cpu: [x64] + os: [win32] + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@types/d3-scale-chromatic@3.0.3': + resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==} + + '@types/d3-scale@4.0.8': + resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} + + '@types/d3-time@3.0.3': + resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/fs-extra@8.1.5': + resolution: {integrity: sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==} + + '@types/glob@7.2.0': + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + + '@types/minimatch@5.1.2': + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + + '@types/node@22.5.0': + resolution: {integrity: sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.23.3: + resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + caniuse-api@3.0.0: + resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} + + caniuse-lite@1.0.30001651: + resolution: {integrity: sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + code-red@1.0.4: + resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + + colorette@1.4.0: + resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + concat-with-sourcemaps@1.1.0: + resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} + + console-clear@1.1.1: + resolution: {integrity: sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==} + engines: {node: '>=4'} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + css-declaration-sorter@6.4.1: + resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} + engines: {node: ^10 || ^12 || >=14} + peerDependencies: + postcss: ^8.0.9 + + css-declaration-sorter@7.2.0: + resolution: {integrity: sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.0.9 + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssnano-preset-default@5.2.14: + resolution: {integrity: sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano-preset-default@7.0.5: + resolution: {integrity: sha512-Jbzja0xaKwc5JzxPQoc+fotKpYtWEu4wQLMQe29CM0FjjdRjA4omvbGHl2DTGgARKxSTpPssBsok+ixv8uTBqw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + cssnano-utils@3.1.0: + resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano-utils@5.0.0: + resolution: {integrity: sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + cssnano@5.1.15: + resolution: {integrity: sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano@7.0.5: + resolution: {integrity: sha512-Aq0vqBLtpTT5Yxj+hLlLfNPFuRQCDIjx5JQAhhaedQKLNDvDGeVziF24PS+S1f0Z5KCxWvw0QVI3VNHNBITxVQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.13: + resolution: {integrity: sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + estree-walker@0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + generic-names@4.0.0: + resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} + + get-port@3.2.0: + resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} + engines: {node: '>=4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globby@10.0.1: + resolution: {integrity: sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==} + engines: {node: '>=8'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + icss-replace-symbols@1.1.0: + resolution: {integrity: sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==} + + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-cwd@3.0.0: + resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==} + engines: {node: '>=8'} + + import-from@3.0.0: + resolution: {integrity: sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-object@3.0.1: + resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} + engines: {node: '>=0.10.0'} + + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + + is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + livereload-js@3.4.1: + resolution: {integrity: sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==} + + livereload@0.9.3: + resolution: {integrity: sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==} + engines: {node: '>=8.0.0'} + hasBin: true + + loader-utils@3.3.1: + resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} + engines: {node: '>= 12.13.0'} + + local-access@1.1.0: + resolution: {integrity: sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==} + engines: {node: '>=6'} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + magic-string@0.30.11: + resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + opener@1.5.2: + resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} + hasBin: true + + opts@2.0.2: + resolution: {integrity: sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==} + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-queue@6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + package-json-from-dist@1.0.0: + resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pify@5.0.0: + resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} + engines: {node: '>=10'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + postcss-calc@10.0.2: + resolution: {integrity: sha512-DT/Wwm6fCKgpYVI7ZEWuPJ4az8hiEHtCUeYjZXqU7Ou4QqYh1Df2yCQ7Ca6N7xqKPFkxN3fhf+u9KSoOCJNAjg==} + engines: {node: ^18.12 || ^20.9 || >=22.0} + peerDependencies: + postcss: ^8.4.38 + + postcss-calc@8.2.4: + resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} + peerDependencies: + postcss: ^8.2.2 + + postcss-colormin@5.3.1: + resolution: {integrity: sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-colormin@7.0.2: + resolution: {integrity: sha512-YntRXNngcvEvDbEjTdRWGU606eZvB5prmHG4BF0yLmVpamXbpsRJzevyy6MZVyuecgzI2AWAlvFi8DAeCqwpvA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-convert-values@5.1.3: + resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-convert-values@7.0.3: + resolution: {integrity: sha512-yJhocjCs2SQer0uZ9lXTMOwDowbxvhwFVrZeS6NPEij/XXthl73ggUmfwVvJM+Vaj5gtCKJV1jiUu4IhAUkX/Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-discard-comments@5.1.2: + resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-comments@7.0.2: + resolution: {integrity: sha512-/Hje9Ls1IYcB9duELO/AyDUJI6aQVY3h5Rj1ziXgaLYCTi1iVBLnjg/TS0D6NszR/kDG6I86OwLmAYe+bvJjiQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-discard-duplicates@5.1.0: + resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-duplicates@7.0.1: + resolution: {integrity: sha512-oZA+v8Jkpu1ct/xbbrntHRsfLGuzoP+cpt0nJe5ED2FQF8n8bJtn7Bo28jSmBYwqgqnqkuSXJfSUEE7if4nClQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-discard-empty@5.1.1: + resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-empty@7.0.0: + resolution: {integrity: sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-discard-overridden@5.1.0: + resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-overridden@7.0.0: + resolution: {integrity: sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@3.1.4: + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-merge-longhand@5.1.7: + resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-merge-longhand@7.0.3: + resolution: {integrity: sha512-8waYomFxshdv6M9Em3QRM9MettRLDRcH2JQi2l0Z1KlYD/vhal3gbkeSES0NuACXOlZBB0V/B0AseHZaklzWOA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-merge-rules@5.1.4: + resolution: {integrity: sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-merge-rules@7.0.3: + resolution: {integrity: sha512-2eSas2p3voPxNfdI5sQrvIkMaeUHpVc3EezgVs18hz/wRTQAC9U99tp9j3W5Jx9/L3qHkEDvizEx/LdnmumIvQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-minify-font-values@5.1.0: + resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-font-values@7.0.0: + resolution: {integrity: sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-minify-gradients@5.1.1: + resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-gradients@7.0.0: + resolution: {integrity: sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-minify-params@5.1.4: + resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-params@7.0.2: + resolution: {integrity: sha512-nyqVLu4MFl9df32zTsdcLqCFfE/z2+f8GE1KHPxWOAmegSo6lpV2GNy5XQvrzwbLmiU7d+fYay4cwto1oNdAaQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-minify-selectors@5.2.1: + resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-selectors@7.0.3: + resolution: {integrity: sha512-SxTgUQSgBk6wEqzQZKEv1xQYIp9UBju6no9q+npohzSdhuSICQdkqmD1UMKkZWItS3olJSJMDDEY9WOJ5oGJew==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.0.5: + resolution: {integrity: sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.0: + resolution: {integrity: sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules@4.3.1: + resolution: {integrity: sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==} + peerDependencies: + postcss: ^8.0.0 + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-normalize-charset@5.1.0: + resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-charset@7.0.0: + resolution: {integrity: sha512-ABisNUXMeZeDNzCQxPxBCkXexvBrUHV+p7/BXOY+ulxkcjUZO0cp8ekGBwvIh2LbCwnWbyMPNJVtBSdyhM2zYQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-normalize-display-values@5.1.0: + resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-display-values@7.0.0: + resolution: {integrity: sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-normalize-positions@5.1.1: + resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-positions@7.0.0: + resolution: {integrity: sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-normalize-repeat-style@5.1.1: + resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-repeat-style@7.0.0: + resolution: {integrity: sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-normalize-string@5.1.0: + resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-string@7.0.0: + resolution: {integrity: sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-normalize-timing-functions@5.1.0: + resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-timing-functions@7.0.0: + resolution: {integrity: sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-normalize-unicode@5.1.1: + resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-unicode@7.0.2: + resolution: {integrity: sha512-ztisabK5C/+ZWBdYC+Y9JCkp3M9qBv/XFvDtSw0d/XwfT3UaKeW/YTm/MD/QrPNxuecia46vkfEhewjwcYFjkg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-normalize-url@5.1.0: + resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-url@7.0.0: + resolution: {integrity: sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-normalize-whitespace@5.1.1: + resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-whitespace@7.0.0: + resolution: {integrity: sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-ordered-values@5.1.3: + resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-ordered-values@7.0.1: + resolution: {integrity: sha512-irWScWRL6nRzYmBOXReIKch75RRhNS86UPUAxXdmW/l0FcAsg0lvAXQCby/1lymxn/o0gVa6Rv/0f03eJOwHxw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-reduce-initial@5.1.2: + resolution: {integrity: sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-reduce-initial@7.0.2: + resolution: {integrity: sha512-pOnu9zqQww7dEKf62Nuju6JgsW2V0KRNBHxeKohU+JkHd/GAH5uvoObqFLqkeB2n20mr6yrlWDvo5UBU5GnkfA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-reduce-transforms@5.1.0: + resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-reduce-transforms@7.0.0: + resolution: {integrity: sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-svgo@5.1.0: + resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-svgo@7.0.1: + resolution: {integrity: sha512-0WBUlSL4lhD9rA5k1e5D8EN5wCEyZD6HJk0jIvRxl+FDVOMlJ7DePHYWGGVc5QRqrJ3/06FTXM0bxjmJpmTPSA==} + engines: {node: ^18.12.0 || ^20.9.0 || >= 18} + peerDependencies: + postcss: ^8.4.31 + + postcss-unique-selectors@5.1.1: + resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-unique-selectors@7.0.2: + resolution: {integrity: sha512-CjSam+7Vf8cflJQsHrMS0P2hmy9u0+n/P001kb5eAszLmhjMqrt/i5AqQuNFihhViwDvEAezqTmXqaYXL2ugMw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.41: + resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==} + engines: {node: ^10 || ^12 || >=14} + + promise.series@0.2.0: + resolution: {integrity: sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==} + engines: {node: '>=0.12'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup-plugin-copy@3.5.0: + resolution: {integrity: sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==} + engines: {node: '>=8.3'} + + rollup-plugin-html-bundle@0.0.3: + resolution: {integrity: sha512-vGMJTnpb57cT8p/BL2igUdohEAofxebRujd11Fk1ZY2zE0xGa3YMvzX4PH1kRUKm4nuQvFeW3ZdIksB9ZGzurw==} + + rollup-plugin-livereload@2.0.5: + resolution: {integrity: sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==} + engines: {node: '>=8.3'} + + rollup-plugin-postcss@4.0.2: + resolution: {integrity: sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==} + engines: {node: '>=10'} + peerDependencies: + postcss: 8.x + + rollup-plugin-serve@1.1.1: + resolution: {integrity: sha512-H0VarZRtFR0lfiiC9/P8jzCDvtFf1liOX4oSdIeeYqUCKrmFA7vNiQ0rg2D+TuoP7leaa/LBR8XBts5viF6lnw==} + + rollup-plugin-svelte@7.2.2: + resolution: {integrity: sha512-hgnIblTRewaBEVQD6N0Q43o+y6q1TmDRhBjaEzQCi50bs8TXqjc+d1zFZyE8tsfgcfNHZQzclh4RxlFUB85H8Q==} + engines: {node: '>=10'} + peerDependencies: + rollup: '>=2.0.0' + svelte: '>=3.5.0' + + rollup-pluginutils@2.8.2: + resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} + + rollup@4.21.0: + resolution: {integrity: sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-identifier@0.4.2: + resolution: {integrity: sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==} + + semiver@1.1.0: + resolution: {integrity: sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==} + engines: {node: '>=6'} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sirv-cli@2.0.2: + resolution: {integrity: sha512-OtSJDwxsF1NWHc7ps3Sa0s+dPtP15iQNJzfKVz+MxkEo3z72mCD+yu30ct79rPr0CaV1HXSOBp+MIY5uIhHZ1A==} + engines: {node: '>= 10'} + hasBin: true + + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + smob@1.5.0: + resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} + + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + + string-hash@1.1.3: + resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + style-inject@0.3.0: + resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} + + stylehacks@5.1.1: + resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + stylehacks@7.0.3: + resolution: {integrity: sha512-4DqtecvI/Nd+2BCvW9YEF6lhBN5UM50IJ1R3rnEAhBwbCKf4VehRf+uqvnVArnBayjYD/WtT3g0G/HSRxWfTRg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.4.31 + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svelte-preprocess@6.0.2: + resolution: {integrity: sha512-OvDTLfaOkkhjprbDKO0SOCkjNYuHy16dbD4SpqbIi6QiabOMHxRT4km5/dzbFFkmW1L0E2INF3MFltG2pgOyKQ==} + engines: {node: '>= 18.0.0'} + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + postcss: ^7 || ^8 + postcss-load-config: '>=3' + pug: ^3.0.0 + sass: ^1.26.8 + stylus: '>=0.55' + sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 + svelte: ^4.0.0 || ^5.0.0-next.100 || ^5.0.0 + typescript: ^5.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + + svelte@4.2.18: + resolution: {integrity: sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==} + engines: {node: '>=16'} + + svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} + engines: {node: '>=14.0.0'} + hasBin: true + + tailwindcss@3.4.10: + resolution: {integrity: sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==} + engines: {node: '>=14.0.0'} + hasBin: true + + terser@5.31.6: + resolution: {integrity: sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==} + engines: {node: '>=10'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tinydate@1.3.0: + resolution: {integrity: sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==} + engines: {node: '>=4'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + update-browserslist-db@1.1.0: + resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.5.0: + resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} + engines: {node: '>= 14'} + hasBin: true + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/source-map@0.3.6': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@polka/url@1.0.0-next.25': {} + + '@rollup/plugin-commonjs@26.0.1(rollup@4.21.0)': + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.21.0) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 10.4.5 + is-reference: 1.2.1 + magic-string: 0.30.11 + optionalDependencies: + rollup: 4.21.0 + + '@rollup/plugin-node-resolve@15.2.3(rollup@4.21.0)': + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.21.0) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-builtin-module: 3.2.1 + is-module: 1.0.0 + resolve: 1.22.8 + optionalDependencies: + rollup: 4.21.0 + + '@rollup/plugin-terser@0.4.4(rollup@4.21.0)': + dependencies: + serialize-javascript: 6.0.2 + smob: 1.5.0 + terser: 5.31.6 + optionalDependencies: + rollup: 4.21.0 + + '@rollup/plugin-typescript@11.1.6(rollup@4.21.0)(tslib@2.6.3)(typescript@5.5.4)': + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.21.0) + resolve: 1.22.8 + typescript: 5.5.4 + optionalDependencies: + rollup: 4.21.0 + tslib: 2.6.3 + + '@rollup/pluginutils@4.2.1': + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + + '@rollup/pluginutils@5.1.0(rollup@4.21.0)': + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 4.21.0 + + '@rollup/rollup-android-arm-eabi@4.21.0': + optional: true + + '@rollup/rollup-android-arm64@4.21.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.21.0': + optional: true + + '@rollup/rollup-darwin-x64@4.21.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.21.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.21.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.21.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.21.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.21.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.21.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.21.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.21.0': + optional: true + + '@trysound/sax@0.2.0': {} + + '@types/d3-scale-chromatic@3.0.3': {} + + '@types/d3-scale@4.0.8': + dependencies: + '@types/d3-time': 3.0.3 + + '@types/d3-time@3.0.3': {} + + '@types/estree@1.0.5': {} + + '@types/fs-extra@8.1.5': + dependencies: + '@types/node': 22.5.0 + + '@types/glob@7.2.0': + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 22.5.0 + + '@types/minimatch@5.1.2': {} + + '@types/node@22.5.0': + dependencies: + undici-types: 6.19.8 + + '@types/resolve@1.20.2': {} + + acorn@8.12.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + array-union@2.1.0: {} + + autoprefixer@10.4.20(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + caniuse-lite: 1.0.30001651 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.1 + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + axobject-query@4.1.0: {} + + balanced-match@1.0.2: {} + + binary-extensions@2.3.0: {} + + boolbase@1.0.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.23.3: + dependencies: + caniuse-lite: 1.0.30001651 + electron-to-chromium: 1.5.13 + node-releases: 2.0.18 + update-browserslist-db: 1.1.0(browserslist@4.23.3) + + buffer-from@1.1.2: {} + + builtin-modules@3.3.0: {} + + camelcase-css@2.0.1: {} + + caniuse-api@3.0.0: + dependencies: + browserslist: 4.23.3 + caniuse-lite: 1.0.30001651 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + + caniuse-lite@1.0.30001651: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + code-red@1.0.4: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@types/estree': 1.0.5 + acorn: 8.12.1 + estree-walker: 3.0.3 + periscopic: 3.1.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colord@2.9.3: {} + + colorette@1.4.0: {} + + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@7.2.0: {} + + commondir@1.0.1: {} + + concat-map@0.0.1: {} + + concat-with-sourcemaps@1.1.0: + dependencies: + source-map: 0.6.1 + + console-clear@1.1.1: {} + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-declaration-sorter@6.4.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + css-declaration-sorter@7.2.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-select@5.1.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.0 + + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.0 + + css-what@6.1.0: {} + + cssesc@3.0.0: {} + + cssnano-preset-default@5.2.14(postcss@8.4.41): + dependencies: + css-declaration-sorter: 6.4.1(postcss@8.4.41) + cssnano-utils: 3.1.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-calc: 8.2.4(postcss@8.4.41) + postcss-colormin: 5.3.1(postcss@8.4.41) + postcss-convert-values: 5.1.3(postcss@8.4.41) + postcss-discard-comments: 5.1.2(postcss@8.4.41) + postcss-discard-duplicates: 5.1.0(postcss@8.4.41) + postcss-discard-empty: 5.1.1(postcss@8.4.41) + postcss-discard-overridden: 5.1.0(postcss@8.4.41) + postcss-merge-longhand: 5.1.7(postcss@8.4.41) + postcss-merge-rules: 5.1.4(postcss@8.4.41) + postcss-minify-font-values: 5.1.0(postcss@8.4.41) + postcss-minify-gradients: 5.1.1(postcss@8.4.41) + postcss-minify-params: 5.1.4(postcss@8.4.41) + postcss-minify-selectors: 5.2.1(postcss@8.4.41) + postcss-normalize-charset: 5.1.0(postcss@8.4.41) + postcss-normalize-display-values: 5.1.0(postcss@8.4.41) + postcss-normalize-positions: 5.1.1(postcss@8.4.41) + postcss-normalize-repeat-style: 5.1.1(postcss@8.4.41) + postcss-normalize-string: 5.1.0(postcss@8.4.41) + postcss-normalize-timing-functions: 5.1.0(postcss@8.4.41) + postcss-normalize-unicode: 5.1.1(postcss@8.4.41) + postcss-normalize-url: 5.1.0(postcss@8.4.41) + postcss-normalize-whitespace: 5.1.1(postcss@8.4.41) + postcss-ordered-values: 5.1.3(postcss@8.4.41) + postcss-reduce-initial: 5.1.2(postcss@8.4.41) + postcss-reduce-transforms: 5.1.0(postcss@8.4.41) + postcss-svgo: 5.1.0(postcss@8.4.41) + postcss-unique-selectors: 5.1.1(postcss@8.4.41) + + cssnano-preset-default@7.0.5(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + css-declaration-sorter: 7.2.0(postcss@8.4.41) + cssnano-utils: 5.0.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-calc: 10.0.2(postcss@8.4.41) + postcss-colormin: 7.0.2(postcss@8.4.41) + postcss-convert-values: 7.0.3(postcss@8.4.41) + postcss-discard-comments: 7.0.2(postcss@8.4.41) + postcss-discard-duplicates: 7.0.1(postcss@8.4.41) + postcss-discard-empty: 7.0.0(postcss@8.4.41) + postcss-discard-overridden: 7.0.0(postcss@8.4.41) + postcss-merge-longhand: 7.0.3(postcss@8.4.41) + postcss-merge-rules: 7.0.3(postcss@8.4.41) + postcss-minify-font-values: 7.0.0(postcss@8.4.41) + postcss-minify-gradients: 7.0.0(postcss@8.4.41) + postcss-minify-params: 7.0.2(postcss@8.4.41) + postcss-minify-selectors: 7.0.3(postcss@8.4.41) + postcss-normalize-charset: 7.0.0(postcss@8.4.41) + postcss-normalize-display-values: 7.0.0(postcss@8.4.41) + postcss-normalize-positions: 7.0.0(postcss@8.4.41) + postcss-normalize-repeat-style: 7.0.0(postcss@8.4.41) + postcss-normalize-string: 7.0.0(postcss@8.4.41) + postcss-normalize-timing-functions: 7.0.0(postcss@8.4.41) + postcss-normalize-unicode: 7.0.2(postcss@8.4.41) + postcss-normalize-url: 7.0.0(postcss@8.4.41) + postcss-normalize-whitespace: 7.0.0(postcss@8.4.41) + postcss-ordered-values: 7.0.1(postcss@8.4.41) + postcss-reduce-initial: 7.0.2(postcss@8.4.41) + postcss-reduce-transforms: 7.0.0(postcss@8.4.41) + postcss-svgo: 7.0.1(postcss@8.4.41) + postcss-unique-selectors: 7.0.2(postcss@8.4.41) + + cssnano-utils@3.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + cssnano-utils@5.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + cssnano@5.1.15(postcss@8.4.41): + dependencies: + cssnano-preset-default: 5.2.14(postcss@8.4.41) + lilconfig: 2.1.0 + postcss: 8.4.41 + yaml: 1.10.2 + + cssnano@7.0.5(postcss@8.4.41): + dependencies: + cssnano-preset-default: 7.0.5(postcss@8.4.41) + lilconfig: 3.1.2 + postcss: 8.4.41 + + csso@4.2.0: + dependencies: + css-tree: 1.1.3 + + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-color@3.1.0: {} + + d3-format@3.1.0: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + deepmerge@4.3.1: {} + + dequal@2.0.3: {} + + didyoumean@1.2.2: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dlv@1.1.3: {} + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + domutils@3.1.0: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.13: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + entities@2.2.0: {} + + entities@4.5.0: {} + + escalade@3.1.2: {} + + estree-walker@0.6.1: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + + eventemitter3@4.0.7: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.7 + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + fraction.js@4.3.7: {} + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + generic-names@4.0.0: + dependencies: + loader-utils: 3.3.1 + + get-port@3.2.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globby@10.0.1: + dependencies: + '@types/glob': 7.2.0 + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + glob: 7.2.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + icss-replace-symbols@1.1.0: {} + + icss-utils@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + ignore@5.3.2: {} + + import-cwd@3.0.0: + dependencies: + import-from: 3.0.0 + + import-from@3.0.0: + dependencies: + resolve-from: 5.0.0 + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + internmap@2.0.3: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-module@1.0.0: {} + + is-number@7.0.0: {} + + is-plain-object@3.0.1: {} + + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.5 + + is-reference@3.0.2: + dependencies: + '@types/estree': 1.0.5 + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@1.21.6: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + kleur@4.1.5: {} + + lilconfig@2.1.0: {} + + lilconfig@3.1.2: {} + + lines-and-columns@1.2.4: {} + + livereload-js@3.4.1: {} + + livereload@0.9.3: + dependencies: + chokidar: 3.6.0 + livereload-js: 3.4.1 + opts: 2.0.2 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + loader-utils@3.3.1: {} + + local-access@1.1.0: {} + + locate-character@3.0.0: {} + + lodash.camelcase@4.3.0: {} + + lodash.memoize@4.1.2: {} + + lodash.uniq@4.5.0: {} + + lru-cache@10.4.3: {} + + magic-string@0.30.11: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + mdn-data@2.0.14: {} + + mdn-data@2.0.28: {} + + mdn-data@2.0.30: {} + + merge2@1.4.1: {} + + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime@2.6.0: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.1.2: {} + + mri@1.2.0: {} + + mrmime@2.0.0: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.7: {} + + node-releases@2.0.18: {} + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + normalize-url@6.1.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + opener@1.5.2: {} + + opts@2.0.2: {} + + p-finally@1.0.0: {} + + p-queue@6.6.2: + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + package-json-from-dist@1.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-type@4.0.0: {} + + periscopic@3.1.0: + dependencies: + '@types/estree': 1.0.5 + estree-walker: 3.0.3 + is-reference: 3.0.2 + + picocolors@1.0.1: {} + + picomatch@2.3.1: {} + + pify@2.3.0: {} + + pify@5.0.0: {} + + pirates@4.0.6: {} + + postcss-calc@10.0.2(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + + postcss-calc@8.2.4(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + + postcss-colormin@5.3.1(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-colormin@7.0.2(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-convert-values@5.1.3(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-convert-values@7.0.3(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-discard-comments@5.1.2(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-discard-comments@7.0.2(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-discard-duplicates@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-discard-duplicates@7.0.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-discard-empty@5.1.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-discard-empty@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-discard-overridden@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-discard-overridden@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-import@15.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.41): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.41 + + postcss-load-config@3.1.4(postcss@8.4.41): + dependencies: + lilconfig: 2.1.0 + yaml: 1.10.2 + optionalDependencies: + postcss: 8.4.41 + + postcss-load-config@4.0.2(postcss@8.4.41): + dependencies: + lilconfig: 3.1.2 + yaml: 2.5.0 + optionalDependencies: + postcss: 8.4.41 + + postcss-merge-longhand@5.1.7(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + stylehacks: 5.1.1(postcss@8.4.41) + + postcss-merge-longhand@7.0.3(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + stylehacks: 7.0.3(postcss@8.4.41) + + postcss-merge-rules@5.1.4(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + caniuse-api: 3.0.0 + cssnano-utils: 3.1.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-merge-rules@7.0.3(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + caniuse-api: 3.0.0 + cssnano-utils: 5.0.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-minify-font-values@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-minify-font-values@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-minify-gradients@5.1.1(postcss@8.4.41): + dependencies: + colord: 2.9.3 + cssnano-utils: 3.1.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-minify-gradients@7.0.0(postcss@8.4.41): + dependencies: + colord: 2.9.3 + cssnano-utils: 5.0.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-minify-params@5.1.4(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + cssnano-utils: 3.1.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-minify-params@7.0.2(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + cssnano-utils: 5.0.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-minify-selectors@5.2.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-minify-selectors@7.0.3(postcss@8.4.41): + dependencies: + cssesc: 3.0.0 + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-modules-extract-imports@3.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-modules-local-by-default@4.0.5(postcss@8.4.41): + dependencies: + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-modules-values@4.0.0(postcss@8.4.41): + dependencies: + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 + + postcss-modules@4.3.1(postcss@8.4.41): + dependencies: + generic-names: 4.0.0 + icss-replace-symbols: 1.1.0 + lodash.camelcase: 4.3.0 + postcss: 8.4.41 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.41) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.41) + postcss-modules-scope: 3.2.0(postcss@8.4.41) + postcss-modules-values: 4.0.0(postcss@8.4.41) + string-hash: 1.1.3 + + postcss-nested@6.2.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-normalize-charset@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-normalize-charset@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + + postcss-normalize-display-values@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-display-values@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-positions@5.1.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-positions@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-repeat-style@5.1.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-repeat-style@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-string@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-string@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-timing-functions@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-timing-functions@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-unicode@5.1.1(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-unicode@7.0.2(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-url@5.1.0(postcss@8.4.41): + dependencies: + normalize-url: 6.1.0 + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-url@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-whitespace@5.1.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-normalize-whitespace@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-ordered-values@5.1.3(postcss@8.4.41): + dependencies: + cssnano-utils: 3.1.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-ordered-values@7.0.1(postcss@8.4.41): + dependencies: + cssnano-utils: 5.0.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-reduce-initial@5.1.2(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + caniuse-api: 3.0.0 + postcss: 8.4.41 + + postcss-reduce-initial@7.0.2(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + caniuse-api: 3.0.0 + postcss: 8.4.41 + + postcss-reduce-transforms@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-reduce-transforms@7.0.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-svgo@5.1.0(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + svgo: 2.8.0 + + postcss-svgo@7.0.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-value-parser: 4.2.0 + svgo: 3.3.2 + + postcss-unique-selectors@5.1.1(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-unique-selectors@7.0.2(postcss@8.4.41): + dependencies: + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.4.41: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + + promise.series@0.2.0: {} + + queue-microtask@1.2.3: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + resolve-from@5.0.0: {} + + resolve.exports@2.0.2: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.0.4: {} + + rollup-plugin-copy@3.5.0: + dependencies: + '@types/fs-extra': 8.1.5 + colorette: 1.4.0 + fs-extra: 8.1.0 + globby: 10.0.1 + is-plain-object: 3.0.1 + + rollup-plugin-html-bundle@0.0.3: {} + + rollup-plugin-livereload@2.0.5: + dependencies: + livereload: 0.9.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + rollup-plugin-postcss@4.0.2(postcss@8.4.41): + dependencies: + chalk: 4.1.2 + concat-with-sourcemaps: 1.1.0 + cssnano: 5.1.15(postcss@8.4.41) + import-cwd: 3.0.0 + p-queue: 6.6.2 + pify: 5.0.0 + postcss: 8.4.41 + postcss-load-config: 3.1.4(postcss@8.4.41) + postcss-modules: 4.3.1(postcss@8.4.41) + promise.series: 0.2.0 + resolve: 1.22.8 + rollup-pluginutils: 2.8.2 + safe-identifier: 0.4.2 + style-inject: 0.3.0 + transitivePeerDependencies: + - ts-node + + rollup-plugin-serve@1.1.1: + dependencies: + mime: 2.6.0 + opener: 1.5.2 + + rollup-plugin-svelte@7.2.2(rollup@4.21.0)(svelte@4.2.18): + dependencies: + '@rollup/pluginutils': 4.2.1 + resolve.exports: 2.0.2 + rollup: 4.21.0 + svelte: 4.2.18 + + rollup-pluginutils@2.8.2: + dependencies: + estree-walker: 0.6.1 + + rollup@4.21.0: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.21.0 + '@rollup/rollup-android-arm64': 4.21.0 + '@rollup/rollup-darwin-arm64': 4.21.0 + '@rollup/rollup-darwin-x64': 4.21.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.21.0 + '@rollup/rollup-linux-arm-musleabihf': 4.21.0 + '@rollup/rollup-linux-arm64-gnu': 4.21.0 + '@rollup/rollup-linux-arm64-musl': 4.21.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.21.0 + '@rollup/rollup-linux-riscv64-gnu': 4.21.0 + '@rollup/rollup-linux-s390x-gnu': 4.21.0 + '@rollup/rollup-linux-x64-gnu': 4.21.0 + '@rollup/rollup-linux-x64-musl': 4.21.0 + '@rollup/rollup-win32-arm64-msvc': 4.21.0 + '@rollup/rollup-win32-ia32-msvc': 4.21.0 + '@rollup/rollup-win32-x64-msvc': 4.21.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safe-buffer@5.2.1: {} + + safe-identifier@0.4.2: {} + + semiver@1.1.0: {} + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@4.1.0: {} + + sirv-cli@2.0.2: + dependencies: + console-clear: 1.1.1 + get-port: 3.2.0 + kleur: 4.1.5 + local-access: 1.1.0 + sade: 1.8.1 + semiver: 1.1.0 + sirv: 2.0.4 + tinydate: 1.3.0 + + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.25 + mrmime: 2.0.0 + totalist: 3.0.1 + + slash@3.0.0: {} + + smob@1.5.0: {} + + source-map-js@1.2.0: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + stable@0.1.8: {} + + string-hash@1.1.3: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + + style-inject@0.3.0: {} + + stylehacks@5.1.1(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + stylehacks@7.0.3(postcss@8.4.41): + dependencies: + browserslist: 4.23.3 + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svelte-preprocess@6.0.2(postcss-load-config@4.0.2(postcss@8.4.41))(postcss@8.4.41)(svelte@4.2.18)(typescript@5.5.4): + dependencies: + svelte: 4.2.18 + optionalDependencies: + postcss: 8.4.41 + postcss-load-config: 4.0.2(postcss@8.4.41) + typescript: 5.5.4 + + svelte@4.2.18: + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + '@types/estree': 1.0.5 + acorn: 8.12.1 + aria-query: 5.3.0 + axobject-query: 4.1.0 + code-red: 1.0.4 + css-tree: 2.3.1 + estree-walker: 3.0.3 + is-reference: 3.0.2 + locate-character: 3.0.0 + magic-string: 0.30.11 + periscopic: 3.1.0 + + svgo@2.8.0: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.0.1 + stable: 0.1.8 + + svgo@3.3.2: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 5.1.0 + css-tree: 2.3.1 + css-what: 6.1.0 + csso: 5.0.5 + picocolors: 1.0.1 + + tailwindcss@3.4.10: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.7 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.1 + postcss: 8.4.41 + postcss-import: 15.1.0(postcss@8.4.41) + postcss-js: 4.0.1(postcss@8.4.41) + postcss-load-config: 4.0.2(postcss@8.4.41) + postcss-nested: 6.2.0(postcss@8.4.41) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + terser@5.31.6: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.12.1 + commander: 2.20.3 + source-map-support: 0.5.21 + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + tinydate@1.3.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + totalist@3.0.1: {} + + ts-interface-checker@0.1.13: {} + + tslib@2.6.3: {} + + typescript@5.5.4: {} + + undici-types@6.19.8: {} + + universalify@0.1.2: {} + + update-browserslist-db@1.1.0(browserslist@4.23.3): + dependencies: + browserslist: 4.23.3 + escalade: 3.1.2 + picocolors: 1.0.1 + + util-deprecate@1.0.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + ws@7.5.10: {} + + yaml@1.10.2: {} + + yaml@2.5.0: {} diff --git a/client/graphpaper-inline/postcss.config.js b/client/graphpaper-inline/postcss.config.js new file mode 100644 index 000000000..48f950f50 --- /dev/null +++ b/client/graphpaper-inline/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + cssnano: { preset: 'default' } + } +} \ No newline at end of file diff --git a/client/graphpaper-inline/rollup.config.mjs b/client/graphpaper-inline/rollup.config.mjs new file mode 100644 index 000000000..64ba8af66 --- /dev/null +++ b/client/graphpaper-inline/rollup.config.mjs @@ -0,0 +1,56 @@ +import svelte from 'rollup-plugin-svelte'; +import { sveltePreprocess } from 'svelte-preprocess'; +import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import terser from '@rollup/plugin-terser'; +import typescript from '@rollup/plugin-typescript'; +import postcss from 'rollup-plugin-postcss'; +import livereload from 'rollup-plugin-livereload'; +import serve from 'rollup-plugin-serve'; +import htmlBundle from 'rollup-plugin-html-bundle'; +import copy from 'rollup-plugin-copy'; + +const production = !process.env.ROLLUP_WATCH; + +export default [{ + input: 'src/main.js', + output: { + format: 'iife', + name: 'app', + file: 'build/bundle.js', + sourcemap: !production, + }, + plugins: [ + svelte({ + compilerOptions: { + dev: !production + }, + preprocess: sveltePreprocess() + }), + resolve({ + browser: true, + dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/'), + extensions: ['.svelte', '.mjs', '.ts', '.js', '.json', '.node'] + }), + commonjs(), + typescript(), + postcss(), + copy({ + targets: [ + { src: 'src/template.html', dest: 'build' } + ] + }), + htmlBundle({ + template: 'build/template.html', + target: production ? 'dist/index.html' : 'build/index.html', + targetElement: 'body', + inline: production + }), + !production && serve('build'), + !production && livereload('build'), + production && terser() + ], + watch: { + clearScreen: false + } +}]; \ No newline at end of file diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte new file mode 100644 index 000000000..00818d4c4 --- /dev/null +++ b/client/graphpaper-inline/src/App.svelte @@ -0,0 +1,163 @@ + + + + graphpaper + + + + + +
+ + + +
+ +
+ + + + +
\ No newline at end of file diff --git a/client/graphpaper-inline/src/Minibar.svelte b/client/graphpaper-inline/src/Minibar.svelte new file mode 100644 index 000000000..2a3cbcd00 --- /dev/null +++ b/client/graphpaper-inline/src/Minibar.svelte @@ -0,0 +1,38 @@ + + + + +
+ + + {#each values as val, i} + + {/each} + + +
\ No newline at end of file diff --git a/client/graphpaper-inline/src/ResizeListener.svelte b/client/graphpaper-inline/src/ResizeListener.svelte new file mode 100644 index 000000000..ddb175ee8 --- /dev/null +++ b/client/graphpaper-inline/src/ResizeListener.svelte @@ -0,0 +1,32 @@ + \ No newline at end of file diff --git a/client/graphpaper-inline/src/StitchHandler.svelte b/client/graphpaper-inline/src/StitchHandler.svelte new file mode 100644 index 000000000..d787d19a4 --- /dev/null +++ b/client/graphpaper-inline/src/StitchHandler.svelte @@ -0,0 +1,30 @@ + + + \ No newline at end of file diff --git a/client/graphpaper-inline/src/Tokengrid.svelte b/client/graphpaper-inline/src/Tokengrid.svelte new file mode 100644 index 000000000..f23c25f13 --- /dev/null +++ b/client/graphpaper-inline/src/Tokengrid.svelte @@ -0,0 +1,95 @@ + + +
+ +
+ + +
+ + {#each tokens as token, i} + {#if token.content.match(imagePattern)} + + + inlined img + + {:else if token.is_special == 1.0} + {#if token.role !== ""} + {#if i == 0} +
+ {:else} + + {#each {length: 2} as _, i} + +   + {/each} + + {/if} + + + {token.role} + + + + {token.content} + + + {:else} + + + + {token.content} + + + {/if} + {:else} + {#each token.content as ch} + {#if ch === ' '} + +   + + {:else if ch === '\t'} + + \t   + + {:else if ch === '\n'} + + \n + +
+ {:else} + + {ch} + + {/if} + {/each} + {/if} + {/each} + +   + +
+
+
\ No newline at end of file diff --git a/client/graphpaper-inline/src/main.css b/client/graphpaper-inline/src/main.css new file mode 100644 index 000000000..bd6213e1d --- /dev/null +++ b/client/graphpaper-inline/src/main.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/client/graphpaper-inline/src/main.js b/client/graphpaper-inline/src/main.js new file mode 100644 index 000000000..d80e9a350 --- /dev/null +++ b/client/graphpaper-inline/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/client/graphpaper-inline/src/stitch.ts b/client/graphpaper-inline/src/stitch.ts new file mode 100644 index 000000000..de162aa71 --- /dev/null +++ b/client/graphpaper-inline/src/stitch.ts @@ -0,0 +1,26 @@ +import { writable } from 'svelte/store'; + +export interface StitchMessage { + type: "resize" | "clientmsg" | "kernelmsg", + content: any +} + +export interface DisplayResetMessage { + message_type: 'DisplayResetMessage' +} + +export interface ModelUpdateMessage { + message_type: 'ModelUpdateMessage', + model_id: number, + parent_model_id: number, + content_type: string, + content: string, + prob: number, + token_count: number, + is_generated: number, + is_special: number, + role: string +} + +export const kernelmsg = writable(undefined); +export const clientmsg = writable(undefined); \ No newline at end of file diff --git a/client/graphpaper-inline/src/template.html b/client/graphpaper-inline/src/template.html new file mode 100644 index 000000000..8f7102cca --- /dev/null +++ b/client/graphpaper-inline/src/template.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/client/graphpaper-inline/tailwind.config.js b/client/graphpaper-inline/tailwind.config.js new file mode 100644 index 000000000..b14f79b5c --- /dev/null +++ b/client/graphpaper-inline/tailwind.config.js @@ -0,0 +1,21 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./src/**/*.{html,ts,js,svelte}"], + theme: { + extend: { + fontFamily: { + 'token': ['JetBrains Mono'], + }, + keyframes: { + 'cpulse': { + '50%': { opacity: 0.0 } + } + }, + animation: { + 'cpulse': 'cpulse 3.5s cubic-bezier(0.4, 0, 0.6, 1) infinite' + } + } + }, + plugins: [], +} + diff --git a/client/graphpaper-inline/tsconfig.json b/client/graphpaper-inline/tsconfig.json new file mode 100644 index 000000000..a627cd343 --- /dev/null +++ b/client/graphpaper-inline/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "verbatimModuleSyntax": true, + "module": "ESNext", + "moduleResolution": "bundler" + } +} \ No newline at end of file From 017988ae0b826e28dbf8c70bf8882be0eaf67f15 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 30 Sep 2024 11:31:51 -0700 Subject: [PATCH 012/133] Adjustments to clientside. Fixed tooling issue. Tooling appears to create a nameless role. Fixed. --- client/graphpaper-inline/src/App.svelte | 4 +- .../{Tokengrid.svelte => TokenGrid.svelte} | 0 guidance/trace/_trace.py | 4 +- guidance/visual/__init__.py | 2 +- guidance/visual/_renderer.py | 33 ++++++++++-- tests/visual/__init__.py | 0 tests/visual/test_e2e.py | 53 +++++++++++++++++++ 7 files changed, 87 insertions(+), 9 deletions(-) rename client/graphpaper-inline/src/{Tokengrid.svelte => TokenGrid.svelte} (100%) create mode 100644 tests/visual/__init__.py create mode 100644 tests/visual/test_e2e.py diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 00818d4c4..1a565cd23 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -1,7 +1,7 @@ + + diff --git a/guidance/visual/_renderer.py b/guidance/visual/_renderer.py index 2085ab72a..abb2897ba 100644 --- a/guidance/visual/_renderer.py +++ b/guidance/visual/_renderer.py @@ -17,6 +17,14 @@ ipython_imported = False +try: + import stitch + + stitch_installed = True +except ImportError: + stitch_installed = False + + class RenderUpdate(BaseModel): messages: list = [] need_new_display: bool = False @@ -100,57 +108,71 @@ def update(self, message: Message) -> RenderUpdate: class Renderer: - """ Renders guidance model to a visual medium.""" + """Renders guidance model to a visual medium.""" def update(self, message: Message) -> None: raise NotImplementedError("Update not implemented.") -class HtmlRenderer(Renderer): - """ HTML renderer for guidance.""" +class LegacyHtmlRenderer(Renderer): + """Original HTML renderer for guidance.""" + def __init__(self, trace_handler: TraceHandler) -> None: - self._update_controller = UpdateController(trace_handler) - self._formatted = [] + pass def update(self, message: Message) -> None: - render_update = self._update_controller.update(message) - - last_trace_node = None - for out_message in render_update.messages: - if isinstance(out_message, TraceMessage): - last_trace_node = out_message.trace_node + if not isinstance(message, TraceMessage): + return + last_trace_node = message.trace_node if last_trace_node is not None: clear_output(wait=True) display(HTML(trace_node_to_html(last_trace_node, prettify_roles=False))) -class LegacyHtmlRenderer(Renderer): - """ Original HTML renderer for guidance.""" +def _create_stitch_widget(): + from stitch import StitchWidget + import pkg_resources + + if _create_stitch_widget.src_doc_template is None: + with open( + pkg_resources.resource_filename("guidance", "resources/graphpaper-inline.html"), "r" + ) as f: + _create_stitch_widget.src_doc_template = f.read() + w = StitchWidget() + w.initial_width = "100%" + w.initial_height = "auto" + w.srcdoc = _create_stitch_widget.src_doc_template + return w + + +_create_stitch_widget.src_doc_template = None + + +class JupyterWidgetRenderer(Renderer): def __init__(self, trace_handler: TraceHandler) -> None: + self._jupyter_widget = None self._update_controller = UpdateController(trace_handler) - self._formatted = [] def update(self, message: Message) -> None: - if not isinstance(message, TraceMessage): - return + display_update = self._update_controller.update(message) - last_trace_node = message.trace_node - if last_trace_node is not None: + if display_update.need_new_display: + logger.debug(f"NEED_NEW_DISPLAY:new widget") + self._jupyter_widget = _create_stitch_widget() clear_output(wait=True) - display(HTML(trace_node_to_html(last_trace_node, prettify_roles=False))) + display(self._jupyter_widget) + + for out_message in display_update.messages: + message_json = out_message.model_dump_json(indent=2) + logger.debug(f"OUT_MSG: {message_json}") + self._jupyter_widget.kernelmsg = message_json + class AutoRenderer(Renderer): def __init__(self, trace_handler: TraceHandler): - try: - import stitch - stitch_installed = True - except ImportError: - stitch_installed = False - if stitch_installed: - # TODO(nopdive): Hook up stitch jupyter renderer - self._renderer = LegacyHtmlRenderer(trace_handler=trace_handler) + self._renderer = JupyterWidgetRenderer(trace_handler=trace_handler) else: self._renderer = LegacyHtmlRenderer(trace_handler=trace_handler) From 1a51086816633fae6e29af50a0c7b6b8da7f589e Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 30 Sep 2024 12:55:08 -0700 Subject: [PATCH 014/133] Added stitch package. This package is required for Jupyter kernel comms via a custom ipywidget. --- packages/python/stitch/.coveragerc | 2 + packages/python/stitch/.eslintignore | 5 + packages/python/stitch/.eslintrc.js | 28 + .../python/stitch/.github/workflows/build.yml | 44 + packages/python/stitch/.gitignore | 156 + packages/python/stitch/.npmignore | 7 + packages/python/stitch/.prettierignore | 4 + packages/python/stitch/.prettierrc | 3 + packages/python/stitch/.yarnrc.yml | 1 + packages/python/stitch/LICENSE.txt | 27 + packages/python/stitch/MANIFEST.in | 41 + packages/python/stitch/README.md | 83 + packages/python/stitch/babel.config.js | 13 + packages/python/stitch/codecov.yml | 12 + packages/python/stitch/css/widget.css | 4 + packages/python/stitch/docs/Makefile | 20 + packages/python/stitch/docs/environment.yml | 12 + packages/python/stitch/docs/make.bat | 36 + .../stitch/docs/source/_static/helper.js | 5 + packages/python/stitch/docs/source/conf.py | 213 + .../stitch/docs/source/develop-install.rst | 31 + .../stitch/docs/source/examples/index.rst | 18 + .../docs/source/examples/introduction.nblink | 3 + packages/python/stitch/docs/source/index.rst | 49 + .../python/stitch/docs/source/installing.rst | 37 + .../stitch/docs/source/introduction.rst | 7 + .../python/stitch/examples/introduction.ipynb | 123 + packages/python/stitch/install.json | 5 + packages/python/stitch/jest.config.js | 16 + packages/python/stitch/package.json | 100 + packages/python/stitch/pyproject.toml | 119 + packages/python/stitch/pytest.ini | 4 + packages/python/stitch/readthedocs.yml | 9 + packages/python/stitch/setup.py | 2 + .../python/stitch/src/__tests__/index.spec.ts | 26 + packages/python/stitch/src/__tests__/utils.ts | 119 + packages/python/stitch/src/extension.ts | 16 + packages/python/stitch/src/index.ts | 5 + packages/python/stitch/src/plugin.ts | 42 + packages/python/stitch/src/version.ts | 20 + packages/python/stitch/src/widget.ts | 114 + packages/python/stitch/stitch.json | 5 + packages/python/stitch/stitch/__init__.py | 49 + packages/python/stitch/stitch/_frontend.py | 12 + packages/python/stitch/stitch/_version.py | 8 + .../stitch/stitch/nbextension/extension.js | 17 + packages/python/stitch/stitch/stitch.py | 31 + .../python/stitch/stitch/tests/__init__.py | 0 .../python/stitch/stitch/tests/conftest.py | 54 + .../stitch/stitch/tests/test_example.py | 14 + .../stitch/tests/test_nbextension_path.py | 15 + packages/python/stitch/tsconfig.eslint.json | 5 + packages/python/stitch/tsconfig.json | 25 + packages/python/stitch/webpack.config.js | 91 + packages/python/stitch/yarn.lock | 8505 +++++++++++++++++ 55 files changed, 10412 insertions(+) create mode 100644 packages/python/stitch/.coveragerc create mode 100644 packages/python/stitch/.eslintignore create mode 100644 packages/python/stitch/.eslintrc.js create mode 100644 packages/python/stitch/.github/workflows/build.yml create mode 100644 packages/python/stitch/.gitignore create mode 100644 packages/python/stitch/.npmignore create mode 100644 packages/python/stitch/.prettierignore create mode 100644 packages/python/stitch/.prettierrc create mode 100644 packages/python/stitch/.yarnrc.yml create mode 100644 packages/python/stitch/LICENSE.txt create mode 100644 packages/python/stitch/MANIFEST.in create mode 100644 packages/python/stitch/README.md create mode 100644 packages/python/stitch/babel.config.js create mode 100644 packages/python/stitch/codecov.yml create mode 100644 packages/python/stitch/css/widget.css create mode 100644 packages/python/stitch/docs/Makefile create mode 100644 packages/python/stitch/docs/environment.yml create mode 100644 packages/python/stitch/docs/make.bat create mode 100644 packages/python/stitch/docs/source/_static/helper.js create mode 100644 packages/python/stitch/docs/source/conf.py create mode 100644 packages/python/stitch/docs/source/develop-install.rst create mode 100644 packages/python/stitch/docs/source/examples/index.rst create mode 100644 packages/python/stitch/docs/source/examples/introduction.nblink create mode 100644 packages/python/stitch/docs/source/index.rst create mode 100644 packages/python/stitch/docs/source/installing.rst create mode 100644 packages/python/stitch/docs/source/introduction.rst create mode 100644 packages/python/stitch/examples/introduction.ipynb create mode 100644 packages/python/stitch/install.json create mode 100644 packages/python/stitch/jest.config.js create mode 100644 packages/python/stitch/package.json create mode 100644 packages/python/stitch/pyproject.toml create mode 100644 packages/python/stitch/pytest.ini create mode 100644 packages/python/stitch/readthedocs.yml create mode 100644 packages/python/stitch/setup.py create mode 100644 packages/python/stitch/src/__tests__/index.spec.ts create mode 100644 packages/python/stitch/src/__tests__/utils.ts create mode 100644 packages/python/stitch/src/extension.ts create mode 100644 packages/python/stitch/src/index.ts create mode 100644 packages/python/stitch/src/plugin.ts create mode 100644 packages/python/stitch/src/version.ts create mode 100644 packages/python/stitch/src/widget.ts create mode 100644 packages/python/stitch/stitch.json create mode 100644 packages/python/stitch/stitch/__init__.py create mode 100644 packages/python/stitch/stitch/_frontend.py create mode 100644 packages/python/stitch/stitch/_version.py create mode 100644 packages/python/stitch/stitch/nbextension/extension.js create mode 100644 packages/python/stitch/stitch/stitch.py create mode 100644 packages/python/stitch/stitch/tests/__init__.py create mode 100644 packages/python/stitch/stitch/tests/conftest.py create mode 100644 packages/python/stitch/stitch/tests/test_example.py create mode 100644 packages/python/stitch/stitch/tests/test_nbextension_path.py create mode 100644 packages/python/stitch/tsconfig.eslint.json create mode 100644 packages/python/stitch/tsconfig.json create mode 100644 packages/python/stitch/webpack.config.js create mode 100644 packages/python/stitch/yarn.lock diff --git a/packages/python/stitch/.coveragerc b/packages/python/stitch/.coveragerc new file mode 100644 index 000000000..dc0dc815f --- /dev/null +++ b/packages/python/stitch/.coveragerc @@ -0,0 +1,2 @@ +[run] +omit = stitch/tests/* diff --git a/packages/python/stitch/.eslintignore b/packages/python/stitch/.eslintignore new file mode 100644 index 000000000..e8a22210a --- /dev/null +++ b/packages/python/stitch/.eslintignore @@ -0,0 +1,5 @@ +node_modules +dist +coverage +**/*.d.ts +tests \ No newline at end of file diff --git a/packages/python/stitch/.eslintrc.js b/packages/python/stitch/.eslintrc.js new file mode 100644 index 000000000..9fb27ea5b --- /dev/null +++ b/packages/python/stitch/.eslintrc.js @@ -0,0 +1,28 @@ +module.exports = { + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended' + ], + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.eslint.json', + sourceType: 'module' + }, + plugins: ['@typescript-eslint'], + rules: { + '@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }], + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/quotes': [ + 'error', + 'single', + { avoidEscape: true, allowTemplateLiterals: false } + ], + curly: ['error', 'all'], + eqeqeq: 'error', + 'prefer-arrow-callback': 'error' + } +}; \ No newline at end of file diff --git a/packages/python/stitch/.github/workflows/build.yml b/packages/python/stitch/.github/workflows/build.yml new file mode 100644 index 000000000..dfab4e374 --- /dev/null +++ b/packages/python/stitch/.github/workflows/build.yml @@ -0,0 +1,44 @@ +name: Build + +on: + push: + branches: main + pull_request: + branches: "*" + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + python-version: ["3.7", "3.10"] + steps: + - name: Checkout + uses: actions/checkout@v2 + + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + + - name: Install dependencies + run: | + python -m pip install -U codecov + npm install -g codecov + - name: Test the extension + run: | + python -m pip install --upgrade -v -e ".[test, examples, docs]" + python -m pytest + yarn run test + + - name: Linting + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + yarn run lint:check + + - name: Check docs can be build + links + if: ${{ matrix.os == 'ubuntu-latest' }} + working-directory: docs + run: | + sudo apt install -y pandoc + make html + python -m pytest --check-links diff --git a/packages/python/stitch/.gitignore b/packages/python/stitch/.gitignore new file mode 100644 index 000000000..61493d6f8 --- /dev/null +++ b/packages/python/stitch/.gitignore @@ -0,0 +1,156 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask instance folder +instance/ + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ +docs/source/_static/embed-bundle.js +docs/source/_static/embed-bundle.js.map + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +# NPM +# ---- + +**/node_modules/ +stitch/nbextension/index.* +.yarn/ + +# Coverage data +# ------------- +**/coverage/ + +# Packed lab extensions +stitch/labextension diff --git a/packages/python/stitch/.npmignore b/packages/python/stitch/.npmignore new file mode 100644 index 000000000..f8ec1d196 --- /dev/null +++ b/packages/python/stitch/.npmignore @@ -0,0 +1,7 @@ +.DS_Store +node_modules/ +tests/ +.jshintrc +# Ignore any build output from python: +dist/*.tar.gz +dist/*.wheel diff --git a/packages/python/stitch/.prettierignore b/packages/python/stitch/.prettierignore new file mode 100644 index 000000000..b56605bbd --- /dev/null +++ b/packages/python/stitch/.prettierignore @@ -0,0 +1,4 @@ +node_modules +**/node_modules +**/lib +**/package.json \ No newline at end of file diff --git a/packages/python/stitch/.prettierrc b/packages/python/stitch/.prettierrc new file mode 100644 index 000000000..dc2fb828f --- /dev/null +++ b/packages/python/stitch/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} \ No newline at end of file diff --git a/packages/python/stitch/.yarnrc.yml b/packages/python/stitch/.yarnrc.yml new file mode 100644 index 000000000..3186f3f07 --- /dev/null +++ b/packages/python/stitch/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/packages/python/stitch/LICENSE.txt b/packages/python/stitch/LICENSE.txt new file mode 100644 index 000000000..806ff2ed3 --- /dev/null +++ b/packages/python/stitch/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2024 nopdive +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/python/stitch/MANIFEST.in b/packages/python/stitch/MANIFEST.in new file mode 100644 index 000000000..ef35b9f2d --- /dev/null +++ b/packages/python/stitch/MANIFEST.in @@ -0,0 +1,41 @@ +include LICENSE.txt +include README.md + +include setup.py +include pyproject.toml +include pytest.ini +include .coverage.rc + +include tsconfig.json +include package.json +include webpack.config.js +include stitch/labextension/*.tgz + +# Documentation +graft docs +exclude docs/\#* +prune docs/build +prune docs/gh-pages +prune docs/dist + +# Examples +graft examples + +# Tests +graft tests +prune tests/build + +# Javascript files +graft stitch/nbextension +graft src +graft css +prune **/node_modules +prune coverage +prune lib + +# Patterns to exclude from any directory +global-exclude *~ +global-exclude *.pyc +global-exclude *.pyo +global-exclude .git +global-exclude .ipynb_checkpoints diff --git a/packages/python/stitch/README.md b/packages/python/stitch/README.md new file mode 100644 index 000000000..cf34abf7e --- /dev/null +++ b/packages/python/stitch/README.md @@ -0,0 +1,83 @@ + +# stitch + +[![Build Status](https://travis-ci.org/guidance-ai/stitch.svg?branch=master)](https://travis-ci.org/guidance-ai/stitch) +[![codecov](https://codecov.io/gh/guidance-ai/stitch/branch/master/graph/badge.svg)](https://codecov.io/gh/guidance-ai/stitch) + + +Bidirectional comms for Jupyer and JavaScript. + +## Installation + +You can install using `pip`: + +```bash +pip install stitch +``` + +If you are using Jupyter Notebook 5.2 or earlier, you may also need to enable +the nbextension: +```bash +jupyter nbextension enable --py [--sys-prefix|--user|--system] stitch +``` + +## Development Installation + +Create a dev environment: +```bash +conda create -n stitch-dev -c conda-forge nodejs python jupyterlab=4.0.11 +conda activate stitch-dev +``` + +Install the python. This will also build the TS package. +```bash +pip install -e ".[test, examples]" +``` + +When developing your extensions, you need to manually enable your extensions with the +notebook / lab frontend. For lab, this is done by the command: + +``` +jupyter labextension develop --overwrite . +jlpm run build +``` + +For classic notebook, you need to run: + +``` +jupyter nbextension install --sys-prefix --symlink --overwrite --py stitch +jupyter nbextension enable --sys-prefix --py stitch +``` + +Note that the `--symlink` flag doesn't work on Windows, so you will here have to run +the `install` command every time that you rebuild your extension. For certain installations +you might also need another flag instead of `--sys-prefix`, but we won't cover the meaning +of those flags here. + +### How to see your changes +#### Typescript: +If you use JupyterLab to develop then you can watch the source directory and run JupyterLab at the same time in different +terminals to watch for changes in the extension's source and automatically rebuild the widget. + +```bash +# Watch the source directory in one terminal, automatically rebuilding when needed +jlpm run watch +# Run JupyterLab in another terminal +jupyter lab +``` + +After a change wait for the build to finish and then refresh your browser and the changes should take effect. + +#### Python: +If you make a change to the python code then you will need to restart the notebook kernel to have it take effect. + +## Updating the version + +To update the version, install tbump and use it to bump the version. +By default it will also create a tag. + +```bash +pip install tbump +tbump +``` + diff --git a/packages/python/stitch/babel.config.js b/packages/python/stitch/babel.config.js new file mode 100644 index 000000000..bbc789a7f --- /dev/null +++ b/packages/python/stitch/babel.config.js @@ -0,0 +1,13 @@ +module.exports = { + sourceMap: 'inline', + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + }, + ], + ], +}; diff --git a/packages/python/stitch/codecov.yml b/packages/python/stitch/codecov.yml new file mode 100644 index 000000000..075746814 --- /dev/null +++ b/packages/python/stitch/codecov.yml @@ -0,0 +1,12 @@ +comment: off +# show coverage in CI status, but never consider it a failure +coverage: + status: + project: + default: + target: 0% + patch: + default: + target: 0% +ignore: + - "stitch/tests" diff --git a/packages/python/stitch/css/widget.css b/packages/python/stitch/css/widget.css new file mode 100644 index 000000000..f7abb3f64 --- /dev/null +++ b/packages/python/stitch/css/widget.css @@ -0,0 +1,4 @@ +.custom-widget { + background-color: lightseagreen; + padding: 0px 2px; +} diff --git a/packages/python/stitch/docs/Makefile b/packages/python/stitch/docs/Makefile new file mode 100644 index 000000000..8e5059549 --- /dev/null +++ b/packages/python/stitch/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = stitch +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/packages/python/stitch/docs/environment.yml b/packages/python/stitch/docs/environment.yml new file mode 100644 index 000000000..f3f33d9cc --- /dev/null +++ b/packages/python/stitch/docs/environment.yml @@ -0,0 +1,12 @@ + +name: stitch_docs +channels: + - conda-forge +dependencies: + - python=3.* + - nodejs + - jupyter_sphinx + - sphinx + - sphinx_rtd_theme + - nbsphinx + - nbsphinx-link diff --git a/packages/python/stitch/docs/make.bat b/packages/python/stitch/docs/make.bat new file mode 100644 index 000000000..b7ff4ee61 --- /dev/null +++ b/packages/python/stitch/docs/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build +set SPHINXPROJ=stitch + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/packages/python/stitch/docs/source/_static/helper.js b/packages/python/stitch/docs/source/_static/helper.js new file mode 100644 index 000000000..cb2e2a819 --- /dev/null +++ b/packages/python/stitch/docs/source/_static/helper.js @@ -0,0 +1,5 @@ +var cache_require = window.require; + +window.addEventListener('load', function() { + window.require = cache_require; +}); diff --git a/packages/python/stitch/docs/source/conf.py b/packages/python/stitch/docs/source/conf.py new file mode 100644 index 000000000..540963ebd --- /dev/null +++ b/packages/python/stitch/docs/source/conf.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# stitch documentation build configuration file +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.viewcode', + 'sphinx.ext.intersphinx', + 'sphinx.ext.napoleon', + 'sphinx.ext.todo', + 'nbsphinx', + 'jupyter_sphinx', + 'nbsphinx_link', +] + +# Set the nbsphinx JS path to empty to avoid showing twice of the widgets +nbsphinx_requirejs_path = "" +nbsphinx_widgets_path = "" + +# Ensure our extension is available: +import sys +from os.path import dirname, join as pjoin +docs = dirname(dirname(__file__)) +root = dirname(docs) +sys.path.insert(0, root) +sys.path.insert(0, pjoin(docs, 'sphinxext')) + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'stitch' +copyright = '2024, nopdive' +author = 'nopdive' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. + + +# get version from python package: +import os +here = os.path.dirname(__file__) +repo = os.path.join(here, '..', '..') +_version_py = os.path.join(repo, 'stitch', '_version.py') +version_ns = {} +with open(_version_py) as f: + exec(f.read(), version_ns) + +# The short X.Y version. +version = '%i.%i' % version_ns['version_info'][:2] +# The full version, including alpha/beta/rc tags. +release = version_ns['__version__'] + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = "en" + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['**.ipynb_checkpoints'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'stitchdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'stitch.tex', 'stitch Documentation', + 'nopdive', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, + 'stitch', + 'stitch Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, + 'stitch', + 'stitch Documentation', + author, + 'stitch', + 'Bidirectional comms for Jupyer and JavaScript.', + 'Miscellaneous'), +] + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} + +# Read The Docs +# on_rtd is whether we are on readthedocs.org, this line of code grabbed from +# docs.readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# otherwise, readthedocs.org uses their theme by default, so no need to specify it + + +# Uncomment this line if you have know exceptions in your included notebooks +# that nbsphinx complains about: +# +nbsphinx_allow_errors = True # exception ipstruct.py ipython_genutils + +from sphinx.util import logging +logger = logging.getLogger(__name__) + +def setup(app): + def add_scripts(app): + for fname in ['helper.js', 'embed-bundle.js']: + if not os.path.exists(os.path.join(here, '_static', fname)): + logger.warning('missing javascript file: %s' % fname) + app.add_js_file(fname) + app.connect('builder-inited', add_scripts) diff --git a/packages/python/stitch/docs/source/develop-install.rst b/packages/python/stitch/docs/source/develop-install.rst new file mode 100644 index 000000000..3f66ed415 --- /dev/null +++ b/packages/python/stitch/docs/source/develop-install.rst @@ -0,0 +1,31 @@ + +Developer install +================= + + +To install a developer version of stitch, you will first need to clone +the repository:: + + git clone https://github.com/guidance-ai/stitch + cd stitch + +Next, install it with a develop install using pip:: + + pip install -e . + + +If you are planning on working on the JS/frontend code, you should also do +a link installation of the extension:: + + jupyter nbextension install [--sys-prefix / --user / --system] --symlink --py stitch + + jupyter nbextension enable [--sys-prefix / --user / --system] --py stitch + +with the `appropriate flag`_. Or, if you are using Jupyterlab:: + + jupyter labextension install . + + +.. links + +.. _`appropriate flag`: https://jupyter-notebook.readthedocs.io/en/stable/extending/frontend_extensions.html#installing-and-enabling-extensions diff --git a/packages/python/stitch/docs/source/examples/index.rst b/packages/python/stitch/docs/source/examples/index.rst new file mode 100644 index 000000000..57bad7f44 --- /dev/null +++ b/packages/python/stitch/docs/source/examples/index.rst @@ -0,0 +1,18 @@ + +Examples +======== + +This section contains several examples generated from Jupyter notebooks. +The widgets have been embedded into the page for demonstrative purposes. + +.. todo:: + + Add links to notebooks in examples folder similar to the initial + one. This is a manual step to ensure only those examples that + are suited for inclusion are used. + + +.. toctree:: + :glob: + + * diff --git a/packages/python/stitch/docs/source/examples/introduction.nblink b/packages/python/stitch/docs/source/examples/introduction.nblink new file mode 100644 index 000000000..258bb0f01 --- /dev/null +++ b/packages/python/stitch/docs/source/examples/introduction.nblink @@ -0,0 +1,3 @@ +{ + "path": "../../../examples/introduction.ipynb" +} diff --git a/packages/python/stitch/docs/source/index.rst b/packages/python/stitch/docs/source/index.rst new file mode 100644 index 000000000..44862bef8 --- /dev/null +++ b/packages/python/stitch/docs/source/index.rst @@ -0,0 +1,49 @@ + +stitch +===================================== + +Version: |release| + +Bidirectional comms for Jupyer and JavaScript. + + +Quickstart +---------- + +To get started with stitch, install with pip:: + + pip install stitch + +or with conda:: + + conda install stitch + + +Contents +-------- + +.. toctree:: + :maxdepth: 2 + :caption: Installation and usage + + installing + introduction + +.. toctree:: + :maxdepth: 1 + + examples/index + + +.. toctree:: + :maxdepth: 2 + :caption: Development + + develop-install + + +.. links + +.. _`Jupyter widgets`: https://jupyter.org/widgets.html + +.. _`notebook`: https://jupyter-notebook.readthedocs.io/en/latest/ diff --git a/packages/python/stitch/docs/source/installing.rst b/packages/python/stitch/docs/source/installing.rst new file mode 100644 index 000000000..e5f8ad74f --- /dev/null +++ b/packages/python/stitch/docs/source/installing.rst @@ -0,0 +1,37 @@ + +.. _installation: + +Installation +============ + + +The simplest way to install stitch is via pip:: + + pip install stitch + +or via conda:: + + conda install stitch + + +If you installed via pip, and notebook version < 5.3, you will also have to +install / configure the front-end extension as well. If you are using classic +notebook (as opposed to Jupyterlab), run:: + + jupyter nbextension install [--sys-prefix / --user / --system] --py stitch + + jupyter nbextension enable [--sys-prefix / --user / --system] --py stitch + +with the `appropriate flag`_. If you are using Jupyterlab, install the extension +with:: + + jupyter labextension install stitch + +If you are installing using conda, these commands should be unnecessary, but If +you need to run them the commands should be the same (just make sure you choose the +`--sys-prefix` flag). + + +.. links + +.. _`appropriate flag`: https://jupyter-notebook.readthedocs.io/en/stable/extending/frontend_extensions.html#installing-and-enabling-extensions diff --git a/packages/python/stitch/docs/source/introduction.rst b/packages/python/stitch/docs/source/introduction.rst new file mode 100644 index 000000000..ad0edd44f --- /dev/null +++ b/packages/python/stitch/docs/source/introduction.rst @@ -0,0 +1,7 @@ +============= +Introduction +============= + +.. todo:: + + add prose explaining project purpose and usage here diff --git a/packages/python/stitch/examples/introduction.ipynb b/packages/python/stitch/examples/introduction.ipynb new file mode 100644 index 000000000..b6e992f47 --- /dev/null +++ b/packages/python/stitch/examples/introduction.ipynb @@ -0,0 +1,123 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Introduction" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import stitch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w = stitch.StitchWidget()\n", + "w.srcdoc = \"\"\"\n", + "\n", + "\n", + "\n", + "
\n", + "MESSAGE: \n", + "
\n", + "\n", + "\n", + "\"\"\"\n", + "w.initial_width = '100%'\n", + "w.initial_height = 'auto'\n", + "display(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w.kernelmsg = \"\"\"\n", + "A language model is a probabilistic model of a natural language.[1] In 1980, the first significant statistical language model was proposed, and during the decade IBM performed ‘Shannon-style’ experiments, in which potential sources for language modeling improvement were identified by observing and analyzing the performance of human subjects in predicting or correcting text.[2]\n", + "\n", + "Language models are useful for a variety of tasks, including speech recognition[3] (helping prevent predictions of low-probability (e.g. nonsense) sequences), machine translation,[4] natural language generation (generating more human-like text), optical character recognition, handwriting recognition,[5] grammar induction,[6] and information retrieval.[7][8]\n", + "\n", + "Large language models, currently their most advanced form, are a combination of larger datasets (frequently using words scraped from the public internet), feedforward neural networks, and transformers. They have superseded recurrent neural network-based models, which had previously superseded the pure statistical models, such as word n-gram language model. \n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w.observe(lambda x: print(x['new']), 'kernelmsg')\n", + "w.kernelmsg = \"Wow, a change!\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/packages/python/stitch/install.json b/packages/python/stitch/install.json new file mode 100644 index 000000000..fd70e6be8 --- /dev/null +++ b/packages/python/stitch/install.json @@ -0,0 +1,5 @@ +{ + "packageManager": "python", + "packageName": "stitch", + "uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package stitch" +} diff --git a/packages/python/stitch/jest.config.js b/packages/python/stitch/jest.config.js new file mode 100644 index 000000000..79453a3ae --- /dev/null +++ b/packages/python/stitch/jest.config.js @@ -0,0 +1,16 @@ +module.exports = { + automock: false, + moduleNameMapper: { + '\\.(css|less|sass|scss)$': 'identity-obj-proxy', + }, + preset: 'ts-jest/presets/js-with-babel', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + testPathIgnorePatterns: ['/lib/', '/node_modules/'], + testRegex: '/__tests__/.*.spec.ts[x]?$', + transformIgnorePatterns: ['/node_modules/(?!(@jupyter(lab|-widgets)/.*)/)'], + globals: { + 'ts-jest': { + tsconfig: '/tsconfig.json', + }, + }, +}; diff --git a/packages/python/stitch/package.json b/packages/python/stitch/package.json new file mode 100644 index 000000000..e652191a5 --- /dev/null +++ b/packages/python/stitch/package.json @@ -0,0 +1,100 @@ +{ + "name": "stitch", + "version": "0.1.0", + "description": "Bidirectional comms for Jupyer and JavaScript.", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension", + "widgets" + ], + "files": [ + "lib/**/*.js", + "dist/*.js", + "css/*.css" + ], + "homepage": "https://github.com/guidance-ai/stitch", + "bugs": { + "url": "https://github.com/guidance-ai/stitch/issues" + }, + "license": "BSD-3-Clause", + "author": { + "name": "nopdive", + "email": "nopdive@gmail.com" + }, + "main": "lib/index.js", + "types": "./lib/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/guidance-ai/stitch" + }, + "scripts": { + "build": "jlpm run build:lib && jlpm run build:nbextension && jlpm run build:labextension:dev", + "build:prod": "jlpm run build:lib && jlpm run build:nbextension && jlpm run build:labextension", + "build:labextension": "jupyter labextension build .", + "build:labextension:dev": "jupyter labextension build --development True .", + "build:lib": "tsc", + "build:nbextension": "webpack", + "clean": "jlpm run clean:lib && jlpm run clean:nbextension && jlpm run clean:labextension", + "clean:lib": "rimraf lib", + "clean:labextension": "rimraf stitch/labextension", + "clean:nbextension": "rimraf stitch/nbextension/static/index.js", + "lint": "eslint . --ext .ts,.tsx --fix", + "lint:check": "eslint . --ext .ts,.tsx", + "prepack": "jlpm run build:lib", + "test": "jest", + "watch": "npm-run-all -p watch:*", + "watch:lib": "tsc -w", + "watch:nbextension": "webpack --watch --mode=development", + "watch:labextension": "jupyter labextension watch ." + }, + "dependencies": { + "@jupyter-widgets/base": "^1.1.10 || ^2 || ^3 || ^4 || ^5 || ^6" + }, + "devDependencies": { + "@babel/core": "^7.23.7", + "@babel/preset-env": "^7.23.8", + "@jupyter-widgets/base-manager": "^1.0.7", + "@jupyterlab/builder": "^4.0.11", + "@lumino/application": "^2.3.0", + "@lumino/widgets": "^2.3.1", + "@types/jest": "^29.5.11", + "@types/webpack-env": "^1.18.4", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", + "acorn": "^8.11.3", + "css-loader": "^6.9.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "fs-extra": "^11.2.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^29.7.0", + "mkdirp": "^3.0.1", + "npm-run-all": "^4.1.5", + "prettier": "^3.2.4", + "rimraf": "^5.0.5", + "source-map-loader": "^5.0.0", + "style-loader": "^3.3.4", + "ts-jest": "^29.1.2", + "ts-loader": "^9.5.1", + "typescript": "~5.3.3", + "webpack": "^5.90.0", + "webpack-cli": "^5.1.4" + }, + "devDependenciesComments": { + "@jupyterlab/builder": "pinned to the latest JupyterLab 3.x release", + "@lumino/application": "pinned to the latest Lumino 1.x release", + "@lumino/widgets": "pinned to the latest Lumino 1.x release" + }, + "jupyterlab": { + "extension": "lib/plugin", + "outputDir": "stitch/labextension/", + "sharedPackages": { + "@jupyter-widgets/base": { + "bundled": false, + "singleton": true + } + } + } +} diff --git a/packages/python/stitch/pyproject.toml b/packages/python/stitch/pyproject.toml new file mode 100644 index 000000000..7b9b51630 --- /dev/null +++ b/packages/python/stitch/pyproject.toml @@ -0,0 +1,119 @@ +[build-system] +requires = [ + "hatchling>=1.21.1", + "jupyterlab>=4.0.0,<5", + "hatch-nodejs-version>=0.3.2", +] +build-backend = "hatchling.build" + +[project] +name = "stitch" +description = "Bidirectional comms for Jupyer and JavaScript." +readme = "README.md" +license = { file = "LICENSE.txt" } +requires-python = ">=3.9" +authors = [ + { name = "nopdive", email = "nopdive@gmail.com" }, +] +keywords = [ + "IPython", + "Jupyter", + "Widgets", +] +classifiers = [ + "Framework :: Jupyter", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: BSD License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dependencies = [ + "ipywidgets>=8.0.0", +] +version = "0.1.0.dev0" + +[project.optional-dependencies] +docs = [ + "jupyter_sphinx", + "nbsphinx", + "nbsphinx-link", + "pypandoc", + "pytest_check_links", + "recommonmark", + "sphinx>=1.5", + "sphinx_rtd_theme", +] +examples = [] +test = [ + "nbval", + "pytest-cov", + "pytest>=6.0", +] + +[project.urls] +Homepage = "https://github.com/guidance-ai/stitch" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build] +artifacts = [ + "stitch/nbextension/index.*", + "stitch/labextension/*.tgz", + "stitch/labextension", +] + +[tool.hatch.build.targets.wheel.shared-data] +"stitch/nbextension" = "share/jupyter/nbextensions/stitch" +"stitch/labextension" = "share/jupyter/labextensions/stitch" +"./install.json" = "share/jupyter/labextensions/stitch/install.json" +"./stitch.json" = "etc/jupyter/nbconfig/notebook.d/stitch.json" + +[tool.hatch.build.targets.sdist] +exclude = [ + ".github", +] + +[tool.hatch.build.hooks.jupyter-builder] +build-function = "hatch_jupyter_builder.npm_builder" +ensured-targets = [ + "stitch/nbextension/index.js", + "stitch/labextension/package.json", +] +skip-if-exists = [ + "stitch/nbextension/index.js", + "stitch/labextension/package.json", +] +dependencies = [ + "hatch-jupyter-builder>=0.8.3", +] + +[tool.hatch.build.hooks.jupyter-builder.build-kwargs] +path = "." +build_cmd = "build:prod" +npm = ["jlpm"] + +[tool.tbump] +field = [ + { name = "channel", default = "" }, + { name = "release", default = "" }, +] +file = [ + { src = "pyproject.toml", version_template = "version = \"{major}.{minor}.{patch}{channel}{release}\"" }, + { src = "stitch/_version.py" }, +] + +[tool.tbump.version] +current = "0.1.0.dev0" +regex = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)((?Pa|b|rc|.dev)(?P\\d+))?" + +[tool.tbump.git] +message_template = "Bump to {new_version}" +tag_template = "v{new_version}" diff --git a/packages/python/stitch/pytest.ini b/packages/python/stitch/pytest.ini new file mode 100644 index 000000000..e77e2a193 --- /dev/null +++ b/packages/python/stitch/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +testpaths = stitch/tests examples +norecursedirs = node_modules .ipynb_checkpoints +addopts = --nbval --current-env diff --git a/packages/python/stitch/readthedocs.yml b/packages/python/stitch/readthedocs.yml new file mode 100644 index 000000000..c972d9ccf --- /dev/null +++ b/packages/python/stitch/readthedocs.yml @@ -0,0 +1,9 @@ +type: sphinx +python: + version: 3.5 + pip_install: true + extra_requirements: + - examples + - docs +conda: + file: docs/environment.yml diff --git a/packages/python/stitch/setup.py b/packages/python/stitch/setup.py new file mode 100644 index 000000000..b6c668135 --- /dev/null +++ b/packages/python/stitch/setup.py @@ -0,0 +1,2 @@ +# setup.py shim for use with applications that require it. +__import__("setuptools").setup() diff --git a/packages/python/stitch/src/__tests__/index.spec.ts b/packages/python/stitch/src/__tests__/index.spec.ts new file mode 100644 index 000000000..407f930b9 --- /dev/null +++ b/packages/python/stitch/src/__tests__/index.spec.ts @@ -0,0 +1,26 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +// Add any needed widget imports here (or from controls) +// import {} from '@jupyter-widgets/base'; + +import { createTestModel } from './utils'; + +import { ExampleModel } from '..'; + +describe('Example', () => { + describe('ExampleModel', () => { + it('should be createable', () => { + const model = createTestModel(ExampleModel); + expect(model).toBeInstanceOf(ExampleModel); + expect(model.get('value')).toEqual('Hello World'); + }); + + it('should be createable with a value', () => { + const state = { value: 'Foo Bar!' }; + const model = createTestModel(ExampleModel, state); + expect(model).toBeInstanceOf(ExampleModel); + expect(model.get('value')).toEqual('Foo Bar!'); + }); + }); +}); diff --git a/packages/python/stitch/src/__tests__/utils.ts b/packages/python/stitch/src/__tests__/utils.ts new file mode 100644 index 000000000..0a61d63e9 --- /dev/null +++ b/packages/python/stitch/src/__tests__/utils.ts @@ -0,0 +1,119 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +import * as widgets from '@jupyter-widgets/base'; +import * as baseManager from '@jupyter-widgets/base-manager'; +import * as services from '@jupyterlab/services'; + +let numComms = 0; + +export class MockComm implements widgets.IClassicComm { + constructor() { + this.comm_id = `mock-comm-id-${numComms}`; + numComms += 1; + } + on_close(fn: ((x?: any) => void) | null): void { + this._on_close = fn; + } + on_msg(fn: (x?: any) => void): void { + this._on_msg = fn; + } + _process_msg(msg: services.KernelMessage.ICommMsgMsg): void | Promise { + if (this._on_msg) { + return this._on_msg(msg); + } else { + return Promise.resolve(); + } + } + close(): string { + if (this._on_close) { + this._on_close(); + } + return 'dummy'; + } + send(): string { + return 'dummy'; + } + + open(): string { + return 'dummy'; + } + + comm_id: string; + target_name = 'dummy'; + _on_msg: ((x?: any) => void) | null = null; + _on_close: ((x?: any) => void) | null = null; +} + +export class DummyManager extends baseManager.ManagerBase { + constructor() { + super(); + this.el = window.document.createElement('div'); + } + + display_view( + msg: services.KernelMessage.IMessage, + view: widgets.DOMWidgetView, + options: any + ) { + // TODO: make this a spy + // TODO: return an html element + return Promise.resolve(view).then((view) => { + this.el.appendChild(view.el); + view.on('remove', () => console.log('view removed', view)); + return view.el; + }); + } + + protected loadClass( + className: string, + moduleName: string, + moduleVersion: string + ): Promise { + if (moduleName === '@jupyter-widgets/base') { + if ((widgets as any)[className]) { + return Promise.resolve((widgets as any)[className]); + } else { + return Promise.reject(`Cannot find class ${className}`); + } + } else if (moduleName === 'jupyter-datawidgets') { + if (this.testClasses[className]) { + return Promise.resolve(this.testClasses[className]); + } else { + return Promise.reject(`Cannot find class ${className}`); + } + } else { + return Promise.reject(`Cannot find module ${moduleName}`); + } + } + + _get_comm_info() { + return Promise.resolve({}); + } + + _create_comm() { + return Promise.resolve(new MockComm()); + } + + el: HTMLElement; + + testClasses: { [key: string]: any } = {}; +} + +export interface Constructor { + new (attributes?: any, options?: any): T; +} + +export function createTestModel( + constructor: Constructor, + attributes?: any +): T { + const id = widgets.uuid(); + const widget_manager = new DummyManager(); + const modelOptions = { + widget_manager: widget_manager, + model_id: id, + }; + + return new constructor(attributes, modelOptions); +} diff --git a/packages/python/stitch/src/extension.ts b/packages/python/stitch/src/extension.ts new file mode 100644 index 000000000..18ef180b2 --- /dev/null +++ b/packages/python/stitch/src/extension.ts @@ -0,0 +1,16 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +// Entry point for the notebook bundle containing custom model definitions. +// +// Setup notebook base URL +// +// Some static assets may be required by the custom widget javascript. The base +// url for the notebook is not known at build time and is therefore computed +// dynamically. +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion +(window as any).__webpack_public_path__ = + document.querySelector('body')!.getAttribute('data-base-url') + + 'nbextensions/stitch'; + +export * from './index'; diff --git a/packages/python/stitch/src/index.ts b/packages/python/stitch/src/index.ts new file mode 100644 index 000000000..d9d81c9a7 --- /dev/null +++ b/packages/python/stitch/src/index.ts @@ -0,0 +1,5 @@ +// Copyright (c) nopdive +// Distributed under the terms of the Modified BSD License. + +export * from './version'; +export * from './widget'; diff --git a/packages/python/stitch/src/plugin.ts b/packages/python/stitch/src/plugin.ts new file mode 100644 index 000000000..07ab72326 --- /dev/null +++ b/packages/python/stitch/src/plugin.ts @@ -0,0 +1,42 @@ +// Copyright (c) nopdive +// Distributed under the terms of the Modified BSD License. + +import { Application, IPlugin } from '@lumino/application'; + +import { Widget } from '@lumino/widgets'; + +import { IJupyterWidgetRegistry } from '@jupyter-widgets/base'; + +import * as widgetExports from './widget'; + +import { MODULE_NAME, MODULE_VERSION } from './version'; + +const EXTENSION_ID = 'stitch:plugin'; + +/** + * The example plugin. + */ +const examplePlugin: IPlugin, void> = { + id: EXTENSION_ID, + requires: [IJupyterWidgetRegistry], + activate: activateWidgetExtension, + autoStart: true, +} as unknown as IPlugin, void>; +// the "as unknown as ..." typecast above is solely to support JupyterLab 1 +// and 2 in the same codebase and should be removed when we migrate to Lumino. + +export default examplePlugin; + +/** + * Activate the widget extension. + */ +function activateWidgetExtension( + app: Application, + registry: IJupyterWidgetRegistry +): void { + registry.registerWidget({ + name: MODULE_NAME, + version: MODULE_VERSION, + exports: widgetExports, + }); +} diff --git a/packages/python/stitch/src/version.ts b/packages/python/stitch/src/version.ts new file mode 100644 index 000000000..7bf318155 --- /dev/null +++ b/packages/python/stitch/src/version.ts @@ -0,0 +1,20 @@ +// Copyright (c) nopdive +// Distributed under the terms of the Modified BSD License. + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +// eslint-disable-next-line @typescript-eslint/no-var-requires +const data = require('../package.json'); + +/** + * The _model_module_version/_view_module_version this package implements. + * + * The html widget manager assumes that this is the same as the npm package + * version number. + */ +export const MODULE_VERSION = data.version; + +/* + * The current package name. + */ +export const MODULE_NAME = data.name; diff --git a/packages/python/stitch/src/widget.ts b/packages/python/stitch/src/widget.ts new file mode 100644 index 000000000..267fd7f2d --- /dev/null +++ b/packages/python/stitch/src/widget.ts @@ -0,0 +1,114 @@ +// Copyright (c) nopdive +// Distributed under the terms of the Modified BSD License. + +import { + DOMWidgetModel, + DOMWidgetView, + ISerializers, +} from '@jupyter-widgets/base'; + +import { MODULE_NAME, MODULE_VERSION } from './version'; + +// Import the CSS +import '../css/widget.css'; + +export class StitchModel extends DOMWidgetModel { + defaults() { + return { + ...super.defaults(), + _model_name: StitchModel.model_name, + _model_module: StitchModel.model_module, + _model_module_version: StitchModel.model_module_version, + _view_name: StitchModel.view_name, + _view_module: StitchModel.view_module, + _view_module_version: StitchModel.view_module_version, + kernelmsg: '', + clientmsg: '', + srcdoc: '

srcdoc should be defined by the user

', + initial_height: '1px', + initial_width: '1px', + initial_border: "0", + }; + } + + static serializers: ISerializers = { + ...DOMWidgetModel.serializers, + // Add any extra serializers here + }; + + static model_name = 'StitchModel'; + static model_module = MODULE_NAME; + static model_module_version = MODULE_VERSION; + static view_name = 'StitchView'; // Set to null if no view + static view_module = MODULE_NAME; // Set to null if no view + static view_module_version = MODULE_VERSION; +} + +export class StitchView extends DOMWidgetView { + private _iframe: HTMLIFrameElement; + + render() { + // Create sandboxed frame + const iframe = document.createElement('iframe'); + iframe.sandbox.add("allow-scripts"); + iframe.srcdoc = this.model.get("srcdoc"); + iframe.style.height = this.model.get("initial_height"); + iframe.style.width = this.model.get("initial_width"); + iframe.style.border = this.model.get("initial_border"); + iframe.style.display = "block"; + this._iframe = iframe; + + // Send first kernelmsg on load. + const refreshTimeMs = 100; + const sendKernelMsgOnReady = () => { + if (this.model.isNew()) { + window.setTimeout(sendKernelMsgOnReady, refreshTimeMs); + } else { + this.kernelmsg_changed(); + } + }; + window.setTimeout(sendKernelMsgOnReady, refreshTimeMs); + + // Add callback for forwarding messages from client to kernel + const model = this.model; + const recvFromClient = (event: any) => { + const win = iframe.contentWindow; + if (win === event.source && event.data.type === "clientmsg") { + model.set('clientmsg', event.data.content); + model.save_changes(); + } else if (win === event.source && event.data.type === "resize") { + iframe.style.height = event.data.content.height; + iframe.style.width = event.data.content.width; + } + }; + window.addEventListener('message', recvFromClient); + + // Add iframe to root element of widget + this.el.appendChild(this._iframe); + + // Connect callbacks for forwarding from kernel to client + this.model.on('change:kernelmsg', this.kernelmsg_changed, this); + + // Connect callback for when kernel changes the srcdoc + this.model.on('change:srcdoc', this.srcdoc_changed, this); + } + + kernelmsg_changed() { + // Forward message from kernel to client + const kernelmsg = this.model.get('kernelmsg'); + const winmsg = { + 'type': 'kernelmsg', + 'content': kernelmsg + }; + this._iframe.contentWindow?.postMessage(winmsg, '*'); + } + + srcdoc_changed() { + // Apply srcdoc provided by client + const srcdoc = this.model.get('srcdoc'); + this._iframe.srcdoc = srcdoc; + + // Push last kernelmsg immediately to iframe + this.kernelmsg_changed(); + } +} diff --git a/packages/python/stitch/stitch.json b/packages/python/stitch/stitch.json new file mode 100644 index 000000000..d18d678e2 --- /dev/null +++ b/packages/python/stitch/stitch.json @@ -0,0 +1,5 @@ +{ + "load_extensions": { + "stitch/extension": true + } +} diff --git a/packages/python/stitch/stitch/__init__.py b/packages/python/stitch/stitch/__init__.py new file mode 100644 index 000000000..596e1a0e0 --- /dev/null +++ b/packages/python/stitch/stitch/__init__.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright (c) nopdive. +# Distributed under the terms of the Modified BSD License. + +from .stitch import StitchWidget +from ._version import __version__, version_info + +def _jupyter_labextension_paths(): + """Called by Jupyter Lab Server to detect if it is a valid labextension and + to install the widget + Returns + ======= + src: Source directory name to copy files from. Webpack outputs generated files + into this directory and Jupyter Lab copies from this directory during + widget installation + dest: Destination directory name to install widget files to. Jupyter Lab copies + from `src` directory into /labextensions/ directory + during widget installation + """ + return [{ + 'src': 'labextension', + 'dest': 'stitch', + }] + + +def _jupyter_nbextension_paths(): + """Called by Jupyter Notebook Server to detect if it is a valid nbextension and + to install the widget + Returns + ======= + section: The section of the Jupyter Notebook Server to change. + Must be 'notebook' for widget extensions + src: Source directory name to copy files from. Webpack outputs generated files + into this directory and Jupyter Notebook copies from this directory during + widget installation + dest: Destination directory name to install widget files to. Jupyter Notebook copies + from `src` directory into /nbextensions/ directory + during widget installation + require: Path to importable AMD Javascript module inside the + /nbextensions/ directory + """ + return [{ + 'section': 'notebook', + 'src': 'nbextension', + 'dest': 'stitch', + 'require': 'stitch/extension' + }] diff --git a/packages/python/stitch/stitch/_frontend.py b/packages/python/stitch/stitch/_frontend.py new file mode 100644 index 000000000..880a63e74 --- /dev/null +++ b/packages/python/stitch/stitch/_frontend.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright (c) nopdive. +# Distributed under the terms of the Modified BSD License. + +""" +Information about the frontend package of the widgets. +""" + +module_name = "stitch" +module_version = "^0.1.0" diff --git a/packages/python/stitch/stitch/_version.py b/packages/python/stitch/stitch/_version.py new file mode 100644 index 000000000..b56e345f8 --- /dev/null +++ b/packages/python/stitch/stitch/_version.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright (c) nopdive. +# Distributed under the terms of the Modified BSD License. + +version_info = (0, 1, 0, 'dev') +__version__ = ".".join(map(str, version_info)) diff --git a/packages/python/stitch/stitch/nbextension/extension.js b/packages/python/stitch/stitch/nbextension/extension.js new file mode 100644 index 000000000..a06baadcc --- /dev/null +++ b/packages/python/stitch/stitch/nbextension/extension.js @@ -0,0 +1,17 @@ +// Entry point for the notebook bundle containing custom model definitions. +// +define(function() { + "use strict"; + + window['requirejs'].config({ + map: { + '*': { + 'stitch': 'nbextensions/stitch/index', + }, + } + }); + // Export the required load_ipython_extension function + return { + load_ipython_extension : function() {} + }; +}); \ No newline at end of file diff --git a/packages/python/stitch/stitch/stitch.py b/packages/python/stitch/stitch/stitch.py new file mode 100644 index 000000000..f383af105 --- /dev/null +++ b/packages/python/stitch/stitch/stitch.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright (c) nopdive. +# Distributed under the terms of the Modified BSD License. + +""" +Stitch Widget that allows bidirectional comms from Jupyter and JavaScript. +""" + +from ipywidgets import DOMWidget +from traitlets import Unicode +from ._frontend import module_name, module_version + + +class StitchWidget(DOMWidget): + """Widget that purely handles communication between an iframe and kernel via postMessage.""" + + _model_name = Unicode('StitchModel').tag(sync=True) + _model_module = Unicode(module_name).tag(sync=True) + _model_module_version = Unicode(module_version).tag(sync=True) + _view_name = Unicode('StitchView').tag(sync=True) + _view_module = Unicode(module_name).tag(sync=True) + _view_module_version = Unicode(module_version).tag(sync=True) + + kernelmsg = Unicode("").tag(sync=True) + clientmsg = Unicode("").tag(sync=True) + srcdoc = Unicode("

srcdoc should be defined by the user

").tag(sync=True) + initial_height = Unicode("1px").tag(sync=True) + initial_width = Unicode("1px").tag(sync=True) + initial_border = Unicode("0").tag(sync=True) diff --git a/packages/python/stitch/stitch/tests/__init__.py b/packages/python/stitch/stitch/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/python/stitch/stitch/tests/conftest.py b/packages/python/stitch/stitch/tests/conftest.py new file mode 100644 index 000000000..44382d8c1 --- /dev/null +++ b/packages/python/stitch/stitch/tests/conftest.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright (c) nopdive. +# Distributed under the terms of the Modified BSD License. + +import pytest + +from ipykernel.comm import Comm +from ipywidgets import Widget + +class MockComm(Comm): + """A mock Comm object. + + Can be used to inspect calls to Comm's open/send/close methods. + """ + comm_id = 'a-b-c-d' + kernel = 'Truthy' + + def __init__(self, *args, **kwargs): + self.log_open = [] + self.log_send = [] + self.log_close = [] + super(MockComm, self).__init__(*args, **kwargs) + + def open(self, *args, **kwargs): + self.log_open.append((args, kwargs)) + + def send(self, *args, **kwargs): + self.log_send.append((args, kwargs)) + + def close(self, *args, **kwargs): + self.log_close.append((args, kwargs)) + +_widget_attrs = {} +undefined = object() + + +@pytest.fixture +def mock_comm(): + _widget_attrs['_comm_default'] = getattr(Widget, '_comm_default', undefined) + Widget._comm_default = lambda self: MockComm() + _widget_attrs['_ipython_display_'] = Widget._ipython_display_ + def raise_not_implemented(*args, **kwargs): + raise NotImplementedError() + Widget._ipython_display_ = raise_not_implemented + + yield MockComm() + + for attr, value in _widget_attrs.items(): + if value is undefined: + delattr(Widget, attr) + else: + setattr(Widget, attr, value) diff --git a/packages/python/stitch/stitch/tests/test_example.py b/packages/python/stitch/stitch/tests/test_example.py new file mode 100644 index 000000000..dfce827e2 --- /dev/null +++ b/packages/python/stitch/stitch/tests/test_example.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright (c) nopdive. +# Distributed under the terms of the Modified BSD License. + +import pytest + +from ..stitch import StitchWidget + + +def test_example_creation_blank(): + w = StitchWidget() + assert w.value == 'Hello World' diff --git a/packages/python/stitch/stitch/tests/test_nbextension_path.py b/packages/python/stitch/stitch/tests/test_nbextension_path.py new file mode 100644 index 000000000..56a2cbe41 --- /dev/null +++ b/packages/python/stitch/stitch/tests/test_nbextension_path.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# coding: utf-8 + +# Copyright (c) nopdive. +# Distributed under the terms of the Modified BSD License. + + +def test_nbextension_path(): + # Check that magic function can be imported from package root: + from stitch import _jupyter_nbextension_paths + # Ensure that it can be called without incident: + path = _jupyter_nbextension_paths() + # Some sanity checks: + assert len(path) == 1 + assert isinstance(path[0], dict) diff --git a/packages/python/stitch/tsconfig.eslint.json b/packages/python/stitch/tsconfig.eslint.json new file mode 100644 index 000000000..737e3e680 --- /dev/null +++ b/packages/python/stitch/tsconfig.eslint.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": [] +} \ No newline at end of file diff --git a/packages/python/stitch/tsconfig.json b/packages/python/stitch/tsconfig.json new file mode 100644 index 000000000..f143a554e --- /dev/null +++ b/packages/python/stitch/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "declaration": true, + "esModuleInterop":true, + "lib": ["es2015", "dom"], + "module": "commonjs", + "moduleResolution": "node", + "noEmitOnError": true, + "noUnusedLocals": true, + "outDir": "lib", + "resolveJsonModule": true, + "rootDir": "src", + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "strictPropertyInitialization": false, + "target": "es2015", + "types": ["jest"] + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + ], + "exclude": ["src/**/__tests__"] +} diff --git a/packages/python/stitch/webpack.config.js b/packages/python/stitch/webpack.config.js new file mode 100644 index 000000000..8faaf089b --- /dev/null +++ b/packages/python/stitch/webpack.config.js @@ -0,0 +1,91 @@ +const path = require('path'); +const version = require('./package.json').version; + +// Custom webpack rules +const rules = [ + { test: /\.ts$/, loader: 'ts-loader' }, + { test: /\.js$/, loader: 'source-map-loader' }, + { test: /\.css$/, use: ['style-loader', 'css-loader']} +]; + +// Packages that shouldn't be bundled but loaded at runtime +const externals = ['@jupyter-widgets/base']; + +const resolve = { + // Add '.ts' and '.tsx' as resolvable extensions. + extensions: [".webpack.js", ".web.js", ".ts", ".js"] +}; + +module.exports = [ + /** + * Notebook extension + * + * This bundle only contains the part of the JavaScript that is run on load of + * the notebook. + */ + { + entry: './src/extension.ts', + output: { + filename: 'index.js', + path: path.resolve(__dirname, 'stitch', 'nbextension'), + libraryTarget: 'amd', + publicPath: '', + }, + module: { + rules: rules + }, + devtool: 'source-map', + externals, + resolve, + }, + + /** + * Embeddable stitch bundle + * + * This bundle is almost identical to the notebook extension bundle. The only + * difference is in the configuration of the webpack public path for the + * static assets. + * + * The target bundle is always `dist/index.js`, which is the path required by + * the custom widget embedder. + */ + { + entry: './src/index.ts', + output: { + filename: 'index.js', + path: path.resolve(__dirname, 'dist'), + libraryTarget: 'amd', + library: "stitch", + publicPath: 'https://unpkg.com/stitch@' + version + '/dist/' + }, + devtool: 'source-map', + module: { + rules: rules + }, + externals, + resolve, + }, + + + /** + * Documentation widget bundle + * + * This bundle is used to embed widgets in the package documentation. + */ + { + entry: './src/index.ts', + output: { + filename: 'embed-bundle.js', + path: path.resolve(__dirname, 'docs', 'source', '_static'), + library: "stitch", + libraryTarget: 'amd' + }, + module: { + rules: rules + }, + devtool: 'source-map', + externals, + resolve, + } + +]; diff --git a/packages/python/stitch/yarn.lock b/packages/python/stitch/yarn.lock new file mode 100644 index 000000000..f0f3bc47d --- /dev/null +++ b/packages/python/stitch/yarn.lock @@ -0,0 +1,8505 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 6 + cacheKey: 8 + +"@ampproject/remapping@npm:^2.2.0": + version: 2.3.0 + resolution: "@ampproject/remapping@npm:2.3.0" + dependencies: + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.24 + checksum: d3ad7b89d973df059c4e8e6d7c972cbeb1bb2f18f002a3bd04ae0707da214cb06cc06929b65aa2313b9347463df2914772298bae8b1d7973f246bb3f2ab3e8f0 + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/code-frame@npm:7.24.7" + dependencies: + "@babel/highlight": ^7.24.7 + picocolors: ^1.0.0 + checksum: 830e62cd38775fdf84d612544251ce773d544a8e63df667728cc9e0126eeef14c6ebda79be0f0bc307e8318316b7f58c27ce86702e0a1f5c321d842eb38ffda4 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/compat-data@npm:7.25.2" + checksum: b61bc9da7cfe249f19d08da00f4f0c20550cd9ad5bffcde787c2bf61a8a6fa5b66d92bbd89031f3a6e5495a799a2a2499f2947b6cc7964be41979377473ab132 + languageName: node + linkType: hard + +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.7, @babel/core@npm:^7.23.9": + version: 7.25.2 + resolution: "@babel/core@npm:7.25.2" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.25.0 + "@babel/helper-compilation-targets": ^7.25.2 + "@babel/helper-module-transforms": ^7.25.2 + "@babel/helpers": ^7.25.0 + "@babel/parser": ^7.25.0 + "@babel/template": ^7.25.0 + "@babel/traverse": ^7.25.2 + "@babel/types": ^7.25.2 + convert-source-map: ^2.0.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.3 + semver: ^6.3.1 + checksum: 9a1ef604a7eb62195f70f9370cec45472a08114e3934e3eaaedee8fd754edf0730e62347c7b4b5e67d743ce57b5bb8cf3b92459482ca94d06e06246ef021390a + languageName: node + linkType: hard + +"@babel/generator@npm:^7.25.0, @babel/generator@npm:^7.7.2": + version: 7.25.0 + resolution: "@babel/generator@npm:7.25.0" + dependencies: + "@babel/types": ^7.25.0 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + jsesc: ^2.5.1 + checksum: bf25649dde4068bff8e387319bf820f2cb3b1af7b8c0cfba0bd90880656427c8bad96cd5cb6db7058d20cffe93149ee59da16567018ceaa21ecaefbf780a785c + languageName: node + linkType: hard + +"@babel/helper-annotate-as-pure@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-annotate-as-pure@npm:7.24.7" + dependencies: + "@babel/types": ^7.24.7 + checksum: 6178566099a6a0657db7a7fa601a54fb4731ca0b8614fbdccfd8e523c210c13963649bc8fdfd53ce7dd14d05e3dda2fb22dea5b30113c488b9eb1a906d60212e + languageName: node + linkType: hard + +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 71a6158a9fdebffb82fdc400d5555ba8f2e370cea81a0d578155877bdc4db7d5252b75c43b2fdf3f72b3f68348891f99bd35ae315542daad1b7ace8322b1abcb + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7, @babel/helper-compilation-targets@npm:^7.24.8, @babel/helper-compilation-targets@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-compilation-targets@npm:7.25.2" + dependencies: + "@babel/compat-data": ^7.25.2 + "@babel/helper-validator-option": ^7.24.8 + browserslist: ^4.23.1 + lru-cache: ^5.1.1 + semver: ^6.3.1 + checksum: aed33c5496cb9db4b5e2d44e26bf8bc474074cc7f7bb5ebe1d4a20fdeb362cb3ba9e1596ca18c7484bcd6e5c3a155ab975e420d520c0ae60df81f9de04d0fd16 + languageName: node + linkType: hard + +"@babel/helper-create-class-features-plugin@npm:^7.24.7": + version: 7.25.0 + resolution: "@babel/helper-create-class-features-plugin@npm:7.25.0" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-member-expression-to-functions": ^7.24.8 + "@babel/helper-optimise-call-expression": ^7.24.7 + "@babel/helper-replace-supers": ^7.25.0 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/traverse": ^7.25.0 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: e986c1187e16837b71f12920bd77e672b4bc19ac6dfe30b9d9d515a311c5cc5a085a8e337ac8597b1cb7bd0efdbfcc66f69bf652786c9a022070f9b782deec0d + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.24.7, @babel/helper-create-regexp-features-plugin@npm:^7.25.0": + version: 7.25.2 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.25.2" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + regexpu-core: ^5.3.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: df55fdc6a1f3090dd37d91347df52d9322d52affa239543808dc142f8fe35e6787e67d8612337668198fac85826fafa9e6772e6c28b7d249ec94e6fafae5da6e + languageName: node + linkType: hard + +"@babel/helper-define-polyfill-provider@npm:^0.6.2": + version: 0.6.2 + resolution: "@babel/helper-define-polyfill-provider@npm:0.6.2" + dependencies: + "@babel/helper-compilation-targets": ^7.22.6 + "@babel/helper-plugin-utils": ^7.22.5 + debug: ^4.1.1 + lodash.debounce: ^4.0.8 + resolve: ^1.14.2 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 2bba965ea9a4887ddf9c11d51d740ab473bd7597b787d042c325f6a45912dfe908c2d6bb1d837bf82f7e9fa51e6ad5150563c58131d2bb85515e63d971414a9c + languageName: node + linkType: hard + +"@babel/helper-member-expression-to-functions@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-member-expression-to-functions@npm:7.24.8" + dependencies: + "@babel/traverse": ^7.24.8 + "@babel/types": ^7.24.8 + checksum: bf923d05d81b06857f4ca4fe9c528c9c447a58db5ea39595bb559eae2fce01a8266173db0fd6a2ec129d7bbbb9bb22f4e90008252f7c66b422c76630a878a4bc + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-module-imports@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 8ac15d96d262b8940bc469052a048e06430bba1296369be695fabdf6799f201dd0b00151762b56012a218464e706bc033f27c07f6cec20c6f8f5fd6543c67054 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.25.0, @babel/helper-module-transforms@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-module-transforms@npm:7.25.2" + dependencies: + "@babel/helper-module-imports": ^7.24.7 + "@babel/helper-simple-access": ^7.24.7 + "@babel/helper-validator-identifier": ^7.24.7 + "@babel/traverse": ^7.25.2 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 282d4e3308df6746289e46e9c39a0870819630af5f84d632559171e4fae6045684d771a65f62df3d569e88ccf81dc2def78b8338a449ae3a94bb421aa14fc367 + languageName: node + linkType: hard + +"@babel/helper-optimise-call-expression@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-optimise-call-expression@npm:7.24.7" + dependencies: + "@babel/types": ^7.24.7 + checksum: 280654eaf90e92bf383d7eed49019573fb35a98c9e992668f701ad099957246721044be2068cf6840cb2299e0ad393705a1981c88c23a1048096a8d59e5f79a3 + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.24.8 + resolution: "@babel/helper-plugin-utils@npm:7.24.8" + checksum: 73b1a83ba8bcee21dc94de2eb7323207391715e4369fd55844bb15cf13e3df6f3d13a40786d990e6370bf0f571d94fc31f70dec96c1d1002058258c35ca3767a + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.24.7, @babel/helper-remap-async-to-generator@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-remap-async-to-generator@npm:7.25.0" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-wrap-function": ^7.25.0 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 47f3065e43fe9d6128ddb4291ffb9cf031935379265fd13de972b5f241943121f7583efb69cd2e1ecf39e3d0f76f047547d56c3fcc2c853b326fad5465da0bd7 + languageName: node + linkType: hard + +"@babel/helper-replace-supers@npm:^7.24.7, @babel/helper-replace-supers@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-replace-supers@npm:7.25.0" + dependencies: + "@babel/helper-member-expression-to-functions": ^7.24.8 + "@babel/helper-optimise-call-expression": ^7.24.7 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: f669fc2487c22d40b808f94b9c3ee41129484d5ef0ba689bdd70f216ff91e10b6b021d2f8cd37e7bdd700235a2a6ae6622526344f064528190383bf661ac65f8 + languageName: node + linkType: hard + +"@babel/helper-simple-access@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-simple-access@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: ddbf55f9dea1900213f2a1a8500fabfd21c5a20f44dcfa957e4b0d8638c730f88751c77f678644f754f1a1dc73f4eb8b766c300deb45a9daad000e4247957819 + languageName: node + linkType: hard + +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 11b28fe534ce2b1a67c4d8e51a7b5711a2a0a0cae802f74614eee54cca58c744d9a62f6f60103c41759e81c537d270bfd665bf368a6bea214c6052f2094f8407 + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-string-parser@npm:7.24.8" + checksum: 39b03c5119216883878655b149148dc4d2e284791e969b19467a9411fccaa33f7a713add98f4db5ed519535f70ad273cdadfd2eb54d47ebbdeac5083351328ce + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-identifier@npm:7.24.7" + checksum: 6799ab117cefc0ecd35cd0b40ead320c621a298ecac88686a14cffceaac89d80cdb3c178f969861bf5fa5e4f766648f9161ea0752ecfe080d8e89e3147270257 + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-validator-option@npm:7.24.8" + checksum: a52442dfa74be6719c0608fee3225bd0493c4057459f3014681ea1a4643cd38b68ff477fe867c4b356da7330d085f247f0724d300582fa4ab9a02efaf34d107c + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-wrap-function@npm:7.25.0" + dependencies: + "@babel/template": ^7.25.0 + "@babel/traverse": ^7.25.0 + "@babel/types": ^7.25.0 + checksum: 0095b4741704066d1687f9bbd5370bb88c733919e4275e49615f70c180208148ff5f24ab58d186ce92f8f5d28eab034ec6617e9264590cc4744c75302857629c + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helpers@npm:7.25.0" + dependencies: + "@babel/template": ^7.25.0 + "@babel/types": ^7.25.0 + checksum: 739e3704ff41a30f5eaac469b553f4d3ab02be6ced083f5925851532dfbd9efc5c347728e77b754ed0b262a4e5e384e60932a62c192d338db7e4b7f3adf9f4a7 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/highlight@npm:7.24.7" + dependencies: + "@babel/helper-validator-identifier": ^7.24.7 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + picocolors: ^1.0.0 + checksum: 5cd3a89f143671c4ac129960024ba678b669e6fc673ce078030f5175002d1d3d52bc10b22c5b916a6faf644b5028e9a4bd2bb264d053d9b05b6a98690f1d46f1 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.25.0, @babel/parser@npm:^7.25.3": + version: 7.25.3 + resolution: "@babel/parser@npm:7.25.3" + dependencies: + "@babel/types": ^7.25.2 + bin: + parser: ./bin/babel-parser.js + checksum: b55aba64214fa1d66ccd0d29f476d2e55a48586920d280f88c546f81cbbececc0e01c9d05a78d6bf206e8438b9c426caa344942c1a581eecc4d365beaab8a20e + languageName: node + linkType: hard + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.3": + version: 7.25.3 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.25.3" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.3 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: d3dba60f360defe70eb43e35a1b17ea9dd4a99e734249e15be3d5c288019644f96f88d7ff51990118fda0845b4ad50f6d869e0382232b1d8b054d113d4eea7e2 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: fd56d1e6435f2c008ca9050ea906ff7eedcbec43f532f2bf2e7e905d8bf75bf5e4295ea9593f060394e2c8e45737266ccbf718050bad2dd7be4e7613c60d1b5b + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 13ed301b108d85867d64226bbc4032b07dd1a23aab68e9e32452c4fe3930f2198bb65bdae9c262c4104bd5e45647bc1830d25d43d356ee9a137edd8d5fab8350 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/plugin-transform-optional-chaining": ^7.24.7 + peerDependencies: + "@babel/core": ^7.13.0 + checksum: 07b92878ac58a98ea1fdf6a8b4ec3413ba4fa66924e28b694d63ec5b84463123fbf4d7153b56cf3cedfef4a3482c082fe3243c04f8fb2c041b32b0e29b4a9e21 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: c8d08b8d6cc71451ad2a50cf7db72ab5b41c1e5e2e4d56cf6837a25a61270abd682c6b8881ab025f11a552d2024b3780519bb051459ebb71c27aed13d9917663 + languageName: node + linkType: hard + +"@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2": + version: 7.21.0-placeholder-for-preset-env.2 + resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d97745d098b835d55033ff3a7fb2b895b9c5295b08a5759e4f20df325aa385a3e0bc9bd5ad8f2ec554a44d4e6525acfc257b8c5848a1345cb40f26a30e277e91 + languageName: node + linkType: hard + +"@babel/plugin-syntax-async-generators@npm:^7.8.4": + version: 7.8.4 + resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7ed1c1d9b9e5b64ef028ea5e755c0be2d4e5e4e3d6cf7df757b9a8c4cfa4193d268176d0f1f7fbecdda6fe722885c7fda681f480f3741d8a2d26854736f05367 + languageName: node + linkType: hard + +"@babel/plugin-syntax-bigint@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-bigint@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3a10849d83e47aec50f367a9e56a6b22d662ddce643334b087f9828f4c3dd73bdc5909aaeabe123fed78515767f9ca43498a0e621c438d1cd2802d7fae3c9648 + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-properties@npm:^7.12.13": + version: 7.12.13 + resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" + dependencies: + "@babel/helper-plugin-utils": ^7.12.13 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 24f34b196d6342f28d4bad303612d7ff566ab0a013ce89e775d98d6f832969462e7235f3e7eaf17678a533d4be0ba45d3ae34ab4e5a9dcbda5d98d49e5efa2fc + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-static-block@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3e80814b5b6d4fe17826093918680a351c2d34398a914ce6e55d8083d72a9bdde4fbaf6a2dcea0e23a03de26dc2917ae3efd603d27099e2b98380345703bf948 + languageName: node + linkType: hard + +"@babel/plugin-syntax-dynamic-import@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-dynamic-import@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ce307af83cf433d4ec42932329fad25fa73138ab39c7436882ea28742e1c0066626d224e0ad2988724c82644e41601cef607b36194f695cb78a1fcdc959637bd + languageName: node + linkType: hard + +"@babel/plugin-syntax-export-namespace-from@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-export-namespace-from@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 85740478be5b0de185228e7814451d74ab8ce0a26fcca7613955262a26e99e8e15e9da58f60c754b84515d4c679b590dbd3f2148f0f58025f4ae706f1c5a5d4a + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-assertions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c4d67be4eb1d4637e361477dbe01f5b392b037d17c1f861cfa0faa120030e137aab90a9237931b8040fd31d1e5d159e11866fa1165f78beef7a3be876a391a17 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 590dbb5d1a15264f74670b427b8d18527672c3d6c91d7bae7e65f80fd810edbc83d90e68065088644cbad3f2457ed265a54a9956fb789fcb9a5b521822b3a275 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 166ac1125d10b9c0c430e4156249a13858c0366d38844883d75d27389621ebe651115cb2ceb6dc011534d5055719fa1727b59f39e1ab3ca97820eef3dcab5b9b + languageName: node + linkType: hard + +"@babel/plugin-syntax-json-strings@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bf5aea1f3188c9a507e16efe030efb996853ca3cadd6512c51db7233cc58f3ac89ff8c6bdfb01d30843b161cfe7d321e1bf28da82f7ab8d7e6bc5464666f354a + languageName: node + linkType: hard + +"@babel/plugin-syntax-jsx@npm:^7.7.2": + version: 7.24.7 + resolution: "@babel/plugin-syntax-jsx@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7a5ca629d8ca1e1ee78705a78e58c12920d07ed8006d7e7232b31296a384ff5e41d7b649bde5561196041037bbb9f9715be1d1c20975df87ca204f34ad15b965 + languageName: node + linkType: hard + +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: aff33577037e34e515911255cdbb1fd39efee33658aa00b8a5fd3a4b903585112d037cce1cc9e4632f0487dc554486106b79ccd5ea63a2e00df4363f6d4ff886 + languageName: node + linkType: hard + +"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 87aca4918916020d1fedba54c0e232de408df2644a425d153be368313fdde40d96088feed6c4e5ab72aac89be5d07fef2ddf329a15109c5eb65df006bf2580d1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 01ec5547bd0497f76cc903ff4d6b02abc8c05f301c88d2622b6d834e33a5651aa7c7a3d80d8d57656a4588f7276eba357f6b7e006482f5b564b7a6488de493a1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fddcf581a57f77e80eb6b981b10658421bc321ba5f0a5b754118c6a92a5448f12a0c336f77b8abf734841e102e5126d69110a306eadb03ca3e1547cab31f5cbf + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 910d90e72bc90ea1ce698e89c1027fed8845212d5ab588e35ef91f13b93143845f94e2539d831dc8d8ededc14ec02f04f7bd6a8179edd43a326c784e7ed7f0b9 + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-chaining@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: eef94d53a1453361553c1f98b68d17782861a04a392840341bc91780838dd4e695209c783631cf0de14c635758beafb6a3a65399846ffa4386bff90639347f30 + languageName: node + linkType: hard + +"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b317174783e6e96029b743ccff2a67d63d38756876e7e5d0ba53a322e38d9ca452c13354a57de1ad476b4c066dbae699e0ca157441da611117a47af88985ecda + languageName: node + linkType: hard + +"@babel/plugin-syntax-top-level-await@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bbd1a56b095be7820029b209677b194db9b1d26691fe999856462e66b25b281f031f3dfd91b1619e9dcf95bebe336211833b854d0fb8780d618e35667c2d0d7e + languageName: node + linkType: hard + +"@babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.24.7 + resolution: "@babel/plugin-syntax-typescript@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 56fe84f3044ecbf038977281648db6b63bd1301f2fff6595820dc10ee276c1d1586919d48d52a8d497ecae32c958be38f42c1c8d174dc58aad856c516dc5b35a + languageName: node + linkType: hard + +"@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a651d700fe63ff0ddfd7186f4ebc24447ca734f114433139e3c027bc94a900d013cf1ef2e2db8430425ba542e39ae160c3b05f06b59fd4656273a3df97679e9c + languageName: node + linkType: hard + +"@babel/plugin-transform-arrow-functions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 707c209b5331c7dc79bd326128c6a6640dbd62a78da1653c844db20c4f36bf7b68454f1bc4d2d051b3fde9136fa291f276ec03a071bb00ee653069ff82f91010 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-generator-functions@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-remap-async-to-generator": ^7.25.0 + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cce2bab70ad871ac11751bede006bd4861888f4c63bc9954be38620b14cc6890a4cbc633c1062b89c5fe288ce74b9d1974cc0d43c04baeeb2b13231a236fba85 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-to-generator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.24.7" + dependencies: + "@babel/helper-module-imports": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-remap-async-to-generator": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 13704fb3b83effc868db2b71bfb2c77b895c56cb891954fc362e95e200afd523313b0e7cf04ce02f45b05e76017c5b5fa8070c92613727a35131bb542c253a36 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoped-functions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 249cdcbff4e778b177245f9652b014ea4f3cd245d83297f10a7bf6d97790074089aa62bcde8c08eb299c5e68f2faed346b587d3ebac44d625ba9a83a4ee27028 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoping@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-block-scoping@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b1a8f932f69ad2a47ae3e02b4cedd2a876bfc2ac9cf72a503fd706cdc87272646fe9eed81e068c0fc639647033de29f7fa0c21cddd1da0026f83dbaac97316a8 + languageName: node + linkType: hard + +"@babel/plugin-transform-class-properties@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-class-properties@npm:7.24.7" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1348d7ce74da38ba52ea85b3b4289a6a86913748569ef92ef0cff30702a9eb849e5eaf59f1c6f3517059aa68115fb3067e389735dccacca39add4e2b0c67e291 + languageName: node + linkType: hard + +"@babel/plugin-transform-class-static-block@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-class-static-block@npm:7.24.7" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + peerDependencies: + "@babel/core": ^7.12.0 + checksum: 324049263504f18416f1c3e24033baebfafd05480fdd885c8ebe6f2b415b0fc8e0b98d719360f9e30743cc78ac387fabc0b3c6606d2b54135756ffb92963b382 + languageName: node + linkType: hard + +"@babel/plugin-transform-classes@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-classes@npm:7.25.0" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-compilation-targets": ^7.24.8 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-replace-supers": ^7.25.0 + "@babel/traverse": ^7.25.0 + globals: ^11.1.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ff97f168e6a18fa4e7bb439f1a170dc83c470973091c22c74674769350ab572be5af017cdb64fbd261fe99d068a4ee88f1b7fa7f5ab524d84c2f2833b116e577 + languageName: node + linkType: hard + +"@babel/plugin-transform-computed-properties@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-computed-properties@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/template": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0cf8c1b1e4ea57dec8d4612460d84fd4cdbf71a7499bb61ee34632cf89018a59eee818ffca88a8d99ee7057c20a4257044d7d463fda6daef9bf1db9fa81563cb + languageName: node + linkType: hard + +"@babel/plugin-transform-destructuring@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-destructuring@npm:7.24.8" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0b4bd3d608979a1e5bd97d9d42acd5ad405c7fffa61efac4c7afd8e86ea6c2d91ab2d94b6a98d63919571363fe76e0b03c4ff161f0f60241b895842596e4a999 + languageName: node + linkType: hard + +"@babel/plugin-transform-dotall-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 67b10fc6abb1f61f0e765288eb4c6d63d1d0f9fc0660e69f6f2170c56fa16bc74e49857afc644beda112b41771cd90cf52df0940d11e97e52617c77c7dcff171 + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-keys@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d1da2ff85ecb56a63f4ccfd9dc9ae69400d85f0dadf44ecddd9e71c6e5c7a9178e74e3a9637555f415a2bb14551e563f09f98534ab54f53d25e8439fdde6ba2d + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.25.0" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.25.0 + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 608d6b0e77341189508880fd1a9f605a38d0803dd6f678ea3920ab181b17b377f6d5221ae8cf0104c7a044d30d4ddb0366bd064447695671d78457a656bb264f + languageName: node + linkType: hard + +"@babel/plugin-transform-dynamic-import@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 776509ff62ab40c12be814a342fc56a5cc09b91fb63032b2633414b635875fd7da03734657be0f6db2891fe6e3033b75d5ddb6f2baabd1a02e4443754a785002 + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.24.7" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 23c84a23eb56589fdd35a3540f9a1190615be069110a2270865223c03aee3ba4e0fc68fe14850800cf36f0712b26e4964d3026235261f58f0405a29fe8dac9b1 + languageName: node + linkType: hard + +"@babel/plugin-transform-export-namespace-from@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3bd3a10038f10ae0dea1ee42137f3edcf7036b5e9e570a0d1cbd0865f03658990c6c2d84fa2475f87a754e7dc5b46766c16f7ce5c9b32c3040150b6a21233a80 + languageName: node + linkType: hard + +"@babel/plugin-transform-for-of@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-for-of@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a53b42dc93ab4b7d1ebd3c695b52be22b3d592f6a3dbdb3dc2fea2c8e0a7e1508fe919864c455cde552aec44ce7518625fccbb70c7063373ca228d884f4f49ea + languageName: node + linkType: hard + +"@babel/plugin-transform-function-name@npm:^7.25.1": + version: 7.25.1 + resolution: "@babel/plugin-transform-function-name@npm:7.25.1" + dependencies: + "@babel/helper-compilation-targets": ^7.24.8 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 743f3ea03bbc5a90944849d5a880b6bd9243dddbde581a46952da76e53a0b74c1e2424133fe8129d7a152c1f8c872bcd27e0b6728d7caadabd1afa7bb892e1e0 + languageName: node + linkType: hard + +"@babel/plugin-transform-json-strings@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-json-strings@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-json-strings": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 88874d0b7a1ddea66c097fc0abb68801ffae194468aa44b828dde9a0e20ac5d8647943793de86092eabaa2911c96f67a6b373793d4bb9c932ef81b2711c06c2e + languageName: node + linkType: hard + +"@babel/plugin-transform-literals@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/plugin-transform-literals@npm:7.25.2" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 70c9bb40e377a306bd8f500899fb72127e527517914466e95dc6bb53fa7a0f51479db244a54a771b5780fc1eab488fedd706669bf11097b81a23c81ab7423eb1 + languageName: node + linkType: hard + +"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3367ce0be243704dc6fce23e86a592c4380f01998ee5dd9f94c54b1ef7b971ac6f8a002901eb51599ac6cbdc0d067af8d1a720224fca1c40fde8bb8aab804aac + languageName: node + linkType: hard + +"@babel/plugin-transform-member-expression-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2720c57aa3bf70576146ba7d6ea03227f4611852122d76d237924f7b008dafc952e6ae61a19e5024f26c665f44384bbd378466f01b6bd1305b3564a3b7fb1a5d + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-amd@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-modules-amd@npm:7.24.7" + dependencies: + "@babel/helper-module-transforms": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f1dd0fb2f46c0f8f21076b8c7ccd5b33a85ce6dcb31518ea4c648d9a5bb2474cd4bd87c9b1b752e68591e24b022e334ba0d07631fef2b6b4d8a4b85cf3d581f5 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-commonjs@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.8" + dependencies: + "@babel/helper-module-transforms": ^7.24.8 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-simple-access": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a4cf95b1639c33382064b44558f73ee5fac023f2a94d16e549d2bb55ceebd5cbc10fcddd505d08cd5bc97f5a64af9fd155512358b7dcf7b1a0082e8945cf21c5 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-systemjs@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.25.0" + dependencies: + "@babel/helper-module-transforms": ^7.25.0 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-validator-identifier": ^7.24.7 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fe673bec08564e491847324bb80a1e6edfb229f5c37e58a094d51e95306e7b098e1d130fc43e992d22debd93b9beac74441ffc3f6ea5d78f6b2535896efa0728 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-umd@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-modules-umd@npm:7.24.7" + dependencies: + "@babel/helper-module-transforms": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9ff1c464892efe042952ba778468bda6131b196a2729615bdcc3f24cdc94014f016a4616ee5643c5845bade6ba698f386833e61056d7201314b13a7fd69fac88 + languageName: node + linkType: hard + +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: f1c6c7b5d60a86b6d7e4dd098798e1d393d55e993a0b57a73b53640c7a94985b601a96bdacee063f809a9a700bcea3a2ff18e98fa561554484ac56b761d774bd + languageName: node + linkType: hard + +"@babel/plugin-transform-new-target@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-new-target@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3cb94cd1076b270f768f91fdcf9dd2f6d487f8dbfff3df7ca8d07b915900b86d02769a35ba1407d16fe49499012c8f055e1741299e2c880798b953d942a8fa1b + languageName: node + linkType: hard + +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4a9221356401d87762afbc37a9e8e764afc2daf09c421117537820f8cfbed6876888372ad3a7bcfae2d45c95f026651f050ab4020b777be31d3ffb00908dbdd3 + languageName: node + linkType: hard + +"@babel/plugin-transform-numeric-separator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 561b5f1d08b2c3f92ce849f092751558b5e6cfeb7eb55c79e7375c34dd9c3066dce5e630bb439affef6adcf202b6cbcaaa23870070276fa5bb429c8f5b8c7514 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-rest-spread@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.24.7" + dependencies: + "@babel/helper-compilation-targets": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-transform-parameters": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 169d257b9800c13e1feb4c37fb05dae84f702e58b342bb76e19e82e6692b7b5337c9923ee89e3916a97c0dd04a3375bdeca14f5e126f110bbacbeb46d1886ca2 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-super@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-object-super@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-replace-supers": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f71e607a830ee50a22fa1a2686524d3339440cf9dea63032f6efbd865cfe4e35000e1e3f3492459e5c986f7c0c07dc36938bf3ce61fc9ba5f8ab732d0b64ab37 + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-catch-binding@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7229f3a5a4facaab40f4fdfc7faabc157dc38a67d66bed7936599f4bc509e0bff636f847ac2aa45294881fce9cf8a0a460b85d2a465b7b977de9739fce9b18f6 + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-chaining@npm:^7.24.7, @babel/plugin-transform-optional-chaining@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.8" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 45e55e3a2fffb89002d3f89aef59c141610f23b60eee41e047380bffc40290b59f64fc649aa7ec5281f73d41b2065410d788acc6afaad2a9f44cad6e8af04442 + languageName: node + linkType: hard + +"@babel/plugin-transform-parameters@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-parameters@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ab534b03ac2eff94bc79342b8f39a4584666f5305a6c63c1964afda0b1b004e6b861e49d1683548030defe248e3590d3ff6338ee0552cb90c064f7e1479968c3 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-methods@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-private-methods@npm:7.24.7" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c151548e34909be2adcceb224d8fdd70bafa393bc1559a600906f3f647317575bf40db670470934a360e90ee8084ef36dffa34ec25d387d414afd841e74cf3fe + languageName: node + linkType: hard + +"@babel/plugin-transform-private-property-in-object@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.24.7" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-create-class-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8cee9473095305cc787bb653fd681719b49363281feabf677db8a552e8e41c94441408055d7e5fd5c7d41b315e634fa70b145ad0c7c54456216049df4ed57350 + languageName: node + linkType: hard + +"@babel/plugin-transform-property-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-property-literals@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9aeefc3aab6c6bf9d1fae1cf3a2d38c7d886fd3c6c81b7c608c477f5758aee2e7abf52f32724310fe861da61af934ee2508b78a5b5f234b9740c9134e1c14437 + languageName: node + linkType: hard + +"@babel/plugin-transform-regenerator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-regenerator@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + regenerator-transform: ^0.15.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 20c6c3fb6fc9f407829087316653388d311e8c1816b007609bb09aeef254092a7157adace8b3aaa8f34be752503717cb85c88a5fe482180a9b11bcbd676063be + languageName: node + linkType: hard + +"@babel/plugin-transform-reserved-words@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-reserved-words@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3d5876954d5914d7270819479504f30c4bf5452a65c677f44e2dab2db50b3c9d4b47793c45dfad7abf4f377035dd79e4b3f554ae350df9f422201d370ce9f8dd + languageName: node + linkType: hard + +"@babel/plugin-transform-shorthand-properties@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7b524245814607188212b8eb86d8c850e5974203328455a30881b4a92c364b93353fae14bc2af5b614ef16300b75b8c1d3b8f3a08355985b4794a7feb240adc3 + languageName: node + linkType: hard + +"@babel/plugin-transform-spread@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-spread@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4c4254c8b9cceb1a8f975fa9b92257ddb08380a35c0a3721b8f4b9e13a3d82e403af2e0fba577b9f2452dd8f06bc3dea71cc53b1e2c6af595af5db52a13429d6 + languageName: node + linkType: hard + +"@babel/plugin-transform-sticky-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 118fc7a7ebf7c20411b670c8a030535fdfe4a88bc5643bb625a584dbc4c8a468da46430a20e6bf78914246962b0f18f1b9d6a62561a7762c4f34a038a5a77179 + languageName: node + linkType: hard + +"@babel/plugin-transform-template-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-template-literals@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ad44e5826f5a98c1575832dbdbd033adfe683cdff195e178528ead62507564bf02f479b282976cfd3caebad8b06d5fd7349c1cdb880dec3c56daea4f1f179619 + languageName: node + linkType: hard + +"@babel/plugin-transform-typeof-symbol@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.8" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8663a8e7347cedf181001d99c88cf794b6598c3d82f324098510fe8fb8bd22113995526a77aa35a3cc5d70ffd0617a59dd0d10311a9bf0e1a3a7d3e59b900c00 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-escapes@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4af0a193e1ddea6ff82b2b15cc2501b872728050bd625740b813c8062fec917d32d530ff6b41de56c15e7296becdf3336a58db81f5ca8e7c445c1306c52f3e01 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-property-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: aae13350c50973f5802ca7906d022a6a0cc0e3aebac9122d0450bbd51e78252d4c2032ad69385e2759fcbdd3aac5d571bd7e26258907f51f8e1a51b53be626c2 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1cb4e70678906e431da0a05ac3f8350025fee290304ad7482d9cfaa1ca67b2e898654de537c9268efbdad5b80d3ebadf42b4a88ea84609bd8a4cce7b11b48afd + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-sets-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 08a2844914f33dacd2ce1ab021ce8c1cc35dc6568521a746d8bf29c21571ee5be78787b454231c4bb3526cbbe280f1893223c82726cec5df2be5dae0a3b51837 + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.23.8": + version: 7.25.3 + resolution: "@babel/preset-env@npm:7.25.3" + dependencies: + "@babel/compat-data": ^7.25.2 + "@babel/helper-compilation-targets": ^7.25.2 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-validator-option": ^7.24.8 + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.25.3 + "@babel/plugin-bugfix-safari-class-field-initializer-scope": ^7.25.0 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.25.0 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.24.7 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.25.0 + "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/plugin-syntax-class-properties": ^7.12.13 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + "@babel/plugin-syntax-import-assertions": ^7.24.7 + "@babel/plugin-syntax-import-attributes": ^7.24.7 + "@babel/plugin-syntax-import-meta": ^7.10.4 + "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + "@babel/plugin-syntax-top-level-await": ^7.14.5 + "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 + "@babel/plugin-transform-arrow-functions": ^7.24.7 + "@babel/plugin-transform-async-generator-functions": ^7.25.0 + "@babel/plugin-transform-async-to-generator": ^7.24.7 + "@babel/plugin-transform-block-scoped-functions": ^7.24.7 + "@babel/plugin-transform-block-scoping": ^7.25.0 + "@babel/plugin-transform-class-properties": ^7.24.7 + "@babel/plugin-transform-class-static-block": ^7.24.7 + "@babel/plugin-transform-classes": ^7.25.0 + "@babel/plugin-transform-computed-properties": ^7.24.7 + "@babel/plugin-transform-destructuring": ^7.24.8 + "@babel/plugin-transform-dotall-regex": ^7.24.7 + "@babel/plugin-transform-duplicate-keys": ^7.24.7 + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ^7.25.0 + "@babel/plugin-transform-dynamic-import": ^7.24.7 + "@babel/plugin-transform-exponentiation-operator": ^7.24.7 + "@babel/plugin-transform-export-namespace-from": ^7.24.7 + "@babel/plugin-transform-for-of": ^7.24.7 + "@babel/plugin-transform-function-name": ^7.25.1 + "@babel/plugin-transform-json-strings": ^7.24.7 + "@babel/plugin-transform-literals": ^7.25.2 + "@babel/plugin-transform-logical-assignment-operators": ^7.24.7 + "@babel/plugin-transform-member-expression-literals": ^7.24.7 + "@babel/plugin-transform-modules-amd": ^7.24.7 + "@babel/plugin-transform-modules-commonjs": ^7.24.8 + "@babel/plugin-transform-modules-systemjs": ^7.25.0 + "@babel/plugin-transform-modules-umd": ^7.24.7 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.24.7 + "@babel/plugin-transform-new-target": ^7.24.7 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.24.7 + "@babel/plugin-transform-numeric-separator": ^7.24.7 + "@babel/plugin-transform-object-rest-spread": ^7.24.7 + "@babel/plugin-transform-object-super": ^7.24.7 + "@babel/plugin-transform-optional-catch-binding": ^7.24.7 + "@babel/plugin-transform-optional-chaining": ^7.24.8 + "@babel/plugin-transform-parameters": ^7.24.7 + "@babel/plugin-transform-private-methods": ^7.24.7 + "@babel/plugin-transform-private-property-in-object": ^7.24.7 + "@babel/plugin-transform-property-literals": ^7.24.7 + "@babel/plugin-transform-regenerator": ^7.24.7 + "@babel/plugin-transform-reserved-words": ^7.24.7 + "@babel/plugin-transform-shorthand-properties": ^7.24.7 + "@babel/plugin-transform-spread": ^7.24.7 + "@babel/plugin-transform-sticky-regex": ^7.24.7 + "@babel/plugin-transform-template-literals": ^7.24.7 + "@babel/plugin-transform-typeof-symbol": ^7.24.8 + "@babel/plugin-transform-unicode-escapes": ^7.24.7 + "@babel/plugin-transform-unicode-property-regex": ^7.24.7 + "@babel/plugin-transform-unicode-regex": ^7.24.7 + "@babel/plugin-transform-unicode-sets-regex": ^7.24.7 + "@babel/preset-modules": 0.1.6-no-external-plugins + babel-plugin-polyfill-corejs2: ^0.4.10 + babel-plugin-polyfill-corejs3: ^0.10.4 + babel-plugin-polyfill-regenerator: ^0.6.1 + core-js-compat: ^3.37.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9735a44e557f7ef4ade87f59c0d69e4af3383432a23ae7a3cba33e3741bd7812f2d6403a0d94ebfda5f4bd9fdc6250a52c4a156407029f590fde511a792e64e2 + languageName: node + linkType: hard + +"@babel/preset-modules@npm:0.1.6-no-external-plugins": + version: 0.1.6-no-external-plugins + resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" + dependencies: + "@babel/helper-plugin-utils": ^7.0.0 + "@babel/types": ^7.4.4 + esutils: ^2.0.2 + peerDependencies: + "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 + checksum: 4855e799bc50f2449fb5210f78ea9e8fd46cf4f242243f1e2ed838e2bd702e25e73e822e7f8447722a5f4baa5e67a8f7a0e403f3e7ce04540ff743a9c411c375 + languageName: node + linkType: hard + +"@babel/regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "@babel/regjsgen@npm:0.8.0" + checksum: 89c338fee774770e5a487382170711014d49a68eb281e74f2b5eac88f38300a4ad545516a7786a8dd5702e9cf009c94c2f582d200f077ac5decd74c56b973730 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.8.4": + version: 7.25.0 + resolution: "@babel/runtime@npm:7.25.0" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 4a2a374a58eb01aaa65c5762606e90b3a1f448e0c637d42278b6cc0b42a9f5399b5f381ba9f237ee087da2860d14dd2d1de7bddcbe18be6a3cafba97e44bed64 + languageName: node + linkType: hard + +"@babel/template@npm:^7.24.7, @babel/template@npm:^7.25.0, @babel/template@npm:^7.3.3": + version: 7.25.0 + resolution: "@babel/template@npm:7.25.0" + dependencies: + "@babel/code-frame": ^7.24.7 + "@babel/parser": ^7.25.0 + "@babel/types": ^7.25.0 + checksum: 3f2db568718756d0daf2a16927b78f00c425046b654cd30b450006f2e84bdccaf0cbe6dc04994aa1f5f6a4398da2f11f3640a4d3ee31722e43539c4c919c817b + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8, @babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.1, @babel/traverse@npm:^7.25.2, @babel/traverse@npm:^7.25.3": + version: 7.25.3 + resolution: "@babel/traverse@npm:7.25.3" + dependencies: + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.25.0 + "@babel/parser": ^7.25.3 + "@babel/template": ^7.25.0 + "@babel/types": ^7.25.2 + debug: ^4.3.1 + globals: ^11.1.0 + checksum: 5661308b1357816f1d4e2813a5dd82c6053617acc08c5c95db051b8b6577d07c4446bc861c9a5e8bf294953ac8266ae13d7d9d856b6b889fc0d34c1f51abbd8c + languageName: node + linkType: hard + +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.2, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": + version: 7.25.2 + resolution: "@babel/types@npm:7.25.2" + dependencies: + "@babel/helper-string-parser": ^7.24.8 + "@babel/helper-validator-identifier": ^7.24.7 + to-fast-properties: ^2.0.0 + checksum: f73f66ba903c6f7e38f519a33d53a67d49c07e208e59ea65250362691dc546c6da7ab90ec66ee79651ef697329872f6f97eb19a6dfcacc026fd05e76a563c5d2 + languageName: node + linkType: hard + +"@bcoe/v8-coverage@npm:^0.2.3": + version: 0.2.3 + resolution: "@bcoe/v8-coverage@npm:0.2.3" + checksum: 850f9305536d0f2bd13e9e0881cb5f02e4f93fad1189f7b2d4bebf694e3206924eadee1068130d43c11b750efcc9405f88a8e42ef098b6d75239c0f047de1a27 + languageName: node + linkType: hard + +"@discoveryjs/json-ext@npm:^0.5.0": + version: 0.5.7 + resolution: "@discoveryjs/json-ext@npm:0.5.7" + checksum: 2176d301cc258ea5c2324402997cf8134ebb212469c0d397591636cea8d3c02f2b3cf9fd58dcb748c7a0dade77ebdc1b10284fa63e608c033a1db52fddc69918 + languageName: node + linkType: hard + +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": + version: 4.4.0 + resolution: "@eslint-community/eslint-utils@npm:4.4.0" + dependencies: + eslint-visitor-keys: ^3.3.0 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: cdfe3ae42b4f572cbfb46d20edafe6f36fc5fb52bf2d90875c58aefe226892b9677fef60820e2832caf864a326fe4fc225714c46e8389ccca04d5f9288aabd22 + languageName: node + linkType: hard + +"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": + version: 4.11.0 + resolution: "@eslint-community/regexpp@npm:4.11.0" + checksum: 97d2fe46690b69417a551bd19a3dc53b6d9590d2295c43cc4c4e44e64131af541e2f4a44d5c12e87de990403654d3dae9d33600081f3a2f0386b368abc9111ec + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" + dependencies: + ajv: ^6.12.4 + debug: ^4.3.2 + espree: ^9.6.0 + globals: ^13.19.0 + ignore: ^5.2.0 + import-fresh: ^3.2.1 + js-yaml: ^4.1.0 + minimatch: ^3.1.2 + strip-json-comments: ^3.1.1 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 + languageName: node + linkType: hard + +"@eslint/js@npm:8.57.0": + version: 8.57.0 + resolution: "@eslint/js@npm:8.57.0" + checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb + languageName: node + linkType: hard + +"@humanwhocodes/config-array@npm:^0.11.14": + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" + dependencies: + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 + minimatch: ^3.0.5 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 + languageName: node + linkType: hard + +"@humanwhocodes/module-importer@npm:^1.0.1": + version: 1.0.1 + resolution: "@humanwhocodes/module-importer@npm:1.0.1" + checksum: 0fd22007db8034a2cdf2c764b140d37d9020bbfce8a49d3ec5c05290e77d4b0263b1b972b752df8c89e5eaa94073408f2b7d977aed131faf6cf396ebb5d7fb61 + languageName: node + linkType: hard + +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: d3b78f6c5831888c6ecc899df0d03bcc25d46f3ad26a11d7ea52944dc36a35ef543fad965322174238d677a43d5c694434f6607532cff7077062513ad7022631 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: ^5.1.2 + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: ^7.0.1 + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: ^8.1.0 + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb + languageName: node + linkType: hard + +"@istanbuljs/load-nyc-config@npm:^1.0.0": + version: 1.1.0 + resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" + dependencies: + camelcase: ^5.3.1 + find-up: ^4.1.0 + get-package-type: ^0.1.0 + js-yaml: ^3.13.1 + resolve-from: ^5.0.0 + checksum: d578da5e2e804d5c93228450a1380e1a3c691de4953acc162f387b717258512a3e07b83510a936d9fab03eac90817473917e24f5d16297af3867f59328d58568 + languageName: node + linkType: hard + +"@istanbuljs/schema@npm:^0.1.2, @istanbuljs/schema@npm:^0.1.3": + version: 0.1.3 + resolution: "@istanbuljs/schema@npm:0.1.3" + checksum: 5282759d961d61350f33d9118d16bcaed914ebf8061a52f4fa474b2cb08720c9c81d165e13b82f2e5a8a212cc5af482f0c6fc1ac27b9e067e5394c9a6ed186c9 + languageName: node + linkType: hard + +"@jest/console@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/console@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + slash: ^3.0.0 + checksum: 0e3624e32c5a8e7361e889db70b170876401b7d70f509a2538c31d5cd50deb0c1ae4b92dc63fe18a0902e0a48c590c21d53787a0df41a52b34fa7cab96c384d6 + languageName: node + linkType: hard + +"@jest/core@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/core@npm:29.7.0" + dependencies: + "@jest/console": ^29.7.0 + "@jest/reporters": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@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.7.0 + jest-config: ^29.7.0 + jest-haste-map: ^29.7.0 + jest-message-util: ^29.7.0 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.7.0 + jest-resolve-dependencies: ^29.7.0 + jest-runner: ^29.7.0 + jest-runtime: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + jest-watcher: ^29.7.0 + micromatch: ^4.0.4 + pretty-format: ^29.7.0 + 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: af759c9781cfc914553320446ce4e47775ae42779e73621c438feb1e4231a5d4862f84b1d8565926f2d1aab29b3ec3dcfdc84db28608bdf5f29867124ebcfc0d + languageName: node + linkType: hard + +"@jest/environment@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/environment@npm:29.7.0" + dependencies: + "@jest/fake-timers": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-mock: ^29.7.0 + checksum: 6fb398143b2543d4b9b8d1c6dbce83fa5247f84f550330604be744e24c2bd2178bb893657d62d1b97cf2f24baf85c450223f8237cccb71192c36a38ea2272934 + languageName: node + linkType: hard + +"@jest/expect-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect-utils@npm:29.7.0" + dependencies: + jest-get-type: ^29.6.3 + checksum: 75eb177f3d00b6331bcaa057e07c0ccb0733a1d0a1943e1d8db346779039cb7f103789f16e502f888a3096fb58c2300c38d1f3748b36a7fa762eb6f6d1b160ed + languageName: node + linkType: hard + +"@jest/expect@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect@npm:29.7.0" + dependencies: + expect: ^29.7.0 + jest-snapshot: ^29.7.0 + checksum: a01cb85fd9401bab3370618f4b9013b90c93536562222d920e702a0b575d239d74cecfe98010aaec7ad464f67cf534a353d92d181646a4b792acaa7e912ae55e + languageName: node + linkType: hard + +"@jest/fake-timers@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/fake-timers@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@sinonjs/fake-timers": ^10.0.2 + "@types/node": "*" + jest-message-util: ^29.7.0 + jest-mock: ^29.7.0 + jest-util: ^29.7.0 + checksum: caf2bbd11f71c9241b458d1b5a66cbe95debc5a15d96442444b5d5c7ba774f523c76627c6931cca5e10e76f0d08761f6f1f01a608898f4751a0eee54fc3d8d00 + languageName: node + linkType: hard + +"@jest/globals@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/globals@npm:29.7.0" + dependencies: + "@jest/environment": ^29.7.0 + "@jest/expect": ^29.7.0 + "@jest/types": ^29.6.3 + jest-mock: ^29.7.0 + checksum: 97dbb9459135693ad3a422e65ca1c250f03d82b2a77f6207e7fa0edd2c9d2015fbe4346f3dc9ebff1678b9d8da74754d4d440b7837497f8927059c0642a22123 + languageName: node + linkType: hard + +"@jest/reporters@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/reporters@npm:29.7.0" + dependencies: + "@bcoe/v8-coverage": ^0.2.3 + "@jest/console": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@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: ^6.0.0 + istanbul-lib-report: ^3.0.0 + istanbul-lib-source-maps: ^4.0.0 + istanbul-reports: ^3.1.3 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + jest-worker: ^29.7.0 + 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: 7eadabd62cc344f629024b8a268ecc8367dba756152b761bdcb7b7e570a3864fc51b2a9810cd310d85e0a0173ef002ba4528d5ea0329fbf66ee2a3ada9c40455 + languageName: node + linkType: hard + +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": ^0.27.8 + checksum: 910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 + languageName: node + linkType: hard + +"@jest/source-map@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/source-map@npm:29.6.3" + dependencies: + "@jridgewell/trace-mapping": ^0.3.18 + callsites: ^3.0.0 + graceful-fs: ^4.2.9 + checksum: bcc5a8697d471396c0003b0bfa09722c3cd879ad697eb9c431e6164e2ea7008238a01a07193dfe3cbb48b1d258eb7251f6efcea36f64e1ebc464ea3c03ae2deb + languageName: node + linkType: hard + +"@jest/test-result@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-result@npm:29.7.0" + dependencies: + "@jest/console": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/istanbul-lib-coverage": ^2.0.0 + collect-v8-coverage: ^1.0.0 + checksum: 67b6317d526e335212e5da0e768e3b8ab8a53df110361b80761353ad23b6aea4432b7c5665bdeb87658ea373b90fb1afe02ed3611ef6c858c7fba377505057fa + languageName: node + linkType: hard + +"@jest/test-sequencer@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-sequencer@npm:29.7.0" + dependencies: + "@jest/test-result": ^29.7.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.7.0 + slash: ^3.0.0 + checksum: 73f43599017946be85c0b6357993b038f875b796e2f0950487a82f4ebcb115fa12131932dd9904026b4ad8be131fe6e28bd8d0aa93b1563705185f9804bff8bd + languageName: node + linkType: hard + +"@jest/transform@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/transform@npm:29.7.0" + dependencies: + "@babel/core": ^7.11.6 + "@jest/types": ^29.6.3 + "@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.7.0 + jest-regex-util: ^29.6.3 + jest-util: ^29.7.0 + micromatch: ^4.0.4 + pirates: ^4.0.4 + slash: ^3.0.0 + write-file-atomic: ^4.0.2 + checksum: 0f8ac9f413903b3cb6d240102db848f2a354f63971ab885833799a9964999dd51c388162106a807f810071f864302cdd8e3f0c241c29ce02d85a36f18f3f40ab + languageName: node + linkType: hard + +"@jest/types@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/types@npm:29.6.3" + dependencies: + "@jest/schemas": ^29.6.3 + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^17.0.8 + chalk: ^4.0.0 + checksum: a0bcf15dbb0eca6bdd8ce61a3fb055349d40268622a7670a3b2eb3c3dbafe9eb26af59938366d520b86907b9505b0f9b29b85cec11579a9e580694b87cd90fcc + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" + dependencies: + "@jridgewell/set-array": ^1.2.1 + "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/trace-mapping": ^0.3.24 + checksum: ff7a1764ebd76a5e129c8890aa3e2f46045109dabde62b0b6c6a250152227647178ff2069ea234753a690d8f3c4ac8b5e7b267bbee272bffb7f3b0a370ab6e52 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 83b85f72c59d1c080b4cbec0fef84528963a1b5db34e4370fa4bd1e3ff64a0d80e0cee7369d11d73c704e0286fb2865b530acac7a871088fbe92b5edf1000870 + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 + languageName: node + linkType: hard + +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.6 + resolution: "@jridgewell/source-map@npm:0.3.6" + dependencies: + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + checksum: c9dc7d899397df95e3c9ec287b93c0b56f8e4453cd20743e2b9c8e779b1949bc3cccf6c01bb302779e46560eb45f62ea38d19fedd25370d814734268450a9f30 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 05df4f2538b3b0f998ea4c1cd34574d0feba216fa5d4ccaef0187d12abf82eafe6021cec8b49f9bb4d90f2ba4582ccc581e72986a5fcf4176ae0cfeb04cf52ec + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" + dependencies: + "@jridgewell/resolve-uri": ^3.1.0 + "@jridgewell/sourcemap-codec": ^1.4.14 + checksum: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 + languageName: node + linkType: hard + +"@jupyter-widgets/base-manager@npm:^1.0.7": + version: 1.0.9 + resolution: "@jupyter-widgets/base-manager@npm:1.0.9" + dependencies: + "@jupyter-widgets/base": ^6.0.8 + "@jupyterlab/services": ^6.0.0 || ^7.0.0 + "@lumino/coreutils": ^1.11.1 || ^2 + base64-js: ^1.2.1 + sanitize-html: ^2.3 + checksum: 6ec1d7dd16020dfd2798d9e53dca00e60951c72ec3545838a5a331de6226e7a2a260dae14ae487485024cdfdef59db9959868d29e49a742f9b3ff58e79d98b5c + languageName: node + linkType: hard + +"@jupyter-widgets/base@npm:^1.1.10 || ^2 || ^3 || ^4 || ^5 || ^6, @jupyter-widgets/base@npm:^6.0.8": + version: 6.0.8 + resolution: "@jupyter-widgets/base@npm:6.0.8" + dependencies: + "@jupyterlab/services": ^6.0.0 || ^7.0.0 + "@lumino/coreutils": ^1.11.1 || ^2.1 + "@lumino/messaging": ^1.10.1 || ^2.1 + "@lumino/widgets": ^1.30.0 || ^2.1 + "@types/backbone": 1.4.14 + "@types/lodash": ^4.14.134 + backbone: 1.4.0 + jquery: ^3.1.1 + lodash: ^4.17.4 + checksum: fcc7affd49a0b227725082813eac6d8e6ca29f6a0446bd7914394c041382d881263d69dacf3a9463cdb0e207458401c65aaf1f50c708ce7378c701b4a18d10b8 + languageName: node + linkType: hard + +"@jupyter/ydoc@npm:^2.0.1": + version: 2.1.1 + resolution: "@jupyter/ydoc@npm:2.1.1" + dependencies: + "@jupyterlab/nbformat": ^3.0.0 || ^4.0.0-alpha.21 || ^4.0.0 + "@lumino/coreutils": ^1.11.0 || ^2.0.0 + "@lumino/disposable": ^1.10.0 || ^2.0.0 + "@lumino/signaling": ^1.10.0 || ^2.0.0 + y-protocols: ^1.0.5 + yjs: ^13.5.40 + checksum: f10268d4d990f454279e3908a172755ed5885fa81bb70c31bdf66923598b283d26491741bece137d1c348619861e9b7f8354296773fe5352b1915e69101a9fb0 + languageName: node + linkType: hard + +"@jupyterlab/builder@npm:^4.0.11": + version: 4.2.4 + resolution: "@jupyterlab/builder@npm:4.2.4" + dependencies: + "@lumino/algorithm": ^2.0.1 + "@lumino/application": ^2.3.1 + "@lumino/commands": ^2.3.0 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/domutils": ^2.0.1 + "@lumino/dragdrop": ^2.1.4 + "@lumino/messaging": ^2.0.1 + "@lumino/properties": ^2.0.1 + "@lumino/signaling": ^2.1.2 + "@lumino/virtualdom": ^2.0.1 + "@lumino/widgets": ^2.3.2 + ajv: ^8.12.0 + commander: ^9.4.1 + css-loader: ^6.7.1 + duplicate-package-checker-webpack-plugin: ^3.0.0 + fs-extra: ^10.1.0 + glob: ~7.1.6 + license-webpack-plugin: ^2.3.14 + mini-css-extract-plugin: ^2.7.0 + mini-svg-data-uri: ^1.4.4 + path-browserify: ^1.0.0 + process: ^0.11.10 + source-map-loader: ~1.0.2 + style-loader: ~3.3.1 + supports-color: ^7.2.0 + terser-webpack-plugin: ^5.3.7 + webpack: ^5.76.1 + webpack-cli: ^5.0.1 + webpack-merge: ^5.8.0 + worker-loader: ^3.0.2 + bin: + build-labextension: lib/build-labextension.js + checksum: 2488e2013afc5499c409a14c34e9fe92ec30cd99622cdb2f00f42a4cced66afac0a1cdf081cf035f2329b50303f91a265146c1e895e832ddd3651c29e2523844 + languageName: node + linkType: hard + +"@jupyterlab/coreutils@npm:^6.2.4": + version: 6.2.4 + resolution: "@jupyterlab/coreutils@npm:6.2.4" + 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: 4ce2c660dea8a174e805b00cdecfa0b00fd7500cd07f5fbb62c69b48722728162baf90dc9c86c8e72044052d9c0217a53d12a7a5ebdbe9714865d18b8e66593f + languageName: node + linkType: hard + +"@jupyterlab/nbformat@npm:^3.0.0 || ^4.0.0-alpha.21 || ^4.0.0, @jupyterlab/nbformat@npm:^4.2.4": + version: 4.2.4 + resolution: "@jupyterlab/nbformat@npm:4.2.4" + dependencies: + "@lumino/coreutils": ^2.1.2 + checksum: 61ac75dbaa32ef196eb9e177529ba259c6b0648601646b52ec8a1b25dbca4fce8c6d78090b47fd0674bf993f883fa62223dc52e50a59f1b2c843a9d5c8d02ef4 + languageName: node + linkType: hard + +"@jupyterlab/services@npm:^6.0.0 || ^7.0.0": + version: 7.2.4 + resolution: "@jupyterlab/services@npm:7.2.4" + dependencies: + "@jupyter/ydoc": ^2.0.1 + "@jupyterlab/coreutils": ^6.2.4 + "@jupyterlab/nbformat": ^4.2.4 + "@jupyterlab/settingregistry": ^4.2.4 + "@jupyterlab/statedb": ^4.2.4 + "@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: 7262d6ac6bc8a41e03ec45c7d4dd8e8eb2547dff315a9be9c81cff0e5f4f9e3fb12fd3d008cb4132efced9800023470fb5fef5f446307903b8cdee8c1ca96d34 + languageName: node + linkType: hard + +"@jupyterlab/settingregistry@npm:^4.2.4": + version: 4.2.4 + resolution: "@jupyterlab/settingregistry@npm:4.2.4" + dependencies: + "@jupyterlab/nbformat": ^4.2.4 + "@jupyterlab/statedb": ^4.2.4 + "@lumino/commands": ^2.3.0 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/signaling": ^2.1.2 + "@rjsf/utils": ^5.13.4 + ajv: ^8.12.0 + json5: ^2.2.3 + peerDependencies: + react: ">=16" + checksum: c4d1bfef80811697c0979f76b3a0c1f6597d6f07fd227004fd7f1237abc20ac6dda4cfffcb487166625e3c72ffa5c9e25e0a865c86217e9280207362b8864247 + languageName: node + linkType: hard + +"@jupyterlab/statedb@npm:^4.2.4": + version: 4.2.4 + resolution: "@jupyterlab/statedb@npm:4.2.4" + dependencies: + "@lumino/commands": ^2.3.0 + "@lumino/coreutils": ^2.1.2 + "@lumino/disposable": ^2.1.2 + "@lumino/properties": ^2.0.1 + "@lumino/signaling": ^2.1.2 + checksum: 63d2eeab1e4f45593b417f7aa4bbff5a78703858d2c49497632f37d262acca37e4600766dcd3d744de4048ba8e6726dcbe44718453a1d43eb088380f48e70609 + languageName: node + linkType: hard + +"@lumino/algorithm@npm:^1.9.2": + version: 1.9.2 + resolution: "@lumino/algorithm@npm:1.9.2" + checksum: a89e7c63504236119634858e271db1cc649684d30ced5a6ebe2788af7c0837f1e05a6fd3047d8525eb756c42ce137f76b3688f75fd3ef915b71cd4f213dfbb96 + languageName: node + linkType: hard + +"@lumino/algorithm@npm:^2.0.1, @lumino/algorithm@npm:^2.0.2": + version: 2.0.2 + resolution: "@lumino/algorithm@npm:2.0.2" + checksum: 34b25684b845f1bdbf78ca45ebd99a97b67b2992440c9643aafe5fc5a99fae1ddafa9e5890b246b233dc3a12d9f66aa84afe4a2aac44cf31071348ed217740db + languageName: node + linkType: hard + +"@lumino/application@npm:^2.3.0, @lumino/application@npm:^2.3.1": + version: 2.4.1 + resolution: "@lumino/application@npm:2.4.1" + dependencies: + "@lumino/commands": ^2.3.1 + "@lumino/coreutils": ^2.2.0 + "@lumino/widgets": ^2.5.0 + checksum: b7166d1bf4f0e3cc945d984b4057a4cd106d38df6cb4c6f1259c75484e2b976018aca55f169fa4af7dd174ce7117be1920966bef0fb7cba756f503f0df1d211e + languageName: node + linkType: hard + +"@lumino/collections@npm:^1.9.3": + version: 1.9.3 + resolution: "@lumino/collections@npm:1.9.3" + dependencies: + "@lumino/algorithm": ^1.9.2 + checksum: 1c87a12743eddd6f6b593e47945a5645e2f99ad61c5192499b0745e48ee9aff263c7145541e77dfeea4c9f50bdd017fddfa47bfc60e718de4f28533ce45bf8c3 + languageName: node + linkType: hard + +"@lumino/collections@npm:^2.0.2": + version: 2.0.2 + resolution: "@lumino/collections@npm:2.0.2" + dependencies: + "@lumino/algorithm": ^2.0.2 + checksum: e8bb2068a3741940e0dd396fa729c3c9d12458b41b7c2a9d171c5c034e69fb5834116a824094a8aa4182397e13abace06025ed5032a755ea85b976eae74ee9a9 + languageName: node + linkType: hard + +"@lumino/commands@npm:^2.3.0, @lumino/commands@npm:^2.3.1": + version: 2.3.1 + resolution: "@lumino/commands@npm:2.3.1" + dependencies: + "@lumino/algorithm": ^2.0.2 + "@lumino/coreutils": ^2.2.0 + "@lumino/disposable": ^2.1.3 + "@lumino/domutils": ^2.0.2 + "@lumino/keyboard": ^2.0.2 + "@lumino/signaling": ^2.1.3 + "@lumino/virtualdom": ^2.0.2 + checksum: 83bc6d66de37e58582b00f70ce66e797c9fcf84e36041c6881631ed0d281305e2a49927f5b2fe6c5c965733f3cd6fb4a233c7b7967fc050497024a941659bd65 + languageName: node + linkType: hard + +"@lumino/coreutils@npm:^1.11.0 || ^2.0.0, @lumino/coreutils@npm:^1.11.1 || ^2, @lumino/coreutils@npm:^1.11.1 || ^2.1, @lumino/coreutils@npm:^2.1.2, @lumino/coreutils@npm:^2.2.0": + version: 2.2.0 + resolution: "@lumino/coreutils@npm:2.2.0" + dependencies: + "@lumino/algorithm": ^2.0.2 + checksum: 345fcd5d7493d745831dd944edfbd8eda06cc59a117e71023fc97ce53badd697be2bd51671f071f5ff0064f75f104575d9695f116a07517bafbedd38e5c7a785 + languageName: node + linkType: hard + +"@lumino/disposable@npm:^1.10.0 || ^2.0.0, @lumino/disposable@npm:^2.1.2, @lumino/disposable@npm:^2.1.3": + version: 2.1.3 + resolution: "@lumino/disposable@npm:2.1.3" + dependencies: + "@lumino/signaling": ^2.1.3 + checksum: b9a346fa2752b3cd1b053cb637ee173501d33082a73423429070e8acc508b034ea0babdae0549b923cbdd287ee1fc7f6159f0539c9fff7574393a214eef07c57 + languageName: node + linkType: hard + +"@lumino/domutils@npm:^2.0.1, @lumino/domutils@npm:^2.0.2": + version: 2.0.2 + resolution: "@lumino/domutils@npm:2.0.2" + checksum: 037b8d0b62af43887fd7edd506fa551e2af104a4b46d62e6fef256e16754dba40d351513beb5083834d468b2c7806aae0fe205fd6aac8ef24759451ee998bbd9 + languageName: node + linkType: hard + +"@lumino/dragdrop@npm:^2.1.4, @lumino/dragdrop@npm:^2.1.5": + version: 2.1.5 + resolution: "@lumino/dragdrop@npm:2.1.5" + dependencies: + "@lumino/coreutils": ^2.2.0 + "@lumino/disposable": ^2.1.3 + checksum: 48e34bea73186dcde4565fa68cd25067b7f5fe910813d28da9ab3c5392bfaa0b26aab1290635dc953d85bbb139da7ac1ffc040a5d5777d58fd087975dd4b5ef7 + languageName: node + linkType: hard + +"@lumino/keyboard@npm:^2.0.2": + version: 2.0.2 + resolution: "@lumino/keyboard@npm:2.0.2" + checksum: 198e8c17825c9a831fa0770f58a71574b936acb0f0bbbe7f8feb73d89686dda7ff41fcb02d12b401f5d462b45fe0bba24f7f38befb7cefe0826576559f0bee6d + languageName: node + linkType: hard + +"@lumino/messaging@npm:^1.10.1 || ^2.1": + version: 1.10.3 + resolution: "@lumino/messaging@npm:1.10.3" + dependencies: + "@lumino/algorithm": ^1.9.2 + "@lumino/collections": ^1.9.3 + checksum: 1131e80379fa9b8a9b5d3418c90e25d4be48e2c92ec711518190772f9e8845a695bef45daddd06a129168cf6f158c8ad80ae86cb245f566e9195bbd9a0843b7a + languageName: node + linkType: hard + +"@lumino/messaging@npm:^2.0.1, @lumino/messaging@npm:^2.0.2": + version: 2.0.2 + resolution: "@lumino/messaging@npm:2.0.2" + dependencies: + "@lumino/algorithm": ^2.0.2 + "@lumino/collections": ^2.0.2 + checksum: 66abd8c473026123589dc22f2ce8f85da10e0b1a05c05ed9b2011035721da5f751cc7ef63b628877f446a78a4287e26ad1450efbeaf0c2e03b1d08be9abaca4d + languageName: node + linkType: hard + +"@lumino/polling@npm:^2.1.2": + version: 2.1.3 + resolution: "@lumino/polling@npm:2.1.3" + dependencies: + "@lumino/coreutils": ^2.2.0 + "@lumino/disposable": ^2.1.3 + "@lumino/signaling": ^2.1.3 + checksum: 2c94dbc2339dd06b3b89a3a690d23576ce095f92bf1f614557dcaeb1c1a8a707b2a18d78c03e5fd7376a43e3f393cc4fec42a65580ae4b67c6630ea86cecbac6 + languageName: node + linkType: hard + +"@lumino/properties@npm:^2.0.1, @lumino/properties@npm:^2.0.2": + version: 2.0.2 + resolution: "@lumino/properties@npm:2.0.2" + checksum: cbe802bd49ced7e13e50b1d89b82e0f03fb44a590c704e6b9343226498b21d8abfe119b024209e79876b4fc0938dbf85e964c6c4cd5bbdd4d7ba41ce0fb69f3f + languageName: node + linkType: hard + +"@lumino/signaling@npm:^1.10.0 || ^2.0.0, @lumino/signaling@npm:^2.1.2, @lumino/signaling@npm:^2.1.3": + version: 2.1.3 + resolution: "@lumino/signaling@npm:2.1.3" + dependencies: + "@lumino/algorithm": ^2.0.2 + "@lumino/coreutils": ^2.2.0 + checksum: ce59383bd75fe30df5800e0442dbc4193cc6778e2530b9be0f484d159f1d8668be5c6ee92cee9df36d5a0c3dbd9126d0479a82581dee1df889d5c9f922d3328d + languageName: node + linkType: hard + +"@lumino/virtualdom@npm:^2.0.1, @lumino/virtualdom@npm:^2.0.2": + version: 2.0.2 + resolution: "@lumino/virtualdom@npm:2.0.2" + dependencies: + "@lumino/algorithm": ^2.0.2 + checksum: 0e1220d5b3b2441e7668f3542a6341e015bdbea0c8bd6d4be962009386c034336540732596d5dedcd54ca57fbde61c2942549129a3e1b0fccb1aa143685fcd15 + languageName: node + linkType: hard + +"@lumino/widgets@npm:^1.30.0 || ^2.1, @lumino/widgets@npm:^2.3.1, @lumino/widgets@npm:^2.3.2, @lumino/widgets@npm:^2.5.0": + version: 2.5.0 + resolution: "@lumino/widgets@npm:2.5.0" + dependencies: + "@lumino/algorithm": ^2.0.2 + "@lumino/commands": ^2.3.1 + "@lumino/coreutils": ^2.2.0 + "@lumino/disposable": ^2.1.3 + "@lumino/domutils": ^2.0.2 + "@lumino/dragdrop": ^2.1.5 + "@lumino/keyboard": ^2.0.2 + "@lumino/messaging": ^2.0.2 + "@lumino/properties": ^2.0.2 + "@lumino/signaling": ^2.1.3 + "@lumino/virtualdom": ^2.0.2 + checksum: c5055e42b0b7d5d9a0c29d14c7053478cbdef057525e262ccd59c987971364d5462ed1a59d5008b889cf5ecc6810e90c681364239500b9c8ee0ae4624d60df84 + languageName: node + linkType: hard + +"@nodelib/fs.scandir@npm:2.1.5": + version: 2.1.5 + resolution: "@nodelib/fs.scandir@npm:2.1.5" + dependencies: + "@nodelib/fs.stat": 2.0.5 + run-parallel: ^1.1.9 + checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59 + languageName: node + linkType: hard + +"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": + version: 2.0.5 + resolution: "@nodelib/fs.stat@npm:2.0.5" + checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 + languageName: node + linkType: hard + +"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": + version: 1.2.8 + resolution: "@nodelib/fs.walk@npm:1.2.8" + dependencies: + "@nodelib/fs.scandir": 2.1.5 + fastq: ^1.6.0 + checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" + dependencies: + agent-base: ^7.1.0 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.1 + lru-cache: ^10.0.1 + socks-proxy-agent: ^8.0.3 + checksum: 67de7b88cc627a79743c88bab35e023e23daf13831a8aa4e15f998b92f5507b644d8ffc3788afc8e64423c612e0785a6a92b74782ce368f49a6746084b50d874 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" + dependencies: + semver: ^7.3.5 + checksum: d960cab4b93adcb31ce223bfb75c5714edbd55747342efb67dcc2f25e023d930a7af6ece3e75f2f459b6f38fc14d031c766f116cd124fdc937fd33112579e820 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f + languageName: node + linkType: hard + +"@pkgr/core@npm:^0.1.0": + version: 0.1.1 + resolution: "@pkgr/core@npm:0.1.1" + checksum: 6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba + languageName: node + linkType: hard + +"@rjsf/utils@npm:^5.13.4": + version: 5.20.0 + resolution: "@rjsf/utils@npm:5.20.0" + dependencies: + json-schema-merge-allof: ^0.8.1 + jsonpointer: ^5.0.1 + lodash: ^4.17.21 + lodash-es: ^4.17.21 + react-is: ^18.2.0 + peerDependencies: + react: ^16.14.0 || >=17 + checksum: 8baeb254e548abeeefecbe6f6cc2fc3ac02503abd22396ec62959172e4c21c5e688e148961504d1c259074b47635aff758de26a9ff8fe82d55e9d05e4570619d + languageName: node + linkType: hard + +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1 + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^3.0.0": + version: 3.0.1 + resolution: "@sinonjs/commons@npm:3.0.1" + dependencies: + type-detect: 4.0.8 + checksum: a7c3e7cc612352f4004873747d9d8b2d4d90b13a6d483f685598c945a70e734e255f1ca5dc49702515533c403b32725defff148177453b3f3915bcb60e9d4601 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^10.0.2": + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" + dependencies: + "@sinonjs/commons": ^3.0.0 + checksum: 614d30cb4d5201550c940945d44c9e0b6d64a888ff2cd5b357f95ad6721070d6b8839cd10e15b76bf5e14af0bcc1d8f9ec00d49a46318f1f669a4bec1d7f3148 + languageName: node + linkType: hard + +"@types/babel__core@npm:^7.1.14": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" + dependencies: + "@babel/parser": ^7.20.7 + "@babel/types": ^7.20.7 + "@types/babel__generator": "*" + "@types/babel__template": "*" + "@types/babel__traverse": "*" + checksum: a3226f7930b635ee7a5e72c8d51a357e799d19cbf9d445710fa39ab13804f79ab1a54b72ea7d8e504659c7dfc50675db974b526142c754398d7413aa4bc30845 + languageName: node + linkType: hard + +"@types/babel__generator@npm:*": + version: 7.6.8 + resolution: "@types/babel__generator@npm:7.6.8" + dependencies: + "@babel/types": ^7.0.0 + checksum: 5b332ea336a2efffbdeedb92b6781949b73498606ddd4205462f7d96dafd45ff3618770b41de04c4881e333dd84388bfb8afbdf6f2764cbd98be550d85c6bb48 + languageName: node + linkType: hard + +"@types/babel__template@npm:*": + version: 7.4.4 + resolution: "@types/babel__template@npm:7.4.4" + dependencies: + "@babel/parser": ^7.1.0 + "@babel/types": ^7.0.0 + checksum: d7a02d2a9b67e822694d8e6a7ddb8f2b71a1d6962dfd266554d2513eefbb205b33ca71a0d163b1caea3981ccf849211f9964d8bd0727124d18ace45aa6c9ae29 + languageName: node + linkType: hard + +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": + version: 7.20.6 + resolution: "@types/babel__traverse@npm:7.20.6" + dependencies: + "@babel/types": ^7.20.7 + checksum: 2bdc65eb62232c2d5c1086adeb0c31e7980e6fd7e50a3483b4a724a1a1029c84d9cb59749cf8de612f9afa2bc14c85b8f50e64e21f8a4398fa77eb9059a4283c + languageName: node + linkType: hard + +"@types/backbone@npm:1.4.14": + version: 1.4.14 + resolution: "@types/backbone@npm:1.4.14" + dependencies: + "@types/jquery": "*" + "@types/underscore": "*" + checksum: 4f44bfb71d75332b5de610be7687f4ae523ad4ef02da844a828403b534b6a94a6288b32cab64371d0ad526e35cfed511652ac53af22d0b9caaac3f4cfb4375dd + languageName: node + linkType: hard + +"@types/eslint-scope@npm:^3.7.3": + version: 3.7.7 + resolution: "@types/eslint-scope@npm:3.7.7" + dependencies: + "@types/eslint": "*" + "@types/estree": "*" + checksum: e2889a124aaab0b89af1bab5959847c5bec09809209255de0e63b9f54c629a94781daa04adb66bffcdd742f5e25a17614fb933965093c0eea64aacda4309380e + languageName: node + linkType: hard + +"@types/eslint@npm:*": + version: 9.6.0 + resolution: "@types/eslint@npm:9.6.0" + dependencies: + "@types/estree": "*" + "@types/json-schema": "*" + checksum: 7be4b1d24f3df30b28e9cbaac6a5fa14ec1ceca7c173d9605c0ec6e0d1dcdba0452d326dd695dd980f5c14b42aa09fe41675c4f09ffc82db4f466588d3f837cb + languageName: node + linkType: hard + +"@types/estree@npm:*, @types/estree@npm:^1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a + languageName: node + linkType: hard + +"@types/graceful-fs@npm:^4.1.3": + version: 4.1.9 + resolution: "@types/graceful-fs@npm:4.1.9" + dependencies: + "@types/node": "*" + checksum: 79d746a8f053954bba36bd3d94a90c78de995d126289d656fb3271dd9f1229d33f678da04d10bce6be440494a5a73438e2e363e92802d16b8315b051036c5256 + languageName: node + linkType: hard + +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": + version: 2.0.6 + resolution: "@types/istanbul-lib-coverage@npm:2.0.6" + checksum: 3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 + languageName: node + linkType: hard + +"@types/istanbul-lib-report@npm:*": + version: 3.0.3 + resolution: "@types/istanbul-lib-report@npm:3.0.3" + dependencies: + "@types/istanbul-lib-coverage": "*" + checksum: b91e9b60f865ff08cb35667a427b70f6c2c63e88105eadd29a112582942af47ed99c60610180aa8dcc22382fa405033f141c119c69b95db78c4c709fbadfeeb4 + languageName: node + linkType: hard + +"@types/istanbul-reports@npm:^3.0.0": + version: 3.0.4 + resolution: "@types/istanbul-reports@npm:3.0.4" + dependencies: + "@types/istanbul-lib-report": "*" + checksum: 93eb18835770b3431f68ae9ac1ca91741ab85f7606f310a34b3586b5a34450ec038c3eed7ab19266635499594de52ff73723a54a72a75b9f7d6a956f01edee95 + languageName: node + linkType: hard + +"@types/jest@npm:^29.5.11": + version: 29.5.12 + resolution: "@types/jest@npm:29.5.12" + dependencies: + expect: ^29.0.0 + pretty-format: ^29.0.0 + checksum: 19b1efdeed9d9a60a81edc8226cdeae5af7479e493eaed273e01243891c9651f7b8b4c08fc633a7d0d1d379b091c4179bbaa0807af62542325fd72f2dd17ce1c + languageName: node + linkType: hard + +"@types/jquery@npm:*": + version: 3.5.30 + resolution: "@types/jquery@npm:3.5.30" + dependencies: + "@types/sizzle": "*" + checksum: 4594d10fa9b347062883d254a23c9259ae814ef5989ce1985f093dcc7ad4475e324ac3343aef10599c478ea4951726f0e7f79d8ed471ab04de394b7e724d6d13 + languageName: node + linkType: hard + +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 + languageName: node + linkType: hard + +"@types/lodash@npm:^4.14.134": + version: 4.17.7 + resolution: "@types/lodash@npm:4.17.7" + checksum: 09e58a119cd8a70acfb33f8623dc2fc54f74cdce3b3429b879fc2daac4807fe376190a04b9e024dd300f9a3ee1876d6623979cefe619f70654ca0fe0c47679a7 + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 22.4.0 + resolution: "@types/node@npm:22.4.0" + dependencies: + undici-types: ~6.19.2 + checksum: 680303e9b2801f3e19453957df93f59e7ad95e2277a363ba3719e9a3e0c8949ed9bed2265a2a3444254c5e550170177c088bc2b2303eb79740fb8ee96b097ad3 + languageName: node + linkType: hard + +"@types/semver@npm:^7.5.0": + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 + languageName: node + linkType: hard + +"@types/sizzle@npm:*": + version: 2.3.8 + resolution: "@types/sizzle@npm:2.3.8" + checksum: 2ac62443dc917f5f903cbd9afc51c7d6cc1c6569b4e1a15faf04aea5b13b486e7f208650014c3dc4fed34653eded3e00fe5abffe0e6300cbf0e8a01beebf11a6 + languageName: node + linkType: hard + +"@types/source-list-map@npm:*": + version: 0.1.6 + resolution: "@types/source-list-map@npm:0.1.6" + checksum: 9cd294c121f1562062de5d241fe4d10780b1131b01c57434845fe50968e9dcf67ede444591c2b1ad6d3f9b6bc646ac02cc8f51a3577c795f9c64cf4573dcc6b1 + languageName: node + linkType: hard + +"@types/stack-utils@npm:^2.0.0": + version: 2.0.3 + resolution: "@types/stack-utils@npm:2.0.3" + checksum: 72576cc1522090fe497337c2b99d9838e320659ac57fa5560fcbdcbafcf5d0216c6b3a0a8a4ee4fdb3b1f5e3420aa4f6223ab57b82fef3578bec3206425c6cf5 + languageName: node + linkType: hard + +"@types/underscore@npm:*": + version: 1.11.15 + resolution: "@types/underscore@npm:1.11.15" + checksum: 25fdf6da96e0d11ca39a4740aab6fa3bd717e57301be4cb9e7893dc0ad6ce330992d0c8e0b02cac5c5ea86df6f8949c5a8f1fb95f3666b85418d399d3b1112e9 + languageName: node + linkType: hard + +"@types/webpack-env@npm:^1.18.4": + version: 1.18.5 + resolution: "@types/webpack-env@npm:1.18.5" + checksum: 4ca8eb4c44e1e1807c3e245442fce7aaf2816a163056de9436bbac44cc47c8bc5b1c9a330dc05748d6616431b1fb5bd5379733fb1da0b78d03c59f4ec824c184 + languageName: node + linkType: hard + +"@types/webpack-sources@npm:^0.1.5": + version: 0.1.12 + resolution: "@types/webpack-sources@npm:0.1.12" + dependencies: + "@types/node": "*" + "@types/source-list-map": "*" + source-map: ^0.6.1 + checksum: 75342659a9889478969f7bb7360b998aa084ba11ab523c172ded6a807dac43ab2a9e1212078ef8bbf0f33e4fadd2c8a91b75d38184d8030d96a32fe819c9bb57 + languageName: node + linkType: hard + +"@types/yargs-parser@npm:*": + version: 21.0.3 + resolution: "@types/yargs-parser@npm:21.0.3" + checksum: ef236c27f9432983e91432d974243e6c4cdae227cb673740320eff32d04d853eed59c92ca6f1142a335cfdc0e17cccafa62e95886a8154ca8891cc2dec4ee6fc + languageName: node + linkType: hard + +"@types/yargs@npm:^17.0.8": + version: 17.0.33 + resolution: "@types/yargs@npm:17.0.33" + dependencies: + "@types/yargs-parser": "*" + checksum: ee013f257472ab643cb0584cf3e1ff9b0c44bca1c9ba662395300a7f1a6c55fa9d41bd40ddff42d99f5d95febb3907c9ff600fbcb92dadbec22c6a76de7e1236 + languageName: node + linkType: hard + +"@typescript-eslint/eslint-plugin@npm:^6.19.1": + version: 6.21.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.21.0" + dependencies: + "@eslint-community/regexpp": ^4.5.1 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/type-utils": 6.21.0 + "@typescript-eslint/utils": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + debug: ^4.3.4 + graphemer: ^1.4.0 + ignore: ^5.2.4 + natural-compare: ^1.4.0 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependencies: + "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 5ef2c502255e643e98051e87eb682c2a257e87afd8ec3b9f6274277615e1c2caf3131b352244cfb1987b8b2c415645eeacb9113fa841fc4c9b2ac46e8aed6efd + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^6.19.1": + version: 6.21.0 + resolution: "@typescript-eslint/parser@npm:6.21.0" + dependencies: + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + debug: ^4.3.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 162fe3a867eeeffda7328bce32dae45b52283c68c8cb23258fb9f44971f761991af61f71b8c9fe1aa389e93dfe6386f8509c1273d870736c507d76dd40647b68 + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/scope-manager@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + checksum: 71028b757da9694528c4c3294a96cc80bc7d396e383a405eab3bc224cda7341b88e0fc292120b35d3f31f47beac69f7083196c70616434072fbcd3d3e62d3376 + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/type-utils@npm:6.21.0" + dependencies: + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/utils": 6.21.0 + debug: ^4.3.4 + ts-api-utils: ^1.0.1 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 77025473f4d80acf1fafcce99c5c283e557686a61861febeba9c9913331f8a41e930bf5cd8b7a54db502a57b6eb8ea6d155cbd4f41349ed00e3d7aeb1f477ddc + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + minimatch: 9.0.3 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: dec02dc107c4a541e14fb0c96148f3764b92117c3b635db3a577b5a56fc48df7a556fa853fb82b07c0663b4bf2c484c9f245c28ba3e17e5cb0918ea4cab2ea21 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/utils@npm:6.21.0" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@types/json-schema": ^7.0.12 + "@types/semver": ^7.5.0 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 + semver: ^7.5.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + checksum: b129b3a4aebec8468259f4589985cb59ea808afbfdb9c54f02fad11e17d185e2bf72bb332f7c36ec3c09b31f18fc41368678b076323e6e019d06f74ee93f7bf2 + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + eslint-visitor-keys: ^3.4.1 + checksum: 67c7e6003d5af042d8703d11538fca9d76899f0119130b373402819ae43f0bc90d18656aa7add25a24427ccf1a0efd0804157ba83b0d4e145f06107d7d1b7433 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.2.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 + languageName: node + linkType: hard + +"@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/ast@npm:1.12.1" + dependencies: + "@webassemblyjs/helper-numbers": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + checksum: 31bcc64147236bd7b1b6d29d1f419c1f5845c785e1e42dc9e3f8ca2e05a029e9393a271b84f3a5bff2a32d35f51ff59e2181a6e5f953fe88576acd6750506202 + languageName: node + linkType: hard + +"@webassemblyjs/floating-point-hex-parser@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6" + checksum: 29b08758841fd8b299c7152eda36b9eb4921e9c584eb4594437b5cd90ed6b920523606eae7316175f89c20628da14326801090167cc7fbffc77af448ac84b7e2 + languageName: node + linkType: hard + +"@webassemblyjs/helper-api-error@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-api-error@npm:1.11.6" + checksum: e8563df85161096343008f9161adb138a6e8f3c2cc338d6a36011aa55eabb32f2fd138ffe63bc278d009ada001cc41d263dadd1c0be01be6c2ed99076103689f + languageName: node + linkType: hard + +"@webassemblyjs/helper-buffer@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/helper-buffer@npm:1.12.1" + checksum: c3ffb723024130308db608e86e2bdccd4868bbb62dffb0a9a1530606496f79c87f8565bd8e02805ce64912b71f1a70ee5fb00307258b0c082c3abf961d097eca + languageName: node + linkType: hard + +"@webassemblyjs/helper-numbers@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-numbers@npm:1.11.6" + dependencies: + "@webassemblyjs/floating-point-hex-parser": 1.11.6 + "@webassemblyjs/helper-api-error": 1.11.6 + "@xtuc/long": 4.2.2 + checksum: f4b562fa219f84368528339e0f8d273ad44e047a07641ffcaaec6f93e5b76fd86490a009aa91a294584e1436d74b0a01fa9fde45e333a4c657b58168b04da424 + languageName: node + linkType: hard + +"@webassemblyjs/helper-wasm-bytecode@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.6" + checksum: 3535ef4f1fba38de3475e383b3980f4bbf3de72bbb631c2b6584c7df45be4eccd62c6ff48b5edd3f1bcff275cfd605a37679ec199fc91fd0a7705d7f1e3972dc + languageName: node + linkType: hard + +"@webassemblyjs/helper-wasm-section@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": 1.12.1 + "@webassemblyjs/helper-buffer": 1.12.1 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/wasm-gen": 1.12.1 + checksum: c19810cdd2c90ff574139b6d8c0dda254d42d168a9e5b3d353d1bc085f1d7164ccd1b3c05592a45a939c47f7e403dc8d03572bb686642f06a3d02932f6f0bc8f + languageName: node + linkType: hard + +"@webassemblyjs/ieee754@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/ieee754@npm:1.11.6" + dependencies: + "@xtuc/ieee754": ^1.2.0 + checksum: 13574b8e41f6ca39b700e292d7edf102577db5650fe8add7066a320aa4b7a7c09a5056feccac7a74eb68c10dea9546d4461412af351f13f6b24b5f32379b49de + languageName: node + linkType: hard + +"@webassemblyjs/leb128@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/leb128@npm:1.11.6" + dependencies: + "@xtuc/long": 4.2.2 + checksum: 7ea942dc9777d4b18a5ebfa3a937b30ae9e1d2ce1fee637583ed7f376334dd1d4274f813d2e250056cca803e0952def4b954913f1a3c9068bcd4ab4ee5143bf0 + languageName: node + linkType: hard + +"@webassemblyjs/utf8@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/utf8@npm:1.11.6" + checksum: 807fe5b5ce10c390cfdd93e0fb92abda8aebabb5199980681e7c3743ee3306a75729bcd1e56a3903980e96c885ee53ef901fcbaac8efdfa480f9c0dae1d08713 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-edit@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-edit@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": 1.12.1 + "@webassemblyjs/helper-buffer": 1.12.1 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/helper-wasm-section": 1.12.1 + "@webassemblyjs/wasm-gen": 1.12.1 + "@webassemblyjs/wasm-opt": 1.12.1 + "@webassemblyjs/wasm-parser": 1.12.1 + "@webassemblyjs/wast-printer": 1.12.1 + checksum: ae23642303f030af888d30c4ef37b08dfec7eab6851a9575a616e65d1219f880d9223913a39056dd654e49049d76e97555b285d1f7e56935047abf578cce0692 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-gen@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-gen@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": 1.12.1 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/ieee754": 1.11.6 + "@webassemblyjs/leb128": 1.11.6 + "@webassemblyjs/utf8": 1.11.6 + checksum: 5787626bb7f0b033044471ddd00ce0c9fe1ee4584e8b73e232051e3a4c99ba1a102700d75337151c8b6055bae77eefa4548960c610a5e4a504e356bd872138ff + languageName: node + linkType: hard + +"@webassemblyjs/wasm-opt@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-opt@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": 1.12.1 + "@webassemblyjs/helper-buffer": 1.12.1 + "@webassemblyjs/wasm-gen": 1.12.1 + "@webassemblyjs/wasm-parser": 1.12.1 + checksum: 0e8fa8a0645304a1e18ff40d3db5a2e9233ebaa169b19fcc651d6fc9fe2cac0ce092ddee927318015ae735d9cd9c5d97c0cafb6a51dcd2932ac73587b62df991 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-parser@npm:1.12.1, @webassemblyjs/wasm-parser@npm:^1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wasm-parser@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": 1.12.1 + "@webassemblyjs/helper-api-error": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/ieee754": 1.11.6 + "@webassemblyjs/leb128": 1.11.6 + "@webassemblyjs/utf8": 1.11.6 + checksum: 176015de3551ac068cd4505d837414f258d9ade7442bd71efb1232fa26c9f6d7d4e11a5c816caeed389943f409af7ebff6899289a992d7a70343cb47009d21a8 + languageName: node + linkType: hard + +"@webassemblyjs/wast-printer@npm:1.12.1": + version: 1.12.1 + resolution: "@webassemblyjs/wast-printer@npm:1.12.1" + dependencies: + "@webassemblyjs/ast": 1.12.1 + "@xtuc/long": 4.2.2 + checksum: 2974b5dda8d769145ba0efd886ea94a601e61fb37114c14f9a9a7606afc23456799af652ac3052f284909bd42edc3665a76bc9b50f95f0794c053a8a1757b713 + languageName: node + linkType: hard + +"@webpack-cli/configtest@npm:^2.1.1": + version: 2.1.1 + resolution: "@webpack-cli/configtest@npm:2.1.1" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + checksum: 9f9f9145c2d05471fc83d426db1df85cf49f329836b0c4b9f46b6948bed4b013464c00622b136d2a0a26993ce2306976682592245b08ee717500b1db45009a72 + languageName: node + linkType: hard + +"@webpack-cli/info@npm:^2.0.2": + version: 2.0.2 + resolution: "@webpack-cli/info@npm:2.0.2" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + checksum: 8f9a178afca5c82e113aed1efa552d64ee5ae4fdff63fe747c096a981ec74f18a5d07bd6e89bbe6715c3e57d96eea024a410e58977169489fe1df044c10dd94e + languageName: node + linkType: hard + +"@webpack-cli/serve@npm:^2.0.5": + version: 2.0.5 + resolution: "@webpack-cli/serve@npm:2.0.5" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + peerDependenciesMeta: + webpack-dev-server: + optional: true + checksum: 75f0e54681796d567a71ac3e2781d2901a8d8cf1cdfc82f261034dddac59a8343e8c3bc5e32b4bb9d6766759ba49fb29a5cd86ef1701d79c506fe886bb63ac75 + languageName: node + linkType: hard + +"@xtuc/ieee754@npm:^1.2.0": + version: 1.2.0 + resolution: "@xtuc/ieee754@npm:1.2.0" + checksum: ac56d4ca6e17790f1b1677f978c0c6808b1900a5b138885d3da21732f62e30e8f0d9120fcf8f6edfff5100ca902b46f8dd7c1e3f903728634523981e80e2885a + languageName: node + linkType: hard + +"@xtuc/long@npm:4.2.2": + version: 4.2.2 + resolution: "@xtuc/long@npm:4.2.2" + checksum: 8ed0d477ce3bc9c6fe2bf6a6a2cc316bb9c4127c5a7827bae947fa8ec34c7092395c5a283cc300c05b5fa01cbbfa1f938f410a7bf75db7c7846fea41949989ec + languageName: node + linkType: hard + +"abab@npm:^2.0.3": + version: 2.0.6 + resolution: "abab@npm:2.0.6" + checksum: 6ffc1af4ff315066c62600123990d87551ceb0aafa01e6539da77b0f5987ac7019466780bf480f1787576d4385e3690c81ccc37cfda12819bf510b8ab47e5a3e + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 + languageName: node + linkType: hard + +"acorn-import-attributes@npm:^1.9.5": + version: 1.9.5 + resolution: "acorn-import-attributes@npm:1.9.5" + peerDependencies: + acorn: ^8 + checksum: 1c0c49b6a244503964ae46ae850baccf306e84caf99bc2010ed6103c69a423987b07b520a6c619f075d215388bd4923eccac995886a54309eda049ab78a4be95 + languageName: node + linkType: hard + +"acorn-jsx@npm:^5.3.2": + version: 5.3.2 + resolution: "acorn-jsx@npm:5.3.2" + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 + languageName: node + linkType: hard + +"acorn@npm:^8.11.3, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.12.1 + resolution: "acorn@npm:8.12.1" + bin: + acorn: bin/acorn + checksum: 677880034aee5bdf7434cc2d25b641d7bedb0b5ef47868a78dadabedccf58e1c5457526d9d8249cd253f2df087e081c3fe7d903b448d8e19e5131a3065b83c07 + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" + dependencies: + debug: ^4.3.4 + checksum: 51c158769c5c051482f9ca2e6e1ec085ac72b5a418a9b31b4e82fe6c0a6699adb94c1c42d246699a587b3335215037091c79e0de512c516f73b6ea844202f037 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: ^2.0.0 + indent-string: ^4.0.0 + checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 + languageName: node + linkType: hard + +"ajv-formats@npm:^2.1.1": + version: 2.1.1 + resolution: "ajv-formats@npm:2.1.1" + dependencies: + ajv: ^8.0.0 + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + checksum: 4a287d937f1ebaad4683249a4c40c0fa3beed30d9ddc0adba04859026a622da0d317851316ea64b3680dc60f5c3c708105ddd5d5db8fe595d9d0207fd19f90b7 + languageName: node + linkType: hard + +"ajv-keywords@npm:^3.5.2": + version: 3.5.2 + resolution: "ajv-keywords@npm:3.5.2" + peerDependencies: + ajv: ^6.9.1 + checksum: 7dc5e5931677a680589050f79dcbe1fefbb8fea38a955af03724229139175b433c63c68f7ae5f86cf8f65d55eb7c25f75a046723e2e58296707617ca690feae9 + languageName: node + linkType: hard + +"ajv-keywords@npm:^5.1.0": + version: 5.1.0 + resolution: "ajv-keywords@npm:5.1.0" + dependencies: + fast-deep-equal: ^3.1.3 + peerDependencies: + ajv: ^8.8.2 + checksum: c35193940b853119242c6757787f09ecf89a2c19bcd36d03ed1a615e710d19d450cb448bfda407b939aba54b002368c8bff30529cc50a0536a8e10bcce300421 + languageName: node + linkType: hard + +"ajv@npm:^6.12.4, ajv@npm:^6.12.5": + version: 6.12.6 + resolution: "ajv@npm:6.12.6" + dependencies: + fast-deep-equal: ^3.1.1 + fast-json-stable-stringify: ^2.0.0 + json-schema-traverse: ^0.4.1 + uri-js: ^4.2.2 + checksum: 874972efe5c4202ab0a68379481fbd3d1b5d0a7bd6d3cc21d40d3536ebff3352a2a1fabb632d4fd2cc7fe4cbdcd5ed6782084c9bbf7f32a1536d18f9da5007d4 + languageName: node + linkType: hard + +"ajv@npm:^8.0.0, ajv@npm:^8.12.0, ajv@npm:^8.9.0": + version: 8.17.1 + resolution: "ajv@npm:8.17.1" + dependencies: + fast-deep-equal: ^3.1.3 + fast-uri: ^3.0.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + checksum: 1797bf242cfffbaf3b870d13565bd1716b73f214bb7ada9a497063aada210200da36e3ed40237285f3255acc4feeae91b1fb183625331bad27da95973f7253d9 + languageName: node + linkType: hard + +"ansi-escapes@npm:^4.2.1": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: ^0.21.3 + checksum: 93111c42189c0a6bed9cdb4d7f2829548e943827ee8479c74d6e0b22ee127b2a21d3f8b5ca57723b8ef78ce011fbfc2784350eb2bde3ccfccf2f575fa8489815 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + languageName: node + linkType: hard + +"ansi-styles@npm:^3.2.1": + version: 3.2.1 + resolution: "ansi-styles@npm:3.2.1" + dependencies: + color-convert: ^1.9.0 + checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: ^2.0.1 + checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 + languageName: node + linkType: hard + +"ansi-styles@npm:^5.0.0": + version: 5.2.0 + resolution: "ansi-styles@npm:5.2.0" + checksum: d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + languageName: node + linkType: hard + +"anymatch@npm:^3.0.3": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: ^3.0.0 + picomatch: ^2.0.4 + checksum: 3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 + languageName: node + linkType: hard + +"argparse@npm:^1.0.7": + version: 1.0.10 + resolution: "argparse@npm:1.0.10" + dependencies: + sprintf-js: ~1.0.2 + checksum: 7ca6e45583a28de7258e39e13d81e925cfa25d7d4aacbf806a382d3c02fcb13403a07fb8aeef949f10a7cfe4a62da0e2e807b348a5980554cc28ee573ef95945 + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced + languageName: node + linkType: hard + +"array-buffer-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "array-buffer-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.5 + is-array-buffer: ^3.0.4 + checksum: 53524e08f40867f6a9f35318fafe467c32e45e9c682ba67b11943e167344d2febc0f6977a17e699b05699e805c3e8f073d876f8bbf1b559ed494ad2cd0fae09e + languageName: node + linkType: hard + +"array-union@npm:^2.1.0": + version: 2.1.0 + resolution: "array-union@npm:2.1.0" + checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d + languageName: node + linkType: hard + +"arraybuffer.prototype.slice@npm:^1.0.3": + version: 1.0.3 + resolution: "arraybuffer.prototype.slice@npm:1.0.3" + dependencies: + array-buffer-byte-length: ^1.0.1 + call-bind: ^1.0.5 + define-properties: ^1.2.1 + es-abstract: ^1.22.3 + es-errors: ^1.2.1 + get-intrinsic: ^1.2.3 + is-array-buffer: ^3.0.4 + is-shared-array-buffer: ^1.0.2 + checksum: 352259cba534dcdd969c92ab002efd2ba5025b2e3b9bead3973150edbdf0696c629d7f4b3f061c5931511e8207bdc2306da614703c820b45dabce39e3daf7e3e + languageName: node + linkType: hard + +"async@npm:^3.2.3": + version: 3.2.5 + resolution: "async@npm:3.2.5" + checksum: 5ec77f1312301dee02d62140a6b1f7ee0edd2a0f983b6fd2b0849b969f245225b990b47b8243e7b9ad16451a53e7f68e753700385b706198ced888beedba3af4 + languageName: node + linkType: hard + +"available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: ^1.0.0 + checksum: 1aa3ffbfe6578276996de660848b6e95669d9a95ad149e3dd0c0cda77db6ee1dbd9d1dd723b65b6d277b882dd0c4b91a654ae9d3cf9e1254b7e93e4908d78fd3 + languageName: node + linkType: hard + +"babel-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "babel-jest@npm:29.7.0" + dependencies: + "@jest/transform": ^29.7.0 + "@types/babel__core": ^7.1.14 + babel-plugin-istanbul: ^6.1.1 + babel-preset-jest: ^29.6.3 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + slash: ^3.0.0 + peerDependencies: + "@babel/core": ^7.8.0 + checksum: ee6f8e0495afee07cac5e4ee167be705c711a8cc8a737e05a587a131fdae2b3c8f9aa55dfd4d9c03009ac2d27f2de63d8ba96d3e8460da4d00e8af19ef9a83f7 + languageName: node + linkType: hard + +"babel-plugin-istanbul@npm:^6.1.1": + version: 6.1.1 + resolution: "babel-plugin-istanbul@npm:6.1.1" + dependencies: + "@babel/helper-plugin-utils": ^7.0.0 + "@istanbuljs/load-nyc-config": ^1.0.0 + "@istanbuljs/schema": ^0.1.2 + istanbul-lib-instrument: ^5.0.4 + test-exclude: ^6.0.0 + checksum: cb4fd95738219f232f0aece1116628cccff16db891713c4ccb501cddbbf9272951a5df81f2f2658dfdf4b3e7b236a9d5cbcf04d5d8c07dd5077297339598061a + languageName: node + linkType: hard + +"babel-plugin-jest-hoist@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-plugin-jest-hoist@npm:29.6.3" + dependencies: + "@babel/template": ^7.3.3 + "@babel/types": ^7.3.3 + "@types/babel__core": ^7.1.14 + "@types/babel__traverse": ^7.0.6 + checksum: 51250f22815a7318f17214a9d44650ba89551e6d4f47a2dc259128428324b52f5a73979d010cefd921fd5a720d8c1d55ad74ff601cd94c7bd44d5f6292fde2d1 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs2@npm:^0.4.10": + version: 0.4.11 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.11" + dependencies: + "@babel/compat-data": ^7.22.6 + "@babel/helper-define-polyfill-provider": ^0.6.2 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: f098353ce7c7dde1a1d2710858e01b471e85689110c9e37813e009072347eb8c55d5f84d20d3bf1cab31755f20078ba90f8855fdc4686a9daa826a95ff280bd7 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.10.4": + version: 0.10.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.10.6" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.6.2 + core-js-compat: ^3.38.0 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: f762f29f7acca576897c63149c850f0a72babd3fb9ea436a2e36f0c339161c4b912a77828541d8188ce8a91e50965c6687120cf36071eabb1b7aa92f279e2164 + languageName: node + linkType: hard + +"babel-plugin-polyfill-regenerator@npm:^0.6.1": + version: 0.6.2 + resolution: "babel-plugin-polyfill-regenerator@npm:0.6.2" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.6.2 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 150233571072b6b3dfe946242da39cba8587b7f908d1c006f7545fc88b0e3c3018d445739beb61e7a75835f0c2751dbe884a94ff9b245ec42369d9267e0e1b3f + languageName: node + linkType: hard + +"babel-preset-current-node-syntax@npm:^1.0.0": + version: 1.1.0 + resolution: "babel-preset-current-node-syntax@npm:1.1.0" + dependencies: + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/plugin-syntax-bigint": ^7.8.3 + "@babel/plugin-syntax-class-properties": ^7.12.13 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + "@babel/plugin-syntax-import-attributes": ^7.24.7 + "@babel/plugin-syntax-import-meta": ^7.10.4 + "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + "@babel/plugin-syntax-top-level-await": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 9f93fac975eaba296c436feeca1031ca0539143c4066eaf5d1ba23525a31850f03b651a1049caea7287df837a409588c8252c15627ad3903f17864c8e25ed64b + languageName: node + linkType: hard + +"babel-preset-jest@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-preset-jest@npm:29.6.3" + dependencies: + babel-plugin-jest-hoist: ^29.6.3 + babel-preset-current-node-syntax: ^1.0.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: aa4ff2a8a728d9d698ed521e3461a109a1e66202b13d3494e41eea30729a5e7cc03b3a2d56c594423a135429c37bf63a9fa8b0b9ce275298be3095a88c69f6fb + languageName: node + linkType: hard + +"backbone@npm:1.4.0": + version: 1.4.0 + resolution: "backbone@npm:1.4.0" + dependencies: + underscore: ">=1.8.3" + checksum: 09abdf184c485a4cd2c68218298cf772fbefeaa166ef8eb795cdb0159b4ad1d2f6823dde089352eaf0be929e5bbef67c57555722f4d1886f969d954f77814870 + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 + languageName: node + linkType: hard + +"base64-js@npm:^1.2.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 + languageName: node + linkType: hard + +"big.js@npm:^5.2.2": + version: 5.2.2 + resolution: "big.js@npm:5.2.2" + checksum: b89b6e8419b097a8fb4ed2399a1931a68c612bce3cfd5ca8c214b2d017531191070f990598de2fc6f3f993d91c0f08aa82697717f6b3b8732c9731866d233c9e + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" + dependencies: + balanced-match: ^1.0.0 + concat-map: 0.0.1 + checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: ^1.0.0 + checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + languageName: node + linkType: hard + +"braces@npm:^3.0.3": + version: 3.0.3 + resolution: "braces@npm:3.0.3" + dependencies: + fill-range: ^7.1.1 + checksum: b95aa0b3bd909f6cd1720ffcf031aeaf46154dd88b4da01f9a1d3f7ea866a79eba76a6d01cbc3c422b2ee5cdc39a4f02491058d5df0d7bf6e6a162a832df1f69 + languageName: node + linkType: hard + +"browserslist@npm:^4.21.10, browserslist@npm:^4.23.1, browserslist@npm:^4.23.3": + version: 4.23.3 + resolution: "browserslist@npm:4.23.3" + dependencies: + caniuse-lite: ^1.0.30001646 + electron-to-chromium: ^1.5.4 + node-releases: ^2.0.18 + update-browserslist-db: ^1.1.0 + bin: + browserslist: cli.js + checksum: 7906064f9970aeb941310b2fcb8b4ace4a1b50aa657c986677c6f1553a8cabcc94ee9c5922f715baffbedaa0e6cf0831b6fed7b059dde6873a4bfadcbe069c7e + languageName: node + linkType: hard + +"bs-logger@npm:0.x": + version: 0.2.6 + resolution: "bs-logger@npm:0.2.6" + dependencies: + fast-json-stable-stringify: 2.x + checksum: d34bdaf68c64bd099ab97c3ea608c9ae7d3f5faa1178b3f3f345acd94e852e608b2d4f9103fb2e503f5e69780e98293df41691b84be909b41cf5045374d54606 + languageName: node + linkType: hard + +"bser@npm:2.1.1": + version: 2.1.1 + resolution: "bser@npm:2.1.1" + dependencies: + node-int64: ^0.4.0 + checksum: 9ba4dc58ce86300c862bffc3ae91f00b2a03b01ee07f3564beeeaf82aa243b8b03ba53f123b0b842c190d4399b94697970c8e7cf7b1ea44b61aa28c3526a4449 + languageName: node + linkType: hard + +"buffer-from@npm:^1.0.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.4 + resolution: "cacache@npm:18.0.4" + dependencies: + "@npmcli/fs": ^3.1.0 + fs-minipass: ^3.0.0 + glob: ^10.2.2 + lru-cache: ^10.0.1 + minipass: ^7.0.3 + minipass-collect: ^2.0.1 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + p-map: ^4.0.0 + ssri: ^10.0.0 + tar: ^6.1.11 + unique-filename: ^3.0.0 + checksum: b7422c113b4ec750f33beeca0f426a0024c28e3172f332218f48f963e5b970647fa1ac05679fe5bb448832c51efea9fda4456b9a95c3a1af1105fe6c1833cde2 + languageName: node + linkType: hard + +"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": + version: 1.0.7 + resolution: "call-bind@npm:1.0.7" + dependencies: + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.4 + set-function-length: ^1.2.1 + checksum: 295c0c62b90dd6522e6db3b0ab1ce26bdf9e7404215bda13cfee25b626b5ff1a7761324d58d38b1ef1607fc65aca2d06e44d2e18d0dfc6c14b465b00d8660029 + languageName: node + linkType: hard + +"callsites@npm:^3.0.0": + version: 3.1.0 + resolution: "callsites@npm:3.1.0" + checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 + languageName: node + linkType: hard + +"camelcase@npm:^5.3.1": + version: 5.3.1 + resolution: "camelcase@npm:5.3.1" + checksum: e6effce26b9404e3c0f301498184f243811c30dfe6d0b9051863bd8e4034d09c8c2923794f280d6827e5aa055f6c434115ff97864a16a963366fb35fd673024b + languageName: node + linkType: hard + +"camelcase@npm:^6.2.0": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001646": + version: 1.0.30001651 + resolution: "caniuse-lite@npm:1.0.30001651" + checksum: c31a5a01288e70cdbbfb5cd94af3df02f295791673173b8ce6d6a16db4394a6999197d44190be5a6ff06b8c2c7d2047e94dfd5e5eb4c103ab000fca2d370afc7 + languageName: node + linkType: hard + +"chalk@npm:^2.3.0, chalk@npm:^2.4.1, chalk@npm:^2.4.2": + version: 2.4.2 + resolution: "chalk@npm:2.4.2" + dependencies: + ansi-styles: ^3.2.1 + escape-string-regexp: ^1.0.5 + supports-color: ^5.3.0 + checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 + languageName: node + linkType: hard + +"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc + languageName: node + linkType: hard + +"char-regex@npm:^1.0.2": + version: 1.0.2 + resolution: "char-regex@npm:1.0.2" + checksum: b563e4b6039b15213114626621e7a3d12f31008bdce20f9c741d69987f62aeaace7ec30f6018890ad77b2e9b4d95324c9f5acfca58a9441e3b1dcdd1e2525d17 + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f + languageName: node + linkType: hard + +"chrome-trace-event@npm:^1.0.2": + version: 1.0.4 + resolution: "chrome-trace-event@npm:1.0.4" + checksum: fcbbd9dd0cd5b48444319007cc0c15870fd8612cc0df320908aa9d5e8a244084d48571eb28bf3c58c19327d2c5838f354c2d89fac3956d8e992273437401ac19 + languageName: node + linkType: hard + +"ci-info@npm:^3.2.0": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 6b19dc9b2966d1f8c2041a838217299718f15d6c4b63ae36e4674edd2bee48f780e94761286a56aa59eb305a85fbea4ddffb7630ec063e7ec7e7e5ad42549a87 + languageName: node + linkType: hard + +"cjs-module-lexer@npm:^1.0.0": + version: 1.3.1 + resolution: "cjs-module-lexer@npm:1.3.1" + checksum: 75f20ac264a397ea5c63f9c2343a51ab878043666468f275e94862f7180ec1d764a400ec0c09085dcf0db3193c74a8b571519abd2bf4be0d2be510d1377c8d4b + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 + languageName: node + linkType: hard + +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.1 + wrap-ansi: ^7.0.0 + checksum: 79648b3b0045f2e285b76fb2e24e207c6db44323581e421c3acbd0e86454cba1b37aea976ab50195a49e7384b871e6dfb2247ad7dec53c02454ac6497394cb56 + languageName: node + linkType: hard + +"clone-deep@npm:^4.0.1": + version: 4.0.1 + resolution: "clone-deep@npm:4.0.1" + dependencies: + is-plain-object: ^2.0.4 + kind-of: ^6.0.2 + shallow-clone: ^3.0.0 + checksum: 770f912fe4e6f21873c8e8fbb1e99134db3b93da32df271d00589ea4a29dbe83a9808a322c93f3bcaf8584b8b4fa6fc269fc8032efbaa6728e0c9886c74467d2 + languageName: node + linkType: hard + +"co@npm:^4.6.0": + version: 4.6.0 + resolution: "co@npm:4.6.0" + checksum: 5210d9223010eb95b29df06a91116f2cf7c8e0748a9013ed853b53f362ea0e822f1e5bb054fb3cefc645239a4cf966af1f6133a3b43f40d591f3b68ed6cf0510 + languageName: node + linkType: hard + +"collect-v8-coverage@npm:^1.0.0": + version: 1.0.2 + resolution: "collect-v8-coverage@npm:1.0.2" + checksum: c10f41c39ab84629d16f9f6137bc8a63d332244383fc368caf2d2052b5e04c20cd1fd70f66fcf4e2422b84c8226598b776d39d5f2d2a51867cc1ed5d1982b4da + languageName: node + linkType: hard + +"color-convert@npm:^1.9.0": + version: 1.9.3 + resolution: "color-convert@npm:1.9.3" + dependencies: + color-name: 1.1.3 + checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: ~1.1.4 + checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 + languageName: node + linkType: hard + +"color-name@npm:1.1.3": + version: 1.1.3 + resolution: "color-name@npm:1.1.3" + checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 + languageName: node + linkType: hard + +"colorette@npm:^2.0.14": + version: 2.0.20 + resolution: "colorette@npm:2.0.20" + checksum: 0c016fea2b91b733eb9f4bcdb580018f52c0bc0979443dad930e5037a968237ac53d9beb98e218d2e9235834f8eebce7f8e080422d6194e957454255bde71d3d + languageName: node + linkType: hard + +"commander@npm:^10.0.1": + version: 10.0.1 + resolution: "commander@npm:10.0.1" + checksum: 436901d64a818295803c1996cd856621a74f30b9f9e28a588e726b2b1670665bccd7c1a77007ebf328729f0139838a88a19265858a0fa7a8728c4656796db948 + languageName: node + linkType: hard + +"commander@npm:^2.20.0": + version: 2.20.3 + resolution: "commander@npm:2.20.3" + checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e + languageName: node + linkType: hard + +"commander@npm:^9.4.1": + version: 9.5.0 + resolution: "commander@npm:9.5.0" + checksum: c7a3e27aa59e913b54a1bafd366b88650bc41d6651f0cbe258d4ff09d43d6a7394232a4dadd0bf518b3e696fdf595db1028a0d82c785b88bd61f8a440cecfade + languageName: node + linkType: hard + +"compute-gcd@npm:^1.2.1": + version: 1.2.1 + resolution: "compute-gcd@npm:1.2.1" + dependencies: + validate.io-array: ^1.0.3 + validate.io-function: ^1.0.2 + validate.io-integer-array: ^1.0.0 + checksum: 51cf33b75f7c8db5142fcb99a9d84a40260993fed8e02a7ab443834186c3ab99b3fd20b30ad9075a6a9d959d69df6da74dd3be8a59c78d9f2fe780ebda8242e1 + languageName: node + linkType: hard + +"compute-lcm@npm:^1.1.2": + version: 1.1.2 + resolution: "compute-lcm@npm:1.1.2" + dependencies: + compute-gcd: ^1.2.1 + validate.io-array: ^1.0.3 + validate.io-function: ^1.0.2 + validate.io-integer-array: ^1.0.0 + checksum: d499ab57dcb48e8d0fd233b99844a06d1cc56115602c920c586e998ebba60293731f5b6976e8a1e83ae6cbfe86716f62d9432e8d94913fed8bd8352f447dc917 + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af + languageName: node + linkType: hard + +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 63ae9933be5a2b8d4509daca5124e20c14d023c820258e484e32dc324d34c2754e71297c94a05784064ad27615037ef677e3f0c00469fb55f409d2bb21261035 + languageName: node + linkType: hard + +"core-js-compat@npm:^3.37.1, core-js-compat@npm:^3.38.0": + version: 3.38.0 + resolution: "core-js-compat@npm:3.38.0" + dependencies: + browserslist: ^4.23.3 + checksum: bd410be723e3621f7e8c7a4dce91eaefc603d95133da89c042dd961aca368c7281894bd9af14116a455a4473288fb6c121b185cb8a1e8290b8ace15aedb315f2 + languageName: node + linkType: hard + +"create-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "create-jest@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + jest-config: ^29.7.0 + jest-util: ^29.7.0 + prompts: ^2.0.1 + bin: + create-jest: bin/create-jest.js + checksum: 1427d49458adcd88547ef6fa39041e1fe9033a661293aa8d2c3aa1b4967cb5bf4f0c00436c7a61816558f28ba2ba81a94d5c962e8022ea9a883978fc8e1f2945 + languageName: node + linkType: hard + +"cross-spawn@npm:^6.0.5": + version: 6.0.5 + resolution: "cross-spawn@npm:6.0.5" + dependencies: + nice-try: ^1.0.4 + path-key: ^2.0.1 + semver: ^5.5.0 + shebang-command: ^1.2.0 + which: ^1.2.9 + checksum: f893bb0d96cd3d5751d04e67145bdddf25f99449531a72e82dcbbd42796bbc8268c1076c6b3ea51d4d455839902804b94bc45dfb37ecbb32ea8e54a6741c3ab9 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: ^3.1.0 + shebang-command: ^2.0.0 + which: ^2.0.1 + checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 + languageName: node + linkType: hard + +"css-loader@npm:^6.7.1, css-loader@npm:^6.9.1": + version: 6.11.0 + resolution: "css-loader@npm:6.11.0" + dependencies: + icss-utils: ^5.1.0 + postcss: ^8.4.33 + postcss-modules-extract-imports: ^3.1.0 + postcss-modules-local-by-default: ^4.0.5 + postcss-modules-scope: ^3.2.0 + postcss-modules-values: ^4.0.0 + postcss-value-parser: ^4.2.0 + semver: ^7.5.4 + peerDependencies: + "@rspack/core": 0.x || 1.x + webpack: ^5.0.0 + peerDependenciesMeta: + "@rspack/core": + optional: true + webpack: + optional: true + checksum: 5c8d35975a7121334905394e88e28f05df72f037dbed2fb8fec4be5f0b313ae73a13894ba791867d4a4190c35896da84a7fd0c54fb426db55d85ba5e714edbe3 + languageName: node + linkType: hard + +"cssesc@npm:^3.0.0": + version: 3.0.0 + resolution: "cssesc@npm:3.0.0" + bin: + cssesc: bin/cssesc + checksum: f8c4ababffbc5e2ddf2fa9957dda1ee4af6048e22aeda1869d0d00843223c1b13ad3f5d88b51caa46c994225eacb636b764eb807a8883e2fb6f99b4f4e8c48b2 + languageName: node + linkType: hard + +"data-urls@npm:^2.0.0": + version: 2.0.0 + resolution: "data-urls@npm:2.0.0" + dependencies: + abab: ^2.0.3 + whatwg-mimetype: ^2.3.0 + whatwg-url: ^8.0.0 + checksum: 97caf828aac25e25e04ba6869db0f99c75e6859bb5b424ada28d3e7841941ebf08ddff3c1b1bb4585986bd507a5d54c2a716853ea6cb98af877400e637393e71 + languageName: node + linkType: hard + +"data-view-buffer@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-buffer@npm:1.0.1" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: ce24348f3c6231223b216da92e7e6a57a12b4af81a23f27eff8feabdf06acfb16c00639c8b705ca4d167f761cfc756e27e5f065d0a1f840c10b907fdaf8b988c + languageName: node + linkType: hard + +"data-view-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: dbb3200edcb7c1ef0d68979834f81d64fd8cab2f7691b3a4c6b97e67f22182f3ec2c8602efd7b76997b55af6ff8bce485829c1feda4fa2165a6b71fb7baa4269 + languageName: node + linkType: hard + +"data-view-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "data-view-byte-offset@npm:1.0.0" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-data-view: ^1.0.1 + checksum: 7f0bf8720b7414ca719eedf1846aeec392f2054d7af707c5dc9a753cc77eb8625f067fa901e0b5127e831f9da9056138d894b9c2be79c27a21f6db5824f009c2 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": + version: 4.3.6 + resolution: "debug@npm:4.3.6" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 1630b748dea3c581295e02137a9f5cbe2c1d85fea35c1e6597a65ca2b16a6fce68cec61b299d480787ef310ba927dc8c92d3061faba0ad06c6a724672f66be7f + languageName: node + linkType: hard + +"dedent@npm:^1.0.0": + version: 1.5.3 + resolution: "dedent@npm:1.5.3" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: 045b595557b2a8ea2eb9b0b4623d764e9a87326486fe2b61191b4342ed93dc01245644d8a09f3108a50c0ee7965f1eedd92e4a3a503ed89ea8e810566ea27f9a + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3": + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" + checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 + languageName: node + linkType: hard + +"deepmerge@npm:^4.2.2": + version: 4.3.1 + resolution: "deepmerge@npm:4.3.1" + checksum: 2024c6a980a1b7128084170c4cf56b0fd58a63f2da1660dcfe977415f27b17dbe5888668b59d0b063753f3220719d5e400b7f113609489c90160bb9a5518d052 + languageName: node + linkType: hard + +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" + dependencies: + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + gopd: ^1.0.1 + checksum: 8068ee6cab694d409ac25936eb861eea704b7763f7f342adbdfe337fc27c78d7ae0eff2364b2917b58c508d723c7a074326d068eef2e45c4edcd85cf94d0313b + languageName: node + linkType: hard + +"define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": + version: 1.2.1 + resolution: "define-properties@npm:1.2.1" + dependencies: + define-data-property: ^1.0.1 + has-property-descriptors: ^1.0.0 + object-keys: ^1.1.1 + checksum: b4ccd00597dd46cb2d4a379398f5b19fca84a16f3374e2249201992f36b30f6835949a9429669ee6b41b6e837205a163eadd745e472069e70dfc10f03e5fcc12 + languageName: node + linkType: hard + +"detect-newline@npm:^3.0.0": + version: 3.1.0 + resolution: "detect-newline@npm:3.1.0" + checksum: ae6cd429c41ad01b164c59ea36f264a2c479598e61cba7c99da24175a7ab80ddf066420f2bec9a1c57a6bead411b4655ff15ad7d281c000a89791f48cbe939e7 + languageName: node + linkType: hard + +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: f4914158e1f2276343d98ff5b31fc004e7304f5470bf0f1adb2ac6955d85a531a6458d33e87667f98f6ae52ebd3891bb47d420bb48a5bd8b7a27ee25b20e33aa + languageName: node + linkType: hard + +"dir-glob@npm:^3.0.1": + version: 3.0.1 + resolution: "dir-glob@npm:3.0.1" + dependencies: + path-type: ^4.0.0 + checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 + languageName: node + linkType: hard + +"doctrine@npm:^3.0.0": + version: 3.0.0 + resolution: "doctrine@npm:3.0.0" + dependencies: + esutils: ^2.0.2 + checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce + languageName: node + linkType: hard + +"dom-serializer@npm:^2.0.0": + version: 2.0.0 + resolution: "dom-serializer@npm:2.0.0" + dependencies: + domelementtype: ^2.3.0 + domhandler: ^5.0.2 + entities: ^4.2.0 + checksum: cd1810544fd8cdfbd51fa2c0c1128ec3a13ba92f14e61b7650b5de421b88205fd2e3f0cc6ace82f13334114addb90ed1c2f23074a51770a8e9c1273acbc7f3e6 + languageName: node + linkType: hard + +"domelementtype@npm:^2.3.0": + version: 2.3.0 + resolution: "domelementtype@npm:2.3.0" + checksum: ee837a318ff702622f383409d1f5b25dd1024b692ef64d3096ff702e26339f8e345820f29a68bcdcea8cfee3531776b3382651232fbeae95612d6f0a75efb4f6 + languageName: node + linkType: hard + +"domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": + version: 5.0.3 + resolution: "domhandler@npm:5.0.3" + dependencies: + domelementtype: ^2.3.0 + checksum: 0f58f4a6af63e6f3a4320aa446d28b5790a009018707bce2859dcb1d21144c7876482b5188395a188dfa974238c019e0a1e610d2fc269a12b2c192ea2b0b131c + languageName: node + linkType: hard + +"domutils@npm:^3.0.1": + version: 3.1.0 + resolution: "domutils@npm:3.1.0" + dependencies: + dom-serializer: ^2.0.0 + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + checksum: e5757456ddd173caa411cfc02c2bb64133c65546d2c4081381a3bafc8a57411a41eed70494551aa58030be9e58574fcc489828bebd673863d39924fb4878f416 + languageName: node + linkType: hard + +"duplicate-package-checker-webpack-plugin@npm:^3.0.0": + version: 3.0.0 + resolution: "duplicate-package-checker-webpack-plugin@npm:3.0.0" + dependencies: + chalk: ^2.3.0 + find-root: ^1.0.0 + lodash: ^4.17.4 + semver: ^5.4.1 + checksum: d77be45cb72d79a429c64d8f8f7603fea681d182fb795459a3d4afa608faad9a923378a7e80c6855f465263e1983140b6fc3682bd0213228b8cd7906ab4b934d + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed + languageName: node + linkType: hard + +"ejs@npm:^3.1.10": + version: 3.1.10 + resolution: "ejs@npm:3.1.10" + dependencies: + jake: ^10.8.5 + bin: + ejs: bin/cli.js + checksum: ce90637e9c7538663ae023b8a7a380b2ef7cc4096de70be85abf5a3b9641912dde65353211d05e24d56b1f242d71185c6d00e02cb8860701d571786d92c71f05 + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.5.4": + version: 1.5.9 + resolution: "electron-to-chromium@npm:1.5.9" + checksum: 6be72b08540830554c71c9bf96c27fa53275ca12159659a49a47bb8905713c488c5bc025d4dca66ffdd899eb95548b09cc23310551c67f153d2a4f6fd0015231 + languageName: node + linkType: hard + +"emittery@npm:^0.13.1": + version: 0.13.1 + resolution: "emittery@npm:0.13.1" + checksum: 2b089ab6306f38feaabf4f6f02792f9ec85fc054fda79f44f6790e61bbf6bc4e1616afb9b232e0c5ec5289a8a452f79bfa6d905a6fd64e94b49981f0934001c6 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 + languageName: node + linkType: hard + +"emojis-list@npm:^3.0.0": + version: 3.0.0 + resolution: "emojis-list@npm:3.0.0" + checksum: ddaaa02542e1e9436c03970eeed445f4ed29a5337dfba0fe0c38dfdd2af5da2429c2a0821304e8a8d1cadf27fdd5b22ff793571fa803ae16852a6975c65e8e70 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: ^0.6.2 + checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f + languageName: node + linkType: hard + +"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.17.0": + version: 5.17.1 + resolution: "enhanced-resolve@npm:5.17.1" + dependencies: + graceful-fs: ^4.2.4 + tapable: ^2.2.0 + checksum: 4bc38cf1cea96456f97503db7280394177d1bc46f8f87c267297d04f795ac5efa81e48115a2f5b6273c781027b5b6bfc5f62b54df629e4d25fa7001a86624f59 + languageName: node + linkType: hard + +"entities@npm:^4.2.0, entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 853f8ebd5b425d350bffa97dd6958143179a5938352ccae092c62d1267c4e392a039be1bae7d51b6e4ffad25f51f9617531fedf5237f15df302ccfb452cbf2d7 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e + languageName: node + linkType: hard + +"envinfo@npm:^7.7.3": + version: 7.13.0 + resolution: "envinfo@npm:7.13.0" + bin: + envinfo: dist/cli.js + checksum: 822fc30f53bd0be67f0e25be96eb6a2562b8062f3058846bbd7ec471bd4b7835fca6436ee72c4029c8ae4a3d8f8cddbe2ee725b22291f015232d20a682bee732 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 + languageName: node + linkType: hard + +"error-ex@npm:^1.3.1": + version: 1.3.2 + resolution: "error-ex@npm:1.3.2" + dependencies: + is-arrayish: ^0.2.1 + checksum: c1c2b8b65f9c91b0f9d75f0debaa7ec5b35c266c2cac5de412c1a6de86d4cbae04ae44e510378cb14d032d0645a36925d0186f8bb7367bcc629db256b743a001 + languageName: node + linkType: hard + +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2": + version: 1.23.3 + resolution: "es-abstract@npm:1.23.3" + dependencies: + array-buffer-byte-length: ^1.0.1 + arraybuffer.prototype.slice: ^1.0.3 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + data-view-buffer: ^1.0.1 + data-view-byte-length: ^1.0.1 + data-view-byte-offset: ^1.0.0 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + es-set-tostringtag: ^2.0.3 + es-to-primitive: ^1.2.1 + function.prototype.name: ^1.1.6 + get-intrinsic: ^1.2.4 + get-symbol-description: ^1.0.2 + globalthis: ^1.0.3 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.2 + has-proto: ^1.0.3 + has-symbols: ^1.0.3 + hasown: ^2.0.2 + internal-slot: ^1.0.7 + is-array-buffer: ^3.0.4 + is-callable: ^1.2.7 + is-data-view: ^1.0.1 + is-negative-zero: ^2.0.3 + is-regex: ^1.1.4 + is-shared-array-buffer: ^1.0.3 + is-string: ^1.0.7 + is-typed-array: ^1.1.13 + is-weakref: ^1.0.2 + object-inspect: ^1.13.1 + object-keys: ^1.1.1 + object.assign: ^4.1.5 + regexp.prototype.flags: ^1.5.2 + safe-array-concat: ^1.1.2 + safe-regex-test: ^1.0.3 + string.prototype.trim: ^1.2.9 + string.prototype.trimend: ^1.0.8 + string.prototype.trimstart: ^1.0.8 + typed-array-buffer: ^1.0.2 + typed-array-byte-length: ^1.0.1 + typed-array-byte-offset: ^1.0.2 + typed-array-length: ^1.0.6 + unbox-primitive: ^1.0.2 + which-typed-array: ^1.1.15 + checksum: f840cf161224252512f9527306b57117192696571e07920f777cb893454e32999206198b4f075516112af6459daca282826d1735c450528470356d09eff3a9ae + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.0": + version: 1.0.0 + resolution: "es-define-property@npm:1.0.0" + dependencies: + get-intrinsic: ^1.2.4 + checksum: f66ece0a887b6dca71848fa71f70461357c0e4e7249696f81bad0a1f347eed7b31262af4a29f5d726dc026426f085483b6b90301855e647aa8e21936f07293c6 + languageName: node + linkType: hard + +"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 + languageName: node + linkType: hard + +"es-module-lexer@npm:^1.2.1": + version: 1.5.4 + resolution: "es-module-lexer@npm:1.5.4" + checksum: a0cf04fb92d052647ac7d818d1913b98d3d3d0f5b9d88f0eafb993436e4c3e2c958599db68839d57f2dfa281fdf0f60e18d448eb78fc292c33c0f25635b6854f + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0": + version: 1.0.0 + resolution: "es-object-atoms@npm:1.0.0" + dependencies: + es-errors: ^1.3.0 + checksum: 26f0ff78ab93b63394e8403c353842b2272836968de4eafe97656adfb8a7c84b9099bf0fe96ed58f4a4cddc860f6e34c77f91649a58a5daa4a9c40b902744e3c + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.3": + version: 2.0.3 + resolution: "es-set-tostringtag@npm:2.0.3" + dependencies: + get-intrinsic: ^1.2.4 + has-tostringtag: ^1.0.2 + hasown: ^2.0.1 + checksum: 7227fa48a41c0ce83e0377b11130d324ac797390688135b8da5c28994c0165be8b252e15cd1de41e1325e5a5412511586960213e88f9ab4a5e7d028895db5129 + languageName: node + linkType: hard + +"es-to-primitive@npm:^1.2.1": + version: 1.2.1 + resolution: "es-to-primitive@npm:1.2.1" + dependencies: + is-callable: ^1.1.4 + is-date-object: ^1.0.1 + is-symbol: ^1.0.2 + checksum: 4ead6671a2c1402619bdd77f3503991232ca15e17e46222b0a41a5d81aebc8740a77822f5b3c965008e631153e9ef0580540007744521e72de8e33599fca2eed + languageName: node + linkType: hard + +"escalade@npm:^3.1.1, escalade@npm:^3.1.2": + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 1ec0977aa2772075493002bdbd549d595ff6e9393b1cb0d7d6fcaf78c750da0c158f180938365486f75cb69fba20294351caddfce1b46552a7b6c3cde52eaa02 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^1.0.5": + version: 1.0.5 + resolution: "escape-string-regexp@npm:1.0.5" + checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^2.0.0": + version: 2.0.0 + resolution: "escape-string-regexp@npm:2.0.0" + checksum: 9f8a2d5743677c16e85c810e3024d54f0c8dea6424fad3c79ef6666e81dd0846f7437f5e729dfcdac8981bc9e5294c39b4580814d114076b8d36318f46ae4395 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 + languageName: node + linkType: hard + +"eslint-config-prettier@npm:^9.1.0": + version: 9.1.0 + resolution: "eslint-config-prettier@npm:9.1.0" + peerDependencies: + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 9229b768c879f500ee54ca05925f31b0c0bafff3d9f5521f98ff05127356de78c81deb9365c86a5ec4efa990cb72b74df8612ae15965b14136044c73e1f6a907 + languageName: node + linkType: hard + +"eslint-plugin-prettier@npm:^5.1.3": + version: 5.2.1 + resolution: "eslint-plugin-prettier@npm:5.2.1" + dependencies: + prettier-linter-helpers: ^1.0.0 + synckit: ^0.9.1 + peerDependencies: + "@types/eslint": ">=8.0.0" + eslint: ">=8.0.0" + eslint-config-prettier: "*" + prettier: ">=3.0.0" + peerDependenciesMeta: + "@types/eslint": + optional: true + eslint-config-prettier: + optional: true + checksum: 812f4d1596dcd3a55963212dfbd818a4b38f880741aac75f6869aa740dc5d934060674d3b85d10ff9fec424defa61967dbdef26b8a893a92c9b51880264ed0d9 + languageName: node + linkType: hard + +"eslint-scope@npm:5.1.1": + version: 5.1.1 + resolution: "eslint-scope@npm:5.1.1" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^4.1.1 + checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb + languageName: node + linkType: hard + +"eslint-scope@npm:^7.2.2": + version: 7.2.2 + resolution: "eslint-scope@npm:7.2.2" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^5.2.0 + checksum: ec97dbf5fb04b94e8f4c5a91a7f0a6dd3c55e46bfc7bbcd0e3138c3a76977570e02ed89a1810c778dcd72072ff0e9621ba1379b4babe53921d71e2e4486fda3e + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" + checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 + languageName: node + linkType: hard + +"eslint@npm:^8.56.0": + version: 8.57.0 + resolution: "eslint@npm:8.57.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.6.1 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.57.0 + "@humanwhocodes/config-array": ^0.11.14 + "@humanwhocodes/module-importer": ^1.0.1 + "@nodelib/fs.walk": ^1.2.8 + "@ungap/structured-clone": ^1.2.0 + ajv: ^6.12.4 + chalk: ^4.0.0 + cross-spawn: ^7.0.2 + debug: ^4.3.2 + doctrine: ^3.0.0 + escape-string-regexp: ^4.0.0 + eslint-scope: ^7.2.2 + eslint-visitor-keys: ^3.4.3 + espree: ^9.6.1 + esquery: ^1.4.2 + esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 + file-entry-cache: ^6.0.1 + find-up: ^5.0.0 + glob-parent: ^6.0.2 + globals: ^13.19.0 + graphemer: ^1.4.0 + ignore: ^5.2.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + is-path-inside: ^3.0.3 + js-yaml: ^4.1.0 + json-stable-stringify-without-jsonify: ^1.0.1 + levn: ^0.4.1 + lodash.merge: ^4.6.2 + minimatch: ^3.1.2 + natural-compare: ^1.4.0 + optionator: ^0.9.3 + strip-ansi: ^6.0.1 + text-table: ^0.2.0 + bin: + eslint: bin/eslint.js + checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 + languageName: node + linkType: hard + +"espree@npm:^9.6.0, espree@npm:^9.6.1": + version: 9.6.1 + resolution: "espree@npm:9.6.1" + dependencies: + acorn: ^8.9.0 + acorn-jsx: ^5.3.2 + eslint-visitor-keys: ^3.4.1 + checksum: eb8c149c7a2a77b3f33a5af80c10875c3abd65450f60b8af6db1bfcfa8f101e21c1e56a561c6dc13b848e18148d43469e7cd208506238554fb5395a9ea5a1ab9 + languageName: node + linkType: hard + +"esprima@npm:^4.0.0": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 + languageName: node + linkType: hard + +"esquery@npm:^1.4.2": + version: 1.6.0 + resolution: "esquery@npm:1.6.0" + dependencies: + estraverse: ^5.1.0 + checksum: 08ec4fe446d9ab27186da274d979558557fbdbbd10968fa9758552482720c54152a5640e08b9009e5a30706b66aba510692054d4129d32d0e12e05bbc0b96fb2 + languageName: node + linkType: hard + +"esrecurse@npm:^4.3.0": + version: 4.3.0 + resolution: "esrecurse@npm:4.3.0" + dependencies: + estraverse: ^5.2.0 + checksum: ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 + languageName: node + linkType: hard + +"estraverse@npm:^4.1.1": + version: 4.3.0 + resolution: "estraverse@npm:4.3.0" + checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 + languageName: node + linkType: hard + +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0": + version: 5.3.0 + resolution: "estraverse@npm:5.3.0" + checksum: 072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b + languageName: node + linkType: hard + +"esutils@npm:^2.0.2": + version: 2.0.3 + resolution: "esutils@npm:2.0.3" + checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 + languageName: node + linkType: hard + +"events@npm:^3.2.0": + version: 3.3.0 + resolution: "events@npm:3.3.0" + checksum: f6f487ad2198aa41d878fa31452f1a3c00958f46e9019286ff4787c84aac329332ab45c9cdc8c445928fc6d7ded294b9e005a7fce9426488518017831b272780 + 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" + checksum: abc407f07a875c3961e4781dfcb743b58d6c93de9ab263f4f8c9d23bb6da5f9b7764fc773f86b43dd88030444d5ab8abcb611cb680fba8ca075362b77114bba3 + languageName: node + linkType: hard + +"expect@npm:^29.0.0, expect@npm:^29.7.0": + version: 29.7.0 + resolution: "expect@npm:29.7.0" + dependencies: + "@jest/expect-utils": ^29.7.0 + jest-get-type: ^29.6.3 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + checksum: 9257f10288e149b81254a0fda8ffe8d54a7061cd61d7515779998b012579d2b8c22354b0eb901daf0145f347403da582f75f359f4810c007182ad3fb318b5c0c + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 3d21519a4f8207c99f7457287291316306255a328770d320b401114ec8481986e4e467e854cb9914dd965e0a1ca810a23ccb559c642c88f4c7f55c55778a9b48 + languageName: node + linkType: hard + +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": + version: 3.1.3 + resolution: "fast-deep-equal@npm:3.1.3" + checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d + languageName: node + linkType: hard + +"fast-diff@npm:^1.1.2": + version: 1.3.0 + resolution: "fast-diff@npm:1.3.0" + checksum: d22d371b994fdc8cce9ff510d7b8dc4da70ac327bcba20df607dd5b9cae9f908f4d1028f5fe467650f058d1e7270235ae0b8230809a262b4df587a3b3aa216c3 + languageName: node + linkType: hard + +"fast-glob@npm:^3.2.9": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" + dependencies: + "@nodelib/fs.stat": ^2.0.2 + "@nodelib/fs.walk": ^1.2.3 + glob-parent: ^5.1.2 + merge2: ^1.3.0 + micromatch: ^4.0.4 + checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 + languageName: node + linkType: hard + +"fast-json-stable-stringify@npm:2.x, fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": + version: 2.1.0 + resolution: "fast-json-stable-stringify@npm:2.1.0" + checksum: b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb + languageName: node + linkType: hard + +"fast-levenshtein@npm:^2.0.6": + version: 2.0.6 + resolution: "fast-levenshtein@npm:2.0.6" + checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c + languageName: node + linkType: hard + +"fast-uri@npm:^3.0.1": + version: 3.0.1 + resolution: "fast-uri@npm:3.0.1" + checksum: 106143ff83705995225dcc559411288f3337e732bb2e264e79788f1914b6bd8f8bc3683102de60b15ba00e6ebb443633cabac77d4ebc5cb228c47cf955e199ff + languageName: node + linkType: hard + +"fastest-levenshtein@npm:^1.0.12": + version: 1.0.16 + resolution: "fastest-levenshtein@npm:1.0.16" + checksum: a78d44285c9e2ae2c25f3ef0f8a73f332c1247b7ea7fb4a191e6bb51aa6ee1ef0dfb3ed113616dcdc7023e18e35a8db41f61c8d88988e877cf510df8edafbc71 + languageName: node + linkType: hard + +"fastq@npm:^1.6.0": + version: 1.17.1 + resolution: "fastq@npm:1.17.1" + dependencies: + reusify: ^1.0.4 + checksum: a8c5b26788d5a1763f88bae56a8ddeee579f935a831c5fe7a8268cea5b0a91fbfe705f612209e02d639b881d7b48e461a50da4a10cfaa40da5ca7cc9da098d88 + languageName: node + linkType: hard + +"fb-watchman@npm:^2.0.0": + version: 2.0.2 + resolution: "fb-watchman@npm:2.0.2" + dependencies: + bser: 2.1.1 + checksum: b15a124cef28916fe07b400eb87cbc73ca082c142abf7ca8e8de6af43eca79ca7bd13eb4d4d48240b3bd3136eaac40d16e42d6edf87a8e5d1dd8070626860c78 + languageName: node + linkType: hard + +"file-entry-cache@npm:^6.0.1": + version: 6.0.1 + resolution: "file-entry-cache@npm:6.0.1" + dependencies: + flat-cache: ^3.0.4 + checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 + languageName: node + linkType: hard + +"filelist@npm:^1.0.4": + version: 1.0.4 + resolution: "filelist@npm:1.0.4" + dependencies: + minimatch: ^5.0.1 + checksum: a303573b0821e17f2d5e9783688ab6fbfce5d52aaac842790ae85e704a6f5e4e3538660a63183d6453834dedf1e0f19a9dadcebfa3e926c72397694ea11f5160 + languageName: node + linkType: hard + +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" + dependencies: + to-regex-range: ^5.0.1 + checksum: b4abfbca3839a3d55e4ae5ec62e131e2e356bf4859ce8480c64c4876100f4df292a63e5bb1618e1d7460282ca2b305653064f01654474aa35c68000980f17798 + languageName: node + linkType: hard + +"find-root@npm:^1.0.0": + version: 1.1.0 + resolution: "find-root@npm:1.1.0" + checksum: b2a59fe4b6c932eef36c45a048ae8f93c85640212ebe8363164814990ee20f154197505965f3f4f102efc33bfb1cbc26fd17c4a2fc739ebc51b886b137cbefaf + languageName: node + linkType: hard + +"find-up@npm:^4.0.0, find-up@npm:^4.1.0": + version: 4.1.0 + resolution: "find-up@npm:4.1.0" + dependencies: + locate-path: ^5.0.0 + path-exists: ^4.0.0 + checksum: 4c172680e8f8c1f78839486e14a43ef82e9decd0e74145f40707cc42e7420506d5ec92d9a11c22bd2c48fb0c384ea05dd30e10dd152fefeec6f2f75282a8b844 + languageName: node + linkType: hard + +"find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: ^6.0.0 + path-exists: ^4.0.0 + checksum: 07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 + languageName: node + linkType: hard + +"flat-cache@npm:^3.0.4": + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" + dependencies: + flatted: ^3.2.9 + keyv: ^4.5.3 + rimraf: ^3.0.2 + checksum: e7e0f59801e288b54bee5cb9681e9ee21ee28ef309f886b312c9d08415b79fc0f24ac842f84356ce80f47d6a53de62197ce0e6e148dc42d5db005992e2a756ec + languageName: node + linkType: hard + +"flat@npm:^5.0.2": + version: 5.0.2 + resolution: "flat@npm:5.0.2" + bin: + flat: cli.js + checksum: 12a1536ac746db74881316a181499a78ef953632ddd28050b7a3a43c62ef5462e3357c8c29d76072bb635f147f7a9a1f0c02efef6b4be28f8db62ceb3d5c7f5d + languageName: node + linkType: hard + +"flatted@npm:^3.2.9": + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 85ae7181650bb728c221e7644cbc9f4bf28bc556f2fc89bb21266962bdf0ce1029cc7acc44bb646cd469d9baac7c317f64e841c4c4c00516afa97320cdac7f94 + languageName: node + linkType: hard + +"for-each@npm:^0.3.3": + version: 0.3.3 + resolution: "for-each@npm:0.3.3" + dependencies: + is-callable: ^1.1.3 + checksum: 6c48ff2bc63362319c65e2edca4a8e1e3483a2fabc72fbe7feaf8c73db94fc7861bd53bc02c8a66a0c1dd709da6b04eec42e0abdd6b40ce47305ae92a25e5d28 + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.3.0 + resolution: "foreground-child@npm:3.3.0" + dependencies: + cross-spawn: ^7.0.0 + signal-exit: ^4.0.1 + checksum: 1989698488f725b05b26bc9afc8a08f08ec41807cd7b92ad85d96004ddf8243fd3e79486b8348c64a3011ae5cc2c9f0936af989e1f28339805d8bc178a75b451 + languageName: node + linkType: hard + +"fs-extra@npm:^10.1.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: dc94ab37096f813cc3ca12f0f1b5ad6744dfed9ed21e953d72530d103cea193c2f81584a39e9dee1bea36de5ee66805678c0dddc048e8af1427ac19c00fffc50 + languageName: node + linkType: hard + +"fs-extra@npm:^11.2.0": + version: 11.2.0 + resolution: "fs-extra@npm:11.2.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: b12e42fa40ba47104202f57b8480dd098aa931c2724565e5e70779ab87605665594e76ee5fb00545f772ab9ace167fe06d2ab009c416dc8c842c5ae6df7aa7e8 + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: ^3.0.0 + checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: ^7.0.3 + checksum: 8722a41109130851d979222d3ec88aabaceeaaf8f57b2a8f744ef8bd2d1ce95453b04a61daa0078822bc5cd21e008814f06fe6586f56fef511e71b8d2394d802 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 + languageName: node + linkType: hard + +"fsevents@npm:^2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@^2.3.2#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1 + languageName: node + linkType: hard + +"function.prototype.name@npm:^1.1.6": + version: 1.1.6 + resolution: "function.prototype.name@npm:1.1.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + functions-have-names: ^1.2.3 + checksum: 7a3f9bd98adab09a07f6e1f03da03d3f7c26abbdeaeee15223f6c04a9fb5674792bdf5e689dac19b97ac71de6aad2027ba3048a9b883aa1b3173eed6ab07f479 + languageName: node + linkType: hard + +"functions-have-names@npm:^1.2.3": + version: 1.2.3 + resolution: "functions-have-names@npm:1.2.3" + checksum: c3f1f5ba20f4e962efb71344ce0a40722163e85bee2101ce25f88214e78182d2d2476aa85ef37950c579eb6cf6ee811c17b3101bb84004bb75655f3e33f3fdb5 + languageName: node + linkType: hard + +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: a7437e58c6be12aa6c90f7730eac7fa9833dc78872b4ad2963d2031b00a3367a93f98aec75f9aaac7220848e4026d67a8655e870b24f20a543d103c0d65952ec + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": + version: 1.2.4 + resolution: "get-intrinsic@npm:1.2.4" + dependencies: + es-errors: ^1.3.0 + function-bind: ^1.1.2 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + hasown: ^2.0.0 + checksum: 414e3cdf2c203d1b9d7d33111df746a4512a1aa622770b361dadddf8ed0b5aeb26c560f49ca077e24bfafb0acb55ca908d1f709216ccba33ffc548ec8a79a951 + languageName: node + linkType: hard + +"get-package-type@npm:^0.1.0": + version: 0.1.0 + resolution: "get-package-type@npm:0.1.0" + checksum: bba0811116d11e56d702682ddef7c73ba3481f114590e705fc549f4d868972263896af313c57a25c076e3c0d567e11d919a64ba1b30c879be985fc9d44f96148 + 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.2": + version: 1.0.2 + resolution: "get-symbol-description@npm:1.0.2" + dependencies: + call-bind: ^1.0.5 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + checksum: e1cb53bc211f9dbe9691a4f97a46837a553c4e7caadd0488dc24ac694db8a390b93edd412b48dcdd0b4bbb4c595de1709effc75fc87c0839deedc6968f5bd973 + languageName: node + linkType: hard + +"glob-parent@npm:^5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: ^4.0.1 + checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e + languageName: node + linkType: hard + +"glob-parent@npm:^6.0.2": + version: 6.0.2 + resolution: "glob-parent@npm:6.0.2" + dependencies: + is-glob: ^4.0.3 + checksum: c13ee97978bef4f55106b71e66428eb1512e71a7466ba49025fc2aec59a5bfb0954d5abd58fc5ee6c9b076eef4e1f6d3375c2e964b88466ca390da4419a786a8 + languageName: node + linkType: hard + +"glob-to-regexp@npm:^0.4.1": + version: 0.4.1 + resolution: "glob-to-regexp@npm:0.4.1" + checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167 + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": + version: 10.4.5 + resolution: "glob@npm:10.4.5" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^3.1.2 + minimatch: ^9.0.4 + minipass: ^7.1.2 + package-json-from-dist: ^1.0.0 + path-scurry: ^1.11.1 + bin: + glob: dist/esm/bin.mjs + checksum: 0bc725de5e4862f9f387fd0f2b274baf16850dcd2714502ccf471ee401803997983e2c05590cb65f9675a3c6f2a58e7a53f9e365704108c6ad3cbf1d60934c4a + languageName: node + linkType: hard + +"glob@npm:^7.1.3, glob@npm:^7.1.4": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^3.1.1 + once: ^1.3.0 + path-is-absolute: ^1.0.0 + checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 + 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 + +"globals@npm:^11.1.0": + version: 11.12.0 + resolution: "globals@npm:11.12.0" + checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e + languageName: node + linkType: hard + +"globals@npm:^13.19.0": + version: 13.24.0 + resolution: "globals@npm:13.24.0" + dependencies: + type-fest: ^0.20.2 + checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c + languageName: node + linkType: hard + +"globalthis@npm:^1.0.3": + version: 1.0.4 + resolution: "globalthis@npm:1.0.4" + dependencies: + define-properties: ^1.2.1 + gopd: ^1.0.1 + checksum: 39ad667ad9f01476474633a1834a70842041f70a55571e8dcef5fb957980a92da5022db5430fca8aecc5d47704ae30618c0bc877a579c70710c904e9ef06108a + languageName: node + linkType: hard + +"globby@npm:^11.1.0": + version: 11.1.0 + resolution: "globby@npm:11.1.0" + dependencies: + array-union: ^2.1.0 + dir-glob: ^3.0.1 + fast-glob: ^3.2.9 + ignore: ^5.2.0 + merge2: ^1.4.1 + slash: ^3.0.0 + checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 + languageName: node + linkType: hard + +"gopd@npm:^1.0.1": + version: 1.0.1 + resolution: "gopd@npm:1.0.1" + dependencies: + get-intrinsic: ^1.1.3 + checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, 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 + +"graphemer@npm:^1.4.0": + version: 1.4.0 + resolution: "graphemer@npm:1.4.0" + checksum: bab8f0be9b568857c7bec9fda95a89f87b783546d02951c40c33f84d05bb7da3fd10f863a9beb901463669b6583173a8c8cc6d6b306ea2b9b9d5d3d943c3a673 + languageName: node + linkType: hard + +"harmony-reflect@npm:^1.4.6": + version: 1.6.2 + resolution: "harmony-reflect@npm:1.6.2" + checksum: 2e5bae414cd2bfae5476147f9935dc69ee9b9a413206994dcb94c5b3208d4555da3d4313aff6fd14bd9991c1e3ef69cdda5c8fac1eb1d7afc064925839339b8c + languageName: node + linkType: hard + +"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": + version: 1.0.2 + resolution: "has-bigints@npm:1.0.2" + checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b + languageName: node + linkType: hard + +"has-flag@npm:^3.0.0": + version: 3.0.0 + resolution: "has-flag@npm:3.0.0" + checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b + languageName: node + linkType: hard + +"has-flag@npm:^4.0.0": + version: 4.0.0 + resolution: "has-flag@npm:4.0.0" + checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad + languageName: node + linkType: hard + +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" + dependencies: + es-define-property: ^1.0.0 + checksum: fcbb246ea2838058be39887935231c6d5788babed499d0e9d0cc5737494c48aba4fe17ba1449e0d0fbbb1e36175442faa37f9c427ae357d6ccb1d895fbcd3de3 + languageName: node + linkType: hard + +"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: fe7c3d50b33f50f3933a04413ed1f69441d21d2d2944f81036276d30635cad9279f6b43bc8f32036c31ebdfcf6e731150f46c1907ad90c669ffe9b066c3ba5c4 + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": + version: 1.0.3 + resolution: "has-symbols@npm:1.0.3" + checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" + dependencies: + has-symbols: ^1.0.3 + checksum: 999d60bb753ad714356b2c6c87b7fb74f32463b8426e159397da4bde5bca7e598ab1073f4d8d4deafac297f2eb311484cd177af242776bf05f0d11565680468d + languageName: node + linkType: hard + +"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": + version: 2.0.2 + resolution: "hasown@npm:2.0.2" + dependencies: + function-bind: ^1.1.2 + checksum: e8516f776a15149ca6c6ed2ae3110c417a00b62260e222590e54aa367cbcd6ed99122020b37b7fbdf05748df57b265e70095d7bf35a47660587619b15ffb93db + languageName: node + linkType: hard + +"hosted-git-info@npm:^2.1.4": + version: 2.8.9 + resolution: "hosted-git-info@npm:2.8.9" + checksum: c955394bdab888a1e9bb10eb33029e0f7ce5a2ac7b3f158099dc8c486c99e73809dca609f5694b223920ca2174db33d32b12f9a2a47141dc59607c29da5a62dd + languageName: node + linkType: hard + +"html-escaper@npm:^2.0.0": + version: 2.0.2 + resolution: "html-escaper@npm:2.0.2" + checksum: d2df2da3ad40ca9ee3a39c5cc6475ef67c8f83c234475f24d8e9ce0dc80a2c82df8e1d6fa78ddd1e9022a586ea1bd247a615e80a5cd9273d90111ddda7d9e974 + languageName: node + linkType: hard + +"htmlparser2@npm:^8.0.0": + version: 8.0.2 + resolution: "htmlparser2@npm:8.0.2" + dependencies: + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + domutils: ^3.0.1 + entities: ^4.4.0 + checksum: 29167a0f9282f181da8a6d0311b76820c8a59bc9e3c87009e21968264c2987d2723d6fde5a964d4b7b6cba663fca96ffb373c06d8223a85f52a6089ced942700 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: ^7.1.0 + debug: ^4.3.4 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" + dependencies: + agent-base: ^7.0.2 + debug: 4 + checksum: 2e1a28960f13b041a50702ee74f240add8e75146a5c37fc98f1960f0496710f6918b3a9fe1e5aba41e50f58e6df48d107edd9c405c5f0d73ac260dabf2210857 + languageName: node + linkType: hard + +"human-signals@npm:^2.1.0": + version: 2.1.0 + resolution: "human-signals@npm:2.1.0" + checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: ">= 2.1.2 < 3.0.0" + checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf + languageName: node + linkType: hard + +"icss-utils@npm:^5.0.0, icss-utils@npm:^5.1.0": + version: 5.1.0 + resolution: "icss-utils@npm:5.1.0" + peerDependencies: + postcss: ^8.1.0 + checksum: 5c324d283552b1269cfc13a503aaaa172a280f914e5b81544f3803bc6f06a3b585fb79f66f7c771a2c052db7982c18bf92d001e3b47282e3abbbb4c4cc488d68 + languageName: node + linkType: hard + +"identity-obj-proxy@npm:^3.0.0": + version: 3.0.0 + resolution: "identity-obj-proxy@npm:3.0.0" + dependencies: + harmony-reflect: ^1.4.6 + checksum: 97559f8ea2aeaa1a880d279d8c49550dce01148321e00a2102cda5ddf9ce622fa1d7f3efc7bed63458af78889de888fdaebaf31c816312298bb3fdd0ef8aaf2c + languageName: node + linkType: hard + +"ignore@npm:^5.2.0, ignore@npm:^5.2.4": + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 2acfd32a573260ea522ea0bfeff880af426d68f6831f973129e2ba7363f422923cf53aab62f8369cbf4667c7b25b6f8a3761b34ecdb284ea18e87a5262a865be + languageName: node + linkType: hard + +"import-fresh@npm:^3.2.1": + version: 3.3.0 + resolution: "import-fresh@npm:3.3.0" + dependencies: + parent-module: ^1.0.0 + resolve-from: ^4.0.0 + checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + languageName: node + linkType: hard + +"import-local@npm:^3.0.2": + version: 3.2.0 + resolution: "import-local@npm:3.2.0" + dependencies: + pkg-dir: ^4.2.0 + resolve-cwd: ^3.0.0 + bin: + import-local-fixture: fixtures/cli.js + checksum: 0b0b0b412b2521739fbb85eeed834a3c34de9bc67e670b3d0b86248fc460d990a7b116ad056c084b87a693ef73d1f17268d6a5be626bb43c998a8b1c8a230004 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: ^1.3.0 + wrappy: 1 + checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd + languageName: node + linkType: hard + +"inherits@npm:2": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 + languageName: node + linkType: hard + +"internal-slot@npm:^1.0.7": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" + dependencies: + es-errors: ^1.3.0 + hasown: ^2.0.0 + side-channel: ^1.0.4 + checksum: cadc5eea5d7d9bc2342e93aae9f31f04c196afebb11bde97448327049f492cd7081e18623ae71388aac9cd237b692ca3a105be9c68ac39c1dec679d7409e33eb + languageName: node + linkType: hard + +"interpret@npm:^3.1.1": + version: 3.1.1 + resolution: "interpret@npm:3.1.1" + checksum: 35cebcf48c7351130437596d9ab8c8fe131ce4038da4561e6d665f25640e0034702a031cf7e3a5cea60ac7ac548bf17465e0571ede126f3d3a6933152171ac82 + languageName: node + linkType: hard + +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: 1.1.0 + sprintf-js: ^1.1.3 + checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc + languageName: node + linkType: hard + +"is-array-buffer@npm:^3.0.4": + version: 3.0.4 + resolution: "is-array-buffer@npm:3.0.4" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.1 + checksum: e4e3e6ef0ff2239e75371d221f74bc3c26a03564a22efb39f6bb02609b598917ddeecef4e8c877df2a25888f247a98198959842a5e73236bc7f22cabdf6351a7 + languageName: node + linkType: hard + +"is-arrayish@npm:^0.2.1": + version: 0.2.1 + resolution: "is-arrayish@npm:0.2.1" + checksum: eef4417e3c10e60e2c810b6084942b3ead455af16c4509959a27e490e7aee87cfb3f38e01bbde92220b528a0ee1a18d52b787e1458ee86174d8c7f0e58cd488f + languageName: node + linkType: hard + +"is-bigint@npm:^1.0.1": + version: 1.0.4 + resolution: "is-bigint@npm:1.0.4" + dependencies: + has-bigints: ^1.0.1 + checksum: c56edfe09b1154f8668e53ebe8252b6f185ee852a50f9b41e8d921cb2bed425652049fbe438723f6cb48a63ca1aa051e948e7e401e093477c99c84eba244f666 + languageName: node + linkType: hard + +"is-boolean-object@npm:^1.1.0": + version: 1.1.2 + resolution: "is-boolean-object@npm:1.1.2" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 + languageName: node + linkType: hard + +"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac + languageName: node + linkType: hard + +"is-core-module@npm:^2.13.0": + version: 2.15.0 + resolution: "is-core-module@npm:2.15.0" + dependencies: + hasown: ^2.0.2 + checksum: a9f7a52707c9b59d7164094d183bda892514fc3ba3139f245219c7abe7f6e8d3e2cdcf861f52a891a467f785f1dfa5d549f73b0ee715f4ba56e8882d335ea585 + languageName: node + linkType: hard + +"is-data-view@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-view@npm:1.0.1" + dependencies: + is-typed-array: ^1.1.13 + checksum: 4ba4562ac2b2ec005fefe48269d6bd0152785458cd253c746154ffb8a8ab506a29d0cfb3b74af87513843776a88e4981ae25c89457bf640a33748eab1a7216b5 + languageName: node + linkType: hard + +"is-date-object@npm:^1.0.1": + version: 1.0.5 + resolution: "is-date-object@npm:1.0.5" + dependencies: + has-tostringtag: ^1.0.0 + checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 + languageName: node + linkType: hard + +"is-generator-fn@npm:^2.0.0": + version: 2.1.0 + resolution: "is-generator-fn@npm:2.1.0" + checksum: a6ad5492cf9d1746f73b6744e0c43c0020510b59d56ddcb78a91cbc173f09b5e6beff53d75c9c5a29feb618bfef2bf458e025ecf3a57ad2268e2fb2569f56215 + languageName: node + linkType: hard + +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: ^2.1.1 + checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 + languageName: node + linkType: hard + +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: c1e6b23d2070c0539d7b36022d5a94407132411d01aba39ec549af824231f3804b1aea90b5e4e58e807a65d23ceb538ed6e355ce76b267bdd86edb757ffcbdcd + languageName: node + linkType: hard + +"is-number-object@npm:^1.0.4": + version: 1.0.7 + resolution: "is-number-object@npm:1.0.7" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a + languageName: node + linkType: hard + +"is-path-inside@npm:^3.0.3": + version: 3.0.3 + resolution: "is-path-inside@npm:3.0.3" + checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 + languageName: node + linkType: hard + +"is-plain-object@npm:^2.0.4": + version: 2.0.4 + resolution: "is-plain-object@npm:2.0.4" + dependencies: + isobject: ^3.0.1 + checksum: 2a401140cfd86cabe25214956ae2cfee6fbd8186809555cd0e84574f88de7b17abacb2e477a6a658fa54c6083ecbda1e6ae404c7720244cd198903848fca70ca + languageName: node + linkType: hard + +"is-plain-object@npm:^5.0.0": + version: 5.0.0 + resolution: "is-plain-object@npm:5.0.0" + checksum: e32d27061eef62c0847d303125440a38660517e586f2f3db7c9d179ae5b6674ab0f469d519b2e25c147a1a3bc87156d0d5f4d8821e0ce4a9ee7fe1fcf11ce45c + languageName: node + linkType: hard + +"is-regex@npm:^1.1.4": + version: 1.1.4 + resolution: "is-regex@npm:1.1.4" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 + languageName: node + linkType: hard + +"is-shared-array-buffer@npm:^1.0.2, is-shared-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" + dependencies: + call-bind: ^1.0.7 + checksum: a4fff602c309e64ccaa83b859255a43bb011145a42d3f56f67d9268b55bc7e6d98a5981a1d834186ad3105d6739d21547083fe7259c76c0468483fc538e716d8 + 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" + dependencies: + has-tostringtag: ^1.0.0 + checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 + languageName: node + linkType: hard + +"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": + version: 1.0.4 + resolution: "is-symbol@npm:1.0.4" + dependencies: + has-symbols: ^1.0.2 + checksum: 92805812ef590738d9de49d677cd17dfd486794773fb6fa0032d16452af46e9b91bb43ffe82c983570f015b37136f4b53b28b8523bfb10b0ece7a66c31a54510 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.13": + version: 1.1.13 + resolution: "is-typed-array@npm:1.1.13" + dependencies: + which-typed-array: ^1.1.14 + checksum: 150f9ada183a61554c91e1c4290086d2c100b0dff45f60b028519be72a8db964da403c48760723bf5253979b8dffe7b544246e0e5351dcd05c5fdb1dcc1dc0f0 + languageName: node + linkType: hard + +"is-weakref@npm:^1.0.2": + version: 1.0.2 + resolution: "is-weakref@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + checksum: 95bd9a57cdcb58c63b1c401c60a474b0f45b94719c30f548c891860f051bc2231575c290a6b420c6bc6e7ed99459d424c652bd5bf9a1d5259505dc35b4bf83de + languageName: node + linkType: hard + +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: bd5bbe4104438c4196ba58a54650116007fa0262eccef13a4c55b2e09a5b36b59f1e75b9fcc49883dd9d4953892e6fc007eef9e9155648ceea036e184b0f930a + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + +"isobject@npm:^3.0.1": + version: 3.0.1 + resolution: "isobject@npm:3.0.1" + checksum: db85c4c970ce30693676487cca0e61da2ca34e8d4967c2e1309143ff910c207133a969f9e4ddb2dc6aba670aabce4e0e307146c310350b298e74a31f7d464703 + languageName: node + linkType: hard + +"isomorphic.js@npm:^0.2.4": + version: 0.2.5 + resolution: "isomorphic.js@npm:0.2.5" + checksum: d8d1b083f05f3c337a06628b982ac3ce6db953bbef14a9de8ad49131250c3592f864b73c12030fdc9ef138ce97b76ef55c7d96a849561ac215b1b4b9d301c8e9 + languageName: node + linkType: hard + +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 2367407a8d13982d8f7a859a35e7f8dd5d8f75aae4bb5484ede3a9ea1b426dc245aff28b976a2af48ee759fdd9be374ce2bd2669b644f31e76c5f46a2e29a831 + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^5.0.4": + version: 5.2.1 + resolution: "istanbul-lib-instrument@npm:5.2.1" + dependencies: + "@babel/core": ^7.12.3 + "@babel/parser": ^7.14.7 + "@istanbuljs/schema": ^0.1.2 + istanbul-lib-coverage: ^3.2.0 + semver: ^6.3.0 + checksum: bf16f1803ba5e51b28bbd49ed955a736488381e09375d830e42ddeb403855b2006f850711d95ad726f2ba3f1ae8e7366de7e51d2b9ac67dc4d80191ef7ddf272 + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^6.0.0": + version: 6.0.3 + resolution: "istanbul-lib-instrument@npm:6.0.3" + dependencies: + "@babel/core": ^7.23.9 + "@babel/parser": ^7.23.9 + "@istanbuljs/schema": ^0.1.3 + istanbul-lib-coverage: ^3.2.0 + semver: ^7.5.4 + checksum: 74104c60c65c4fa0e97cc76f039226c356123893929f067bfad5f86fe839e08f5d680354a68fead3bc9c1e2f3fa6f3f53cded70778e821d911e851d349f3545a + languageName: node + linkType: hard + +"istanbul-lib-report@npm:^3.0.0": + version: 3.0.1 + resolution: "istanbul-lib-report@npm:3.0.1" + dependencies: + istanbul-lib-coverage: ^3.0.0 + make-dir: ^4.0.0 + supports-color: ^7.1.0 + checksum: fd17a1b879e7faf9bb1dc8f80b2a16e9f5b7b8498fe6ed580a618c34df0bfe53d2abd35bf8a0a00e628fb7405462576427c7df20bbe4148d19c14b431c974b21 + languageName: node + linkType: hard + +"istanbul-lib-source-maps@npm:^4.0.0": + version: 4.0.1 + resolution: "istanbul-lib-source-maps@npm:4.0.1" + dependencies: + debug: ^4.1.1 + istanbul-lib-coverage: ^3.0.0 + source-map: ^0.6.1 + checksum: 21ad3df45db4b81852b662b8d4161f6446cd250c1ddc70ef96a585e2e85c26ed7cd9c2a396a71533cfb981d1a645508bc9618cae431e55d01a0628e7dec62ef2 + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.1.3": + version: 3.1.7 + resolution: "istanbul-reports@npm:3.1.7" + dependencies: + html-escaper: ^2.0.0 + istanbul-lib-report: ^3.0.0 + checksum: 2072db6e07bfbb4d0eb30e2700250636182398c1af811aea5032acb219d2080f7586923c09fa194029efd6b92361afb3dcbe1ebcc3ee6651d13340f7c6c4ed95 + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: be31027fc72e7cc726206b9f560395604b82e0fddb46c4cbf9f97d049bcef607491a5afc0699612eaa4213ca5be8fd3e1e7cd187b3040988b65c9489838a7c00 + languageName: node + linkType: hard + +"jake@npm:^10.8.5": + version: 10.9.2 + resolution: "jake@npm:10.9.2" + dependencies: + async: ^3.2.3 + chalk: ^4.0.2 + filelist: ^1.0.4 + minimatch: ^3.1.2 + bin: + jake: bin/cli.js + checksum: f2dc4a086b4f58446d02cb9be913c39710d9ea570218d7681bb861f7eeaecab7b458256c946aeaa7e548c5e0686cc293e6435501e4047174a3b6a504dcbfcaae + languageName: node + linkType: hard + +"jest-changed-files@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-changed-files@npm:29.7.0" + dependencies: + execa: ^5.0.0 + jest-util: ^29.7.0 + p-limit: ^3.1.0 + checksum: 963e203893c396c5dfc75e00a49426688efea7361b0f0e040035809cecd2d46b3c01c02be2d9e8d38b1138357d2de7719ea5b5be21f66c10f2e9685a5a73bb99 + languageName: node + linkType: hard + +"jest-circus@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-circus@npm:29.7.0" + dependencies: + "@jest/environment": ^29.7.0 + "@jest/expect": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + co: ^4.6.0 + dedent: ^1.0.0 + is-generator-fn: ^2.0.0 + jest-each: ^29.7.0 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-runtime: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 + p-limit: ^3.1.0 + pretty-format: ^29.7.0 + pure-rand: ^6.0.0 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 349437148924a5a109c9b8aad6d393a9591b4dac1918fc97d81b7fc515bc905af9918495055071404af1fab4e48e4b04ac3593477b1d5dcf48c4e71b527c70a7 + languageName: node + linkType: hard + +"jest-cli@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-cli@npm:29.7.0" + dependencies: + "@jest/core": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + create-jest: ^29.7.0 + exit: ^0.1.2 + import-local: ^3.0.2 + jest-config: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + 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: 664901277a3f5007ea4870632ed6e7889db9da35b2434e7cb488443e6bf5513889b344b7fddf15112135495b9875892b156faeb2d7391ddb9e2a849dcb7b6c36 + languageName: node + linkType: hard + +"jest-config@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-config@npm:29.7.0" + dependencies: + "@babel/core": ^7.11.6 + "@jest/test-sequencer": ^29.7.0 + "@jest/types": ^29.6.3 + babel-jest: ^29.7.0 + 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.7.0 + jest-environment-node: ^29.7.0 + jest-get-type: ^29.6.3 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.7.0 + jest-runner: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + micromatch: ^4.0.4 + parse-json: ^5.2.0 + pretty-format: ^29.7.0 + 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: 4cabf8f894c180cac80b7df1038912a3fc88f96f2622de33832f4b3314f83e22b08fb751da570c0ab2b7988f21604bdabade95e3c0c041068ac578c085cf7dff + languageName: node + linkType: hard + +"jest-diff@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-diff@npm:29.7.0" + dependencies: + chalk: ^4.0.0 + diff-sequences: ^29.6.3 + jest-get-type: ^29.6.3 + pretty-format: ^29.7.0 + checksum: 08e24a9dd43bfba1ef07a6374e5af138f53137b79ec3d5cc71a2303515335898888fa5409959172e1e05de966c9e714368d15e8994b0af7441f0721ee8e1bb77 + languageName: node + linkType: hard + +"jest-docblock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-docblock@npm:29.7.0" + dependencies: + detect-newline: ^3.0.0 + checksum: 66390c3e9451f8d96c5da62f577a1dad701180cfa9b071c5025acab2f94d7a3efc2515cfa1654ebe707213241541ce9c5530232cdc8017c91ed64eea1bd3b192 + languageName: node + linkType: hard + +"jest-each@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-each@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + jest-get-type: ^29.6.3 + jest-util: ^29.7.0 + pretty-format: ^29.7.0 + checksum: e88f99f0184000fc8813f2a0aa79e29deeb63700a3b9b7928b8a418d7d93cd24933608591dbbdea732b473eb2021c72991b5cc51a17966842841c6e28e6f691c + languageName: node + linkType: hard + +"jest-environment-node@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-environment-node@npm:29.7.0" + dependencies: + "@jest/environment": ^29.7.0 + "@jest/fake-timers": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-mock: ^29.7.0 + jest-util: ^29.7.0 + checksum: 501a9966292cbe0ca3f40057a37587cb6def25e1e0c5e39ac6c650fe78d3c70a2428304341d084ac0cced5041483acef41c477abac47e9a290d5545fd2f15646 + languageName: node + linkType: hard + +"jest-get-type@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-get-type@npm:29.6.3" + checksum: 88ac9102d4679d768accae29f1e75f592b760b44277df288ad76ce5bf038c3f5ce3719dea8aa0f035dac30e9eb034b848ce716b9183ad7cc222d029f03e92205 + languageName: node + linkType: hard + +"jest-haste-map@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-haste-map@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@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.6.3 + jest-util: ^29.7.0 + jest-worker: ^29.7.0 + micromatch: ^4.0.4 + walker: ^1.0.8 + dependenciesMeta: + fsevents: + optional: true + checksum: c2c8f2d3e792a963940fbdfa563ce14ef9e14d4d86da645b96d3cd346b8d35c5ce0b992ee08593939b5f718cf0a1f5a90011a056548a1dbf58397d4356786f01 + languageName: node + linkType: hard + +"jest-leak-detector@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-leak-detector@npm:29.7.0" + dependencies: + jest-get-type: ^29.6.3 + pretty-format: ^29.7.0 + checksum: e3950e3ddd71e1d0c22924c51a300a1c2db6cf69ec1e51f95ccf424bcc070f78664813bef7aed4b16b96dfbdeea53fe358f8aeaaea84346ae15c3735758f1605 + languageName: node + linkType: hard + +"jest-matcher-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-matcher-utils@npm:29.7.0" + dependencies: + chalk: ^4.0.0 + jest-diff: ^29.7.0 + jest-get-type: ^29.6.3 + pretty-format: ^29.7.0 + checksum: d7259e5f995d915e8a37a8fd494cb7d6af24cd2a287b200f831717ba0d015190375f9f5dc35393b8ba2aae9b2ebd60984635269c7f8cff7d85b077543b7744cd + languageName: node + linkType: hard + +"jest-message-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-message-util@npm:29.7.0" + dependencies: + "@babel/code-frame": ^7.12.13 + "@jest/types": ^29.6.3 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^29.7.0 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: a9d025b1c6726a2ff17d54cc694de088b0489456c69106be6b615db7a51b7beb66788bea7a59991a019d924fbf20f67d085a445aedb9a4d6760363f4d7d09930 + languageName: node + linkType: hard + +"jest-mock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-mock@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-util: ^29.7.0 + checksum: 81ba9b68689a60be1482212878973700347cb72833c5e5af09895882b9eb5c4e02843a1bbdf23f94c52d42708bab53a30c45a3482952c9eec173d1eaac5b86c5 + languageName: node + linkType: hard + +"jest-pnp-resolver@npm:^1.2.2": + version: 1.2.3 + resolution: "jest-pnp-resolver@npm:1.2.3" + peerDependencies: + jest-resolve: "*" + peerDependenciesMeta: + jest-resolve: + optional: true + checksum: db1a8ab2cb97ca19c01b1cfa9a9c8c69a143fde833c14df1fab0766f411b1148ff0df878adea09007ac6a2085ec116ba9a996a6ad104b1e58c20adbf88eed9b2 + languageName: node + linkType: hard + +"jest-regex-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-regex-util@npm:29.6.3" + checksum: 0518beeb9bf1228261695e54f0feaad3606df26a19764bc19541e0fc6e2a3737191904607fb72f3f2ce85d9c16b28df79b7b1ec9443aa08c3ef0e9efda6f8f2a + languageName: node + linkType: hard + +"jest-resolve-dependencies@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve-dependencies@npm:29.7.0" + dependencies: + jest-regex-util: ^29.6.3 + jest-snapshot: ^29.7.0 + checksum: aeb75d8150aaae60ca2bb345a0d198f23496494677cd6aefa26fc005faf354061f073982175daaf32b4b9d86b26ca928586344516e3e6969aa614cb13b883984 + languageName: node + linkType: hard + +"jest-resolve@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve@npm:29.7.0" + dependencies: + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.7.0 + jest-pnp-resolver: ^1.2.2 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + resolve: ^1.20.0 + resolve.exports: ^2.0.0 + slash: ^3.0.0 + checksum: 0ca218e10731aa17920526ec39deaec59ab9b966237905ffc4545444481112cd422f01581230eceb7e82d86f44a543d520a71391ec66e1b4ef1a578bd5c73487 + languageName: node + linkType: hard + +"jest-runner@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runner@npm:29.7.0" + dependencies: + "@jest/console": ^29.7.0 + "@jest/environment": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + emittery: ^0.13.1 + graceful-fs: ^4.2.9 + jest-docblock: ^29.7.0 + jest-environment-node: ^29.7.0 + jest-haste-map: ^29.7.0 + jest-leak-detector: ^29.7.0 + jest-message-util: ^29.7.0 + jest-resolve: ^29.7.0 + jest-runtime: ^29.7.0 + jest-util: ^29.7.0 + jest-watcher: ^29.7.0 + jest-worker: ^29.7.0 + p-limit: ^3.1.0 + source-map-support: 0.5.13 + checksum: f0405778ea64812bf9b5c50b598850d94ccf95d7ba21f090c64827b41decd680ee19fcbb494007cdd7f5d0d8906bfc9eceddd8fa583e753e736ecd462d4682fb + languageName: node + linkType: hard + +"jest-runtime@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runtime@npm:29.7.0" + dependencies: + "@jest/environment": ^29.7.0 + "@jest/fake-timers": ^29.7.0 + "@jest/globals": ^29.7.0 + "@jest/source-map": ^29.6.3 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@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.7.0 + jest-message-util: ^29.7.0 + jest-mock: ^29.7.0 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 + slash: ^3.0.0 + strip-bom: ^4.0.0 + checksum: d19f113d013e80691e07047f68e1e3448ef024ff2c6b586ce4f90cd7d4c62a2cd1d460110491019719f3c59bfebe16f0e201ed005ef9f80e2cf798c374eed54e + languageName: node + linkType: hard + +"jest-snapshot@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-snapshot@npm:29.7.0" + 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.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + babel-preset-current-node-syntax: ^1.0.0 + chalk: ^4.0.0 + expect: ^29.7.0 + graceful-fs: ^4.2.9 + jest-diff: ^29.7.0 + jest-get-type: ^29.6.3 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + natural-compare: ^1.4.0 + pretty-format: ^29.7.0 + semver: ^7.5.3 + checksum: 86821c3ad0b6899521ce75ee1ae7b01b17e6dfeff9166f2cf17f012e0c5d8c798f30f9e4f8f7f5bed01ea7b55a6bc159f5eda778311162cbfa48785447c237ad + languageName: node + linkType: hard + +"jest-util@npm:^29.0.0, jest-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-util@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: 042ab4980f4ccd4d50226e01e5c7376a8556b472442ca6091a8f102488c0f22e6e8b89ea874111d2328a2080083bf3225c86f3788c52af0bd0345a00eb57a3ca + languageName: node + linkType: hard + +"jest-validate@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-validate@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + camelcase: ^6.2.0 + chalk: ^4.0.0 + jest-get-type: ^29.6.3 + leven: ^3.1.0 + pretty-format: ^29.7.0 + checksum: 191fcdc980f8a0de4dbdd879fa276435d00eb157a48683af7b3b1b98b0f7d9de7ffe12689b617779097ff1ed77601b9f7126b0871bba4f776e222c40f62e9dae + languageName: node + linkType: hard + +"jest-watcher@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-watcher@npm:29.7.0" + dependencies: + "@jest/test-result": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + emittery: ^0.13.1 + jest-util: ^29.7.0 + string-length: ^4.0.1 + checksum: 67e6e7fe695416deff96b93a14a561a6db69389a0667e9489f24485bb85e5b54e12f3b2ba511ec0b777eca1e727235b073e3ebcdd473d68888650489f88df92f + languageName: node + linkType: hard + +"jest-worker@npm:^27.4.5": + version: 27.5.1 + resolution: "jest-worker@npm:27.5.1" + dependencies: + "@types/node": "*" + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 98cd68b696781caed61c983a3ee30bf880b5bd021c01d98f47b143d4362b85d0737f8523761e2713d45e18b4f9a2b98af1eaee77afade4111bb65c77d6f7c980 + languageName: node + linkType: hard + +"jest-worker@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-worker@npm:29.7.0" + dependencies: + "@types/node": "*" + jest-util: ^29.7.0 + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 30fff60af49675273644d408b650fc2eb4b5dcafc5a0a455f238322a8f9d8a98d847baca9d51ff197b6747f54c7901daa2287799230b856a0f48287d131f8c13 + languageName: node + linkType: hard + +"jest@npm:^29.7.0": + version: 29.7.0 + resolution: "jest@npm:29.7.0" + dependencies: + "@jest/core": ^29.7.0 + "@jest/types": ^29.6.3 + import-local: ^3.0.2 + jest-cli: ^29.7.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 17ca8d67504a7dbb1998cf3c3077ec9031ba3eb512da8d71cb91bcabb2b8995c4e4b292b740cb9bf1cbff5ce3e110b3f7c777b0cefb6f41ab05445f248d0ee0b + languageName: node + linkType: hard + +"jquery@npm:^3.1.1": + version: 3.7.1 + resolution: "jquery@npm:3.7.1" + checksum: 4370b8139d6ae82867eb6f7f21d1edccf1d1bdf41c0840920ea80d366c2cd5dbe1ceebb110ee9772aa839b04400faa1572c5c560b507c688ed7b61cea26c0e27 + languageName: node + linkType: hard + +"js-tokens@npm:^4.0.0": + version: 4.0.0 + resolution: "js-tokens@npm:4.0.0" + checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 + languageName: node + linkType: hard + +"js-yaml@npm:^3.13.1": + version: 3.14.1 + resolution: "js-yaml@npm:3.14.1" + dependencies: + argparse: ^1.0.7 + esprima: ^4.0.0 + bin: + js-yaml: bin/js-yaml.js + checksum: bef146085f472d44dee30ec34e5cf36bf89164f5d585435a3d3da89e52622dff0b188a580e4ad091c3341889e14cb88cac6e4deb16dc5b1e9623bb0601fc255c + languageName: node + linkType: hard + +"js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: ^2.0.1 + bin: + js-yaml: bin/js-yaml.js + checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a + languageName: node + linkType: hard + +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 + languageName: node + linkType: hard + +"jsesc@npm:^2.5.1": + version: 2.5.2 + resolution: "jsesc@npm:2.5.2" + bin: + jsesc: bin/jsesc + checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d + languageName: node + linkType: hard + +"jsesc@npm:~0.5.0": + version: 0.5.0 + resolution: "jsesc@npm:0.5.0" + bin: + jsesc: bin/jsesc + checksum: b8b44cbfc92f198ad972fba706ee6a1dfa7485321ee8c0b25f5cedd538dcb20cde3197de16a7265430fce8277a12db066219369e3d51055038946039f6e20e17 + languageName: node + linkType: hard + +"json-buffer@npm:3.0.1": + version: 3.0.1 + resolution: "json-buffer@npm:3.0.1" + checksum: 9026b03edc2847eefa2e37646c579300a1f3a4586cfb62bf857832b60c852042d0d6ae55d1afb8926163fa54c2b01d83ae24705f34990348bdac6273a29d4581 + languageName: node + linkType: hard + +"json-parse-better-errors@npm:^1.0.1": + version: 1.0.2 + resolution: "json-parse-better-errors@npm:1.0.2" + checksum: ff2b5ba2a70e88fd97a3cb28c1840144c5ce8fae9cbeeddba15afa333a5c407cf0e42300cd0a2885dbb055227fe68d405070faad941beeffbfde9cf3b2c78c5d + languageName: node + linkType: hard + +"json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": + version: 2.3.1 + resolution: "json-parse-even-better-errors@npm:2.3.1" + checksum: 798ed4cf3354a2d9ccd78e86d2169515a0097a5c133337807cdf7f1fc32e1391d207ccfc276518cc1d7d8d4db93288b8a50ba4293d212ad1336e52a8ec0a941f + languageName: node + linkType: hard + +"json-schema-compare@npm:^0.2.2": + version: 0.2.2 + resolution: "json-schema-compare@npm:0.2.2" + dependencies: + lodash: ^4.17.4 + checksum: dd6f2173857c8e3b77d6ebdfa05bd505bba5b08709ab46b532722f5d1c33b5fee1fc8f3c97d0c0d011db25f9f3b0baf7ab783bb5f55c32abd9f1201760e43c2c + languageName: node + linkType: hard + +"json-schema-merge-allof@npm:^0.8.1": + version: 0.8.1 + resolution: "json-schema-merge-allof@npm:0.8.1" + dependencies: + compute-lcm: ^1.1.2 + json-schema-compare: ^0.2.2 + lodash: ^4.17.20 + checksum: 82700f6ac77351959138d6b153d77375a8c29cf48d907241b85c8292dd77aabd8cb816400f2b0d17062c4ccc8893832ec4f664ab9c814927ef502e7a595ea873 + languageName: node + linkType: hard + +"json-schema-traverse@npm:^0.4.1": + version: 0.4.1 + resolution: "json-schema-traverse@npm:0.4.1" + checksum: 7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b + languageName: node + linkType: hard + +"json-schema-traverse@npm:^1.0.0": + version: 1.0.0 + resolution: "json-schema-traverse@npm:1.0.0" + checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad + languageName: node + linkType: hard + +"json-stable-stringify-without-jsonify@npm:^1.0.1": + version: 1.0.1 + resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" + checksum: cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 + languageName: node + linkType: hard + +"json5@npm:^2.1.2, json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 + languageName: node + linkType: hard + +"jsonfile@npm:^6.0.1": + version: 6.1.0 + resolution: "jsonfile@npm:6.1.0" + dependencies: + graceful-fs: ^4.1.6 + universalify: ^2.0.0 + dependenciesMeta: + graceful-fs: + optional: true + checksum: 7af3b8e1ac8fe7f1eccc6263c6ca14e1966fcbc74b618d3c78a0a2075579487547b94f72b7a1114e844a1e15bb00d440e5d1720bfc4612d790a6f285d5ea8354 + languageName: node + linkType: hard + +"jsonpointer@npm:^5.0.1": + version: 5.0.1 + resolution: "jsonpointer@npm:5.0.1" + checksum: 0b40f712900ad0c846681ea2db23b6684b9d5eedf55807b4708c656f5894b63507d0e28ae10aa1bddbea551241035afe62b6df0800fc94c2e2806a7f3adecd7c + languageName: node + linkType: hard + +"keyv@npm:^4.5.3": + version: 4.5.4 + resolution: "keyv@npm:4.5.4" + dependencies: + json-buffer: 3.0.1 + checksum: 74a24395b1c34bd44ad5cb2b49140d087553e170625240b86755a6604cd65aa16efdbdeae5cdb17ba1284a0fbb25ad06263755dbc71b8d8b06f74232ce3cdd72 + languageName: node + linkType: hard + +"kind-of@npm:^6.0.2": + version: 6.0.3 + resolution: "kind-of@npm:6.0.3" + checksum: 3ab01e7b1d440b22fe4c31f23d8d38b4d9b91d9f291df683476576493d5dfd2e03848a8b05813dd0c3f0e835bc63f433007ddeceb71f05cb25c45ae1b19c6d3b + languageName: node + linkType: hard + +"kleur@npm:^3.0.3": + version: 3.0.3 + resolution: "kleur@npm:3.0.3" + checksum: df82cd1e172f957bae9c536286265a5cdbd5eeca487cb0a3b2a7b41ef959fc61f8e7c0e9aeea9c114ccf2c166b6a8dd45a46fd619c1c569d210ecd2765ad5169 + languageName: node + linkType: hard + +"leven@npm:^3.1.0": + version: 3.1.0 + resolution: "leven@npm:3.1.0" + checksum: 638401d534585261b6003db9d99afd244dfe82d75ddb6db5c0df412842d5ab30b2ef18de471aaec70fe69a46f17b4ae3c7f01d8a4e6580ef7adb9f4273ad1e55 + languageName: node + linkType: hard + +"levn@npm:^0.4.1": + version: 0.4.1 + resolution: "levn@npm:0.4.1" + dependencies: + prelude-ls: ^1.2.1 + type-check: ~0.4.0 + checksum: 12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 + languageName: node + linkType: hard + +"lib0@npm:^0.2.85, lib0@npm:^0.2.86": + version: 0.2.97 + resolution: "lib0@npm:0.2.97" + dependencies: + isomorphic.js: ^0.2.4 + bin: + 0ecdsa-generate-keypair: bin/0ecdsa-generate-keypair.js + 0gentesthtml: bin/gentesthtml.js + 0serve: bin/0serve.js + checksum: f9ca204aff94e4e25396952c16a302d398468e4076d5f405560463dbbf9c65451a9efd40b1e7d4defd8533765576dc801336a2d2cfa64a2f0ed8e0f3c1a065a2 + languageName: node + linkType: hard + +"license-webpack-plugin@npm:^2.3.14": + version: 2.3.21 + resolution: "license-webpack-plugin@npm:2.3.21" + dependencies: + "@types/webpack-sources": ^0.1.5 + webpack-sources: ^1.2.0 + peerDependenciesMeta: + webpack: + optional: true + checksum: 6208bd2060d200fbffbcc89702c929d50c5a4a3f2158b046cf813b3f7f728bbbe4611b9fea2d67843bb5e7d64ad9122cc368a19ac73f5c4ad41765e6283bdc0c + languageName: node + linkType: hard + +"lines-and-columns@npm:^1.1.6": + version: 1.2.4 + resolution: "lines-and-columns@npm:1.2.4" + checksum: 0c37f9f7fa212b38912b7145e1cd16a5f3cd34d782441c3e6ca653485d326f58b3caccda66efce1c5812bde4961bbde3374fae4b0d11bf1226152337f3894aa5 + languageName: node + linkType: hard + +"load-json-file@npm:^4.0.0": + version: 4.0.0 + resolution: "load-json-file@npm:4.0.0" + dependencies: + graceful-fs: ^4.1.2 + parse-json: ^4.0.0 + pify: ^3.0.0 + strip-bom: ^3.0.0 + checksum: 8f5d6d93ba64a9620445ee9bde4d98b1eac32cf6c8c2d20d44abfa41a6945e7969456ab5f1ca2fb06ee32e206c9769a20eec7002fe290de462e8c884b6b8b356 + languageName: node + linkType: hard + +"loader-runner@npm:^4.2.0": + version: 4.3.0 + resolution: "loader-runner@npm:4.3.0" + checksum: a90e00dee9a16be118ea43fec3192d0b491fe03a32ed48a4132eb61d498f5536a03a1315531c19d284392a8726a4ecad71d82044c28d7f22ef62e029bf761569 + languageName: node + linkType: hard + +"loader-utils@npm:^2.0.0": + version: 2.0.4 + resolution: "loader-utils@npm:2.0.4" + dependencies: + big.js: ^5.2.2 + emojis-list: ^3.0.0 + json5: ^2.1.2 + checksum: a5281f5fff1eaa310ad5e1164095689443630f3411e927f95031ab4fb83b4a98f388185bb1fe949e8ab8d4247004336a625e9255c22122b815bb9a4c5d8fc3b7 + languageName: node + linkType: hard + +"locate-path@npm:^5.0.0": + version: 5.0.0 + resolution: "locate-path@npm:5.0.0" + dependencies: + p-locate: ^4.1.0 + checksum: 83e51725e67517287d73e1ded92b28602e3ae5580b301fe54bfb76c0c723e3f285b19252e375712316774cf52006cb236aed5704692c32db0d5d089b69696e30 + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: ^5.0.0 + checksum: 72eb661788a0368c099a184c59d2fee760b3831c9c1c33955e8a19ae4a21b4116e53fa736dc086cdeb9fce9f7cc508f2f92d2d3aae516f133e16a2bb59a39f5a + languageName: node + linkType: hard + +"lodash-es@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash-es@npm:4.17.21" + checksum: 05cbffad6e2adbb331a4e16fbd826e7faee403a1a04873b82b42c0f22090f280839f85b95393f487c1303c8a3d2a010048bf06151a6cbe03eee4d388fb0a12d2 + languageName: node + linkType: hard + +"lodash.debounce@npm:^4.0.8": + version: 4.0.8 + resolution: "lodash.debounce@npm:4.0.8" + checksum: a3f527d22c548f43ae31c861ada88b2637eb48ac6aa3eb56e82d44917971b8aa96fbb37aa60efea674dc4ee8c42074f90f7b1f772e9db375435f6c83a19b3bc6 + languageName: node + linkType: hard + +"lodash.memoize@npm:4.x": + version: 4.1.2 + resolution: "lodash.memoize@npm:4.1.2" + checksum: 9ff3942feeccffa4f1fafa88d32f0d24fdc62fd15ded5a74a5f950ff5f0c6f61916157246744c620173dddf38d37095a92327d5fd3861e2063e736a5c207d089 + languageName: node + linkType: hard + +"lodash.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 + languageName: node + linkType: hard + +"lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 6476138d2125387a6d20f100608c2583d415a4f64a0fecf30c9e2dda976614f09cad4baa0842447bd37dd459a7bd27f57d9d8f8ce558805abd487c583f3d774a + languageName: node + linkType: hard + +"lru-cache@npm:^5.1.1": + version: 5.1.1 + resolution: "lru-cache@npm:5.1.1" + dependencies: + yallist: ^3.0.2 + checksum: c154ae1cbb0c2206d1501a0e94df349653c92c8cbb25236d7e85190bcaf4567a03ac6eb43166fabfa36fd35623694da7233e88d9601fbf411a9a481d85dbd2cb + languageName: node + linkType: hard + +"make-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "make-dir@npm:4.0.0" + dependencies: + semver: ^7.5.3 + checksum: bf0731a2dd3aab4db6f3de1585cea0b746bb73eb5a02e3d8d72757e376e64e6ada190b1eddcde5b2f24a81b688a9897efd5018737d05e02e2a671dda9cff8a8a + languageName: node + linkType: hard + +"make-error@npm:1.x": + version: 1.3.6 + resolution: "make-error@npm:1.3.6" + checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" + dependencies: + "@npmcli/agent": ^2.0.0 + cacache: ^18.0.0 + http-cache-semantics: ^4.1.1 + is-lambda: ^1.0.1 + minipass: ^7.0.2 + minipass-fetch: ^3.0.0 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + negotiator: ^0.6.3 + proc-log: ^4.2.0 + promise-retry: ^2.0.1 + ssri: ^10.0.0 + checksum: 5c9fad695579b79488fa100da05777213dd9365222f85e4757630f8dd2a21a79ddd3206c78cfd6f9b37346819681782b67900ac847a57cf04190f52dda5343fd + languageName: node + linkType: hard + +"makeerror@npm:1.0.12": + version: 1.0.12 + resolution: "makeerror@npm:1.0.12" + dependencies: + tmpl: 1.0.5 + checksum: b38a025a12c8146d6eeea5a7f2bf27d51d8ad6064da8ca9405fcf7bf9b54acd43e3b30ddd7abb9b1bfa4ddb266019133313482570ddb207de568f71ecfcf6060 + languageName: node + linkType: hard + +"memorystream@npm:^0.3.1": + version: 0.3.1 + resolution: "memorystream@npm:0.3.1" + checksum: f18b42440d24d09516d01466c06adf797df7873f0d40aa7db02e5fb9ed83074e5e65412d0720901d7069363465f82dc4f8bcb44f0cde271567a61426ce6ca2e9 + languageName: node + linkType: hard + +"merge-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-stream@npm:2.0.0" + checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 + languageName: node + linkType: hard + +"merge2@npm:^1.3.0, merge2@npm:^1.4.1": + version: 1.4.1 + resolution: "merge2@npm:1.4.1" + checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 + languageName: node + linkType: hard + +"micromatch@npm:^4.0.0, micromatch@npm:^4.0.4": + version: 4.0.7 + resolution: "micromatch@npm:4.0.7" + dependencies: + braces: ^3.0.3 + picomatch: ^2.3.1 + checksum: 3cde047d70ad80cf60c787b77198d680db3b8c25b23feb01de5e2652205d9c19f43bd81882f69a0fd1f0cde6a7a122d774998aad3271ddb1b8accf8a0f480cf7 + languageName: node + linkType: hard + +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f + languageName: node + linkType: hard + +"mime-types@npm:^2.1.27": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: 1.52.0 + checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836 + languageName: node + linkType: hard + +"mimic-fn@npm:^2.1.0": + version: 2.1.0 + resolution: "mimic-fn@npm:2.1.0" + checksum: d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a + languageName: node + linkType: hard + +"mini-css-extract-plugin@npm:^2.7.0": + version: 2.9.0 + resolution: "mini-css-extract-plugin@npm:2.9.0" + dependencies: + schema-utils: ^4.0.0 + tapable: ^2.2.1 + peerDependencies: + webpack: ^5.0.0 + checksum: ae192c67ba85ac8bffeab66774635bf90181f00d5dd6cf95412426192599ddf5506fb4b1550acbd7a5476476e39db53c770dd40f8378f7baf5de96e3fec4e6e9 + languageName: node + linkType: hard + +"mini-svg-data-uri@npm:^1.4.4": + version: 1.4.4 + resolution: "mini-svg-data-uri@npm:1.4.4" + bin: + mini-svg-data-uri: cli.js + checksum: 997f1fbd8d59a70f03761e18626d335197a3479cb9d1ff75678e4b64b864d32a0b8fc18115eabde035e5299b8b4a354a78e57dd6ac10f9d604162a6170898d09 + languageName: node + linkType: hard + +"minimatch@npm:9.0.3": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: ^2.0.1 + checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + languageName: node + linkType: hard + +"minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: ^1.1.7 + checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a + languageName: node + linkType: hard + +"minimatch@npm:^5.0.1": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" + dependencies: + brace-expansion: ^2.0.1 + checksum: 7564208ef81d7065a370f788d337cd80a689e981042cb9a1d0e6580b6c6a8c9279eba80010516e258835a988363f99f54a6f711a315089b8b42694f5da9d0d77 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.4": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: ^2.0.1 + checksum: 2c035575eda1e50623c731ec6c14f65a85296268f749b9337005210bb2b34e2705f8ef1a358b188f69892286ab99dc42c8fb98a57bde55c8d81b3023c19cea28 + languageName: node + linkType: hard + +"minimist@npm:~1.2.0": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: ^7.0.3 + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" + dependencies: + encoding: ^0.1.13 + minipass: ^7.0.3 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: 8047d273236157aab27ab7cd8eab7ea79e6ecd63e8f80c3366ec076cb9a0fed550a6935bab51764369027c414647fd8256c2a20c5445fb250c483de43350de83 + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: ^3.0.0 + checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: ^3.0.0 + checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: ^3.0.0 + checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: ^4.0.0 + checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 + languageName: node + linkType: hard + +"minipass@npm:^5.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, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 2bfd325b95c555f2b4d2814d49325691c7bee937d753814861b0b49d5edcda55cbbf22b6b6a60bb91eddac8668771f03c5ff647dcd9d0f798e9548b9cdc46ee3 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: ^3.0.0 + yallist: ^4.0.0 + checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f + languageName: node + linkType: hard + +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 972deb188e8fb55547f1e58d66bd6b4a3623bf0c7137802582602d73e6480c1c2268dcbafbfb1be466e00cc7e56ac514d7fd9334b7cf33e3e2ab547c16f83a8d + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f + languageName: node + linkType: hard + +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 + languageName: node + linkType: hard + +"natural-compare@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare@npm:1.4.0" + checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d + languageName: node + linkType: hard + +"negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 + languageName: node + linkType: hard + +"neo-async@npm:^2.6.2": + version: 2.6.2 + resolution: "neo-async@npm:2.6.2" + checksum: deac9f8d00eda7b2e5cd1b2549e26e10a0faa70adaa6fdadca701cc55f49ee9018e427f424bac0c790b7c7e2d3068db97f3093f1093975f2acb8f8818b936ed9 + languageName: node + linkType: hard + +"nice-try@npm:^1.0.4": + version: 1.0.5 + resolution: "nice-try@npm:1.0.5" + checksum: 0b4af3b5bb5d86c289f7a026303d192a7eb4417231fe47245c460baeabae7277bcd8fd9c728fb6bd62c30b3e15cd6620373e2cf33353b095d8b403d3e8a15aff + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.2.0 + resolution: "node-gyp@npm:10.2.0" + dependencies: + env-paths: ^2.2.0 + exponential-backoff: ^3.1.1 + glob: ^10.3.10 + graceful-fs: ^4.2.6 + make-fetch-happen: ^13.0.0 + nopt: ^7.0.0 + proc-log: ^4.1.0 + semver: ^7.3.5 + tar: ^6.2.1 + which: ^4.0.0 + bin: + node-gyp: bin/node-gyp.js + checksum: 0233759d8c19765f7fdc259a35eb046ad86c3d09e22f7384613ae2b89647dd27fcf833fdf5293d9335041e91f9b1c539494225959cdb312a5c8080b7534b926f + languageName: node + linkType: hard + +"node-int64@npm:^0.4.0": + version: 0.4.0 + resolution: "node-int64@npm:0.4.0" + checksum: d0b30b1ee6d961851c60d5eaa745d30b5c95d94bc0e74b81e5292f7c42a49e3af87f1eb9e89f59456f80645d679202537de751b7d72e9e40ceea40c5e449057e + languageName: node + linkType: hard + +"node-releases@npm:^2.0.18": + version: 2.0.18 + resolution: "node-releases@npm:2.0.18" + checksum: ef55a3d853e1269a6d6279b7692cd6ff3e40bc74947945101138745bfdc9a5edabfe72cb19a31a8e45752e1910c4c65c77d931866af6357f242b172b7283f5b3 + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.1 + resolution: "nopt@npm:7.2.1" + dependencies: + abbrev: ^2.0.0 + bin: + nopt: bin/nopt.js + checksum: 6fa729cc77ce4162cfad8abbc9ba31d4a0ff6850c3af61d59b505653bef4781ec059f8890ecfe93ee8aa0c511093369cca88bfc998101616a2904e715bbbb7c9 + languageName: node + linkType: hard + +"normalize-package-data@npm:^2.3.2": + version: 2.5.0 + resolution: "normalize-package-data@npm:2.5.0" + dependencies: + hosted-git-info: ^2.1.4 + resolve: ^1.10.0 + semver: 2 || 3 || 4 || 5 + validate-npm-package-license: ^3.0.1 + checksum: 7999112efc35a6259bc22db460540cae06564aa65d0271e3bdfa86876d08b0e578b7b5b0028ee61b23f1cae9fc0e7847e4edc0948d3068a39a2a82853efc8499 + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 + languageName: node + linkType: hard + +"npm-run-all@npm:^4.1.5": + version: 4.1.5 + resolution: "npm-run-all@npm:4.1.5" + dependencies: + ansi-styles: ^3.2.1 + chalk: ^2.4.1 + cross-spawn: ^6.0.5 + memorystream: ^0.3.1 + minimatch: ^3.0.4 + pidtree: ^0.3.0 + read-pkg: ^3.0.0 + shell-quote: ^1.6.1 + string.prototype.padend: ^3.0.0 + bin: + npm-run-all: bin/npm-run-all/index.js + run-p: bin/run-p/index.js + run-s: bin/run-s/index.js + checksum: 373b72c6a36564da13c1642c1fd9bb4dcc756bce7a3648f883772f02661095319820834ff813762d2fee403e9b40c1cd27c8685807c107440f10eb19c006d4a0 + languageName: node + linkType: hard + +"npm-run-path@npm:^4.0.1": + version: 4.0.1 + resolution: "npm-run-path@npm:4.0.1" + dependencies: + path-key: ^3.0.0 + checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.1": + version: 1.13.2 + resolution: "object-inspect@npm:1.13.2" + checksum: 9f850b3c045db60e0e97746e809ee4090d6ce62195af17dd1e9438ac761394a7d8ec4f7906559aea5424eaf61e35d3e53feded2ccd5f62fcc7d9670d3c8eb353 + languageName: node + linkType: hard + +"object-keys@npm:^1.1.1": + version: 1.1.1 + resolution: "object-keys@npm:1.1.1" + checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a + languageName: node + linkType: hard + +"object.assign@npm:^4.1.5": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" + dependencies: + call-bind: ^1.0.5 + define-properties: ^1.2.1 + has-symbols: ^1.0.3 + object-keys: ^1.1.1 + checksum: f9aeac0541661370a1fc86e6a8065eb1668d3e771f7dbb33ee54578201336c057b21ee61207a186dd42db0c62201d91aac703d20d12a79fc79c353eed44d4e25 + languageName: node + linkType: hard + +"once@npm:^1.3.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: 1 + checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + languageName: node + linkType: hard + +"onetime@npm:^5.1.2": + version: 5.1.2 + resolution: "onetime@npm:5.1.2" + dependencies: + mimic-fn: ^2.1.0 + checksum: 2478859ef817fc5d4e9c2f9e5728512ddd1dbc9fb7829ad263765bb6d3b91ce699d6e2332eef6b7dff183c2f490bd3349f1666427eaba4469fba0ac38dfd0d34 + languageName: node + linkType: hard + +"optionator@npm:^0.9.3": + version: 0.9.4 + resolution: "optionator@npm:0.9.4" + dependencies: + deep-is: ^0.1.3 + fast-levenshtein: ^2.0.6 + levn: ^0.4.1 + prelude-ls: ^1.2.1 + type-check: ^0.4.0 + word-wrap: ^1.2.5 + checksum: ecbd010e3dc73e05d239976422d9ef54a82a13f37c11ca5911dff41c98a6c7f0f163b27f922c37e7f8340af9d36febd3b6e9cef508f3339d4c393d7276d716bb + languageName: node + linkType: hard + +"p-limit@npm:^2.2.0": + version: 2.3.0 + resolution: "p-limit@npm:2.3.0" + dependencies: + p-try: ^2.0.0 + checksum: 84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: ^0.1.0 + checksum: 7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 + languageName: node + linkType: hard + +"p-locate@npm:^4.1.0": + version: 4.1.0 + resolution: "p-locate@npm:4.1.0" + dependencies: + p-limit: ^2.2.0 + checksum: 513bd14a455f5da4ebfcb819ef706c54adb09097703de6aeaa5d26fe5ea16df92b48d1ac45e01e3944ce1e6aa2a66f7f8894742b8c9d6e276e16cd2049a2b870 + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: ^3.0.2 + checksum: 1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: ^3.0.0 + checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c + languageName: node + linkType: hard + +"p-try@npm:^2.0.0": + version: 2.2.0 + resolution: "p-try@npm:2.2.0" + checksum: f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: ac706ec856a5a03f5261e4e48fa974f24feb044d51f84f8332e2af0af04fbdbdd5bbbfb9cbbe354190409bc8307c83a9e38c6672c3c8855f709afb0006a009ea + languageName: node + linkType: hard + +"parent-module@npm:^1.0.0": + version: 1.0.1 + resolution: "parent-module@npm:1.0.1" + dependencies: + callsites: ^3.0.0 + checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff + languageName: node + linkType: hard + +"parse-json@npm:^4.0.0": + version: 4.0.0 + resolution: "parse-json@npm:4.0.0" + dependencies: + error-ex: ^1.3.1 + json-parse-better-errors: ^1.0.1 + checksum: 0fe227d410a61090c247e34fa210552b834613c006c2c64d9a05cfe9e89cf8b4246d1246b1a99524b53b313e9ac024438d0680f67e33eaed7e6f38db64cfe7b5 + languageName: node + linkType: hard + +"parse-json@npm:^5.2.0": + version: 5.2.0 + resolution: "parse-json@npm:5.2.0" + dependencies: + "@babel/code-frame": ^7.0.0 + error-ex: ^1.3.1 + json-parse-even-better-errors: ^2.3.0 + lines-and-columns: ^1.1.6 + checksum: 62085b17d64da57f40f6afc2ac1f4d95def18c4323577e1eced571db75d9ab59b297d1d10582920f84b15985cbfc6b6d450ccbf317644cfa176f3ed982ad87e2 + languageName: node + linkType: hard + +"parse-srcset@npm:^1.0.2": + version: 1.0.2 + resolution: "parse-srcset@npm:1.0.2" + checksum: 3a0380380c6082021fcce982f0b89fb8a493ce9dfd7d308e5e6d855201e80db8b90438649b31fdd82a3d6089a8ca17dccddaa2b730a718389af4c037b8539ebf + languageName: node + linkType: hard + +"path-browserify@npm:^1.0.0": + version: 1.0.1 + resolution: "path-browserify@npm:1.0.1" + checksum: c6d7fa376423fe35b95b2d67990060c3ee304fc815ff0a2dc1c6c3cfaff2bd0d572ee67e18f19d0ea3bbe32e8add2a05021132ac40509416459fffee35200699 + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 + languageName: node + linkType: hard + +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 + languageName: node + linkType: hard + +"path-key@npm:^2.0.1": + version: 2.0.1 + resolution: "path-key@npm:2.0.1" + checksum: f7ab0ad42fe3fb8c7f11d0c4f849871e28fbd8e1add65c370e422512fc5887097b9cf34d09c1747d45c942a8c1e26468d6356e2df3f740bf177ab8ca7301ebfd + languageName: node + linkType: hard + +"path-key@npm:^3.0.0, path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 + languageName: node + linkType: hard + +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: ^10.2.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: 890d5abcd593a7912dcce7cf7c6bf7a0b5648e3dee6caf0712c126ca0a65c7f3d7b9d769072a4d1baf370f61ce493ab5b038d59988688e0c5f3f646ee3c69023 + languageName: node + linkType: hard + +"path-type@npm:^3.0.0": + version: 3.0.0 + resolution: "path-type@npm:3.0.0" + dependencies: + pify: ^3.0.0 + checksum: 735b35e256bad181f38fa021033b1c33cfbe62ead42bb2222b56c210e42938eecb272ae1949f3b6db4ac39597a61b44edd8384623ec4d79bfdc9a9c0f12537a6 + languageName: node + linkType: hard + +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf + languageName: node + linkType: hard + +"pidtree@npm:^0.3.0": + version: 0.3.1 + resolution: "pidtree@npm:0.3.1" + bin: + pidtree: bin/pidtree.js + checksum: eb49025099f1af89a4696f7673351421f13420f3397b963c901fe23a1c9c2ff50f4750321970d4472c0ffbb065e4a6c3c27f75e226cc62284b19e21d32ce7012 + languageName: node + linkType: hard + +"pify@npm:^3.0.0": + version: 3.0.0 + resolution: "pify@npm:3.0.0" + checksum: 6cdcbc3567d5c412450c53261a3f10991665d660961e06605decf4544a61a97a54fefe70a68d5c37080ff9d6f4cf51444c90198d1ba9f9309a6c0d6e9f5c4fde + languageName: node + linkType: hard + +"pirates@npm:^4.0.4": + version: 4.0.6 + resolution: "pirates@npm:4.0.6" + checksum: 46a65fefaf19c6f57460388a5af9ab81e3d7fd0e7bc44ca59d753cb5c4d0df97c6c6e583674869762101836d68675f027d60f841c105d72734df9dfca97cbcc6 + languageName: node + linkType: hard + +"pkg-dir@npm:^4.2.0": + version: 4.2.0 + resolution: "pkg-dir@npm:4.2.0" + dependencies: + find-up: ^4.0.0 + checksum: 9863e3f35132bf99ae1636d31ff1e1e3501251d480336edb1c211133c8d58906bed80f154a1d723652df1fda91e01c7442c2eeaf9dc83157c7ae89087e43c8d6 + languageName: node + linkType: hard + +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: b32d403ece71e042385cc7856385cecf1cd8e144fa74d2f1de40d1e16035dba097bc189715925e79b67bdd1472796ff168d3a90d296356c9c94d272d5b95f3ae + languageName: node + linkType: hard + +"postcss-modules-extract-imports@npm:^3.1.0": + version: 3.1.0 + resolution: "postcss-modules-extract-imports@npm:3.1.0" + peerDependencies: + postcss: ^8.1.0 + checksum: b9192e0f4fb3d19431558be6f8af7ca45fc92baaad9b2778d1732a5880cd25c3df2074ce5484ae491e224f0d21345ffc2d419bd51c25b019af76d7a7af88c17f + languageName: node + linkType: hard + +"postcss-modules-local-by-default@npm:^4.0.5": + version: 4.0.5 + resolution: "postcss-modules-local-by-default@npm:4.0.5" + dependencies: + icss-utils: ^5.0.0 + postcss-selector-parser: ^6.0.2 + postcss-value-parser: ^4.1.0 + peerDependencies: + postcss: ^8.1.0 + checksum: ca9b01f4a0a3dfb33e016299e2dfb7e85c3123292f7aec2efc0c6771b9955648598bfb4c1561f7ee9732fb27fb073681233661b32eef98baab43743f96735452 + languageName: node + linkType: hard + +"postcss-modules-scope@npm:^3.2.0": + version: 3.2.0 + resolution: "postcss-modules-scope@npm:3.2.0" + dependencies: + postcss-selector-parser: ^6.0.4 + peerDependencies: + postcss: ^8.1.0 + checksum: 2ffe7e98c1fa993192a39c8dd8ade93fc4f59fbd1336ce34fcedaee0ee3bafb29e2e23fb49189256895b30e4f21af661c6a6a16ef7b17ae2c859301e4a4459ae + languageName: node + linkType: hard + +"postcss-modules-values@npm:^4.0.0": + version: 4.0.0 + resolution: "postcss-modules-values@npm:4.0.0" + dependencies: + icss-utils: ^5.0.0 + peerDependencies: + postcss: ^8.1.0 + checksum: f7f2cdf14a575b60e919ad5ea52fed48da46fe80db2733318d71d523fc87db66c835814940d7d05b5746b0426e44661c707f09bdb83592c16aea06e859409db6 + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": + version: 6.1.2 + resolution: "postcss-selector-parser@npm:6.1.2" + dependencies: + cssesc: ^3.0.0 + util-deprecate: ^1.0.2 + checksum: ce9440fc42a5419d103f4c7c1847cb75488f3ac9cbe81093b408ee9701193a509f664b4d10a2b4d82c694ee7495e022f8f482d254f92b7ffd9ed9dea696c6f84 + languageName: node + linkType: hard + +"postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": + version: 4.2.0 + resolution: "postcss-value-parser@npm:4.2.0" + checksum: 819ffab0c9d51cf0acbabf8996dffbfafbafa57afc0e4c98db88b67f2094cb44488758f06e5da95d7036f19556a4a732525e84289a425f4f6fd8e412a9d7442f + languageName: node + linkType: hard + +"postcss@npm:^8.3.11, postcss@npm:^8.4.33": + version: 8.4.41 + resolution: "postcss@npm:8.4.41" + dependencies: + nanoid: ^3.3.7 + picocolors: ^1.0.1 + source-map-js: ^1.2.0 + checksum: f865894929eb0f7fc2263811cc853c13b1c75103028b3f4f26df777e27b201f1abe21cb4aa4c2e901c80a04f6fb325ee22979688fe55a70e2ea82b0a517d3b6f + languageName: node + linkType: hard + +"prelude-ls@npm:^1.2.1": + version: 1.2.1 + resolution: "prelude-ls@npm:1.2.1" + checksum: cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a + languageName: node + linkType: hard + +"prettier-linter-helpers@npm:^1.0.0": + version: 1.0.0 + resolution: "prettier-linter-helpers@npm:1.0.0" + dependencies: + fast-diff: ^1.1.2 + checksum: 00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392 + languageName: node + linkType: hard + +"prettier@npm:^3.2.4": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" + bin: + prettier: bin/prettier.cjs + checksum: bc8604354805acfdde6106852d14b045bb20827ad76a5ffc2455b71a8257f94de93f17f14e463fe844808d2ccc87248364a5691488a3304f1031326e62d9276e + languageName: node + linkType: hard + +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": ^29.6.3 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: 032c1602383e71e9c0c02a01bbd25d6759d60e9c7cf21937dde8357aa753da348fcec5def5d1002c9678a8524d5fe099ad98861286550ef44de8808cc61e43b6 + languageName: node + linkType: hard + +"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 98f6cd012d54b5334144c5255ecb941ee171744f45fca8b43b58ae5a0c1af07352475f481cadd9848e7f0250376ee584f6aa0951a856ff8f021bdfbff4eb33fc + languageName: node + linkType: hard + +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: bfcce49814f7d172a6e6a14d5fa3ac92cc3d0c3b9feb1279774708a719e19acd673995226351a082a9ae99978254e320ccda4240ddc474ba31a76c79491ca7c3 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: ^2.0.2 + retry: ^0.12.0 + checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 + languageName: node + linkType: hard + +"prompts@npm:^2.0.1": + version: 2.4.2 + resolution: "prompts@npm:2.4.2" + dependencies: + kleur: ^3.0.3 + sisteransi: ^1.0.5 + checksum: d8fd1fe63820be2412c13bfc5d0a01909acc1f0367e32396962e737cb2fc52d004f3302475d5ce7d18a1e8a79985f93ff04ee03007d091029c3f9104bffc007d + languageName: node + linkType: hard + +"punycode@npm:^2.1.0, punycode@npm:^2.1.1": + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 + languageName: node + linkType: hard + +"pure-rand@npm:^6.0.0": + version: 6.1.0 + resolution: "pure-rand@npm:6.1.0" + checksum: 8d53bc02bed99eca0b65b505090152ee7e9bd67dd74f8ff32ba1c883b87234067c5bf68d2614759fb217d82594d7a92919e6df80f97885e7b12b42af4bd3316a + languageName: node + linkType: hard + +"querystringify@npm:^2.1.1": + version: 2.2.0 + resolution: "querystringify@npm:2.2.0" + checksum: 5641ea231bad7ef6d64d9998faca95611ed4b11c2591a8cae741e178a974f6a8e0ebde008475259abe1621cb15e692404e6b6626e927f7b849d5c09392604b15 + languageName: node + linkType: hard + +"queue-microtask@npm:^1.2.2": + version: 1.2.3 + resolution: "queue-microtask@npm:1.2.3" + checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4 + languageName: node + linkType: hard + +"randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: ^5.1.0 + checksum: d779499376bd4cbb435ef3ab9a957006c8682f343f14089ed5f27764e4645114196e75b7f6abf1cbd84fd247c0cb0651698444df8c9bf30e62120fbbc52269d6 + languageName: node + linkType: hard + +"react-is@npm:^18.0.0, react-is@npm:^18.2.0": + version: 18.3.1 + resolution: "react-is@npm:18.3.1" + checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21 + languageName: node + linkType: hard + +"read-pkg@npm:^3.0.0": + version: 3.0.0 + resolution: "read-pkg@npm:3.0.0" + dependencies: + load-json-file: ^4.0.0 + normalize-package-data: ^2.3.2 + path-type: ^3.0.0 + checksum: 398903ebae6c7e9965419a1062924436cc0b6f516c42c4679a90290d2f87448ed8f977e7aa2dbba4aa1ac09248628c43e493ac25b2bc76640e946035200e34c6 + languageName: node + linkType: hard + +"rechoir@npm:^0.8.0": + version: 0.8.0 + resolution: "rechoir@npm:0.8.0" + dependencies: + resolve: ^1.20.0 + checksum: ad3caed8afdefbc33fbc30e6d22b86c35b3d51c2005546f4e79bcc03c074df804b3640ad18945e6bef9ed12caedc035655ec1082f64a5e94c849ff939dc0a788 + languageName: node + linkType: hard + +"regenerate-unicode-properties@npm:^10.1.0": + version: 10.1.1 + resolution: "regenerate-unicode-properties@npm:10.1.1" + dependencies: + regenerate: ^1.4.2 + checksum: b80958ef40f125275824c2c47d5081dfaefebd80bff26c76761e9236767c748a4a95a69c053fe29d2df881177f2ca85df4a71fe70a82360388b31159ef19adcf + languageName: node + linkType: hard + +"regenerate@npm:^1.4.2": + version: 1.4.2 + resolution: "regenerate@npm:1.4.2" + checksum: 3317a09b2f802da8db09aa276e469b57a6c0dd818347e05b8862959c6193408242f150db5de83c12c3fa99091ad95fb42a6db2c3329bfaa12a0ea4cbbeb30cb0 + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.14.0": + version: 0.14.1 + resolution: "regenerator-runtime@npm:0.14.1" + checksum: 9f57c93277b5585d3c83b0cf76be47b473ae8c6d9142a46ce8b0291a04bb2cf902059f0f8445dcabb3fb7378e5fe4bb4ea1e008876343d42e46d3b484534ce38 + languageName: node + linkType: hard + +"regenerator-transform@npm:^0.15.2": + version: 0.15.2 + resolution: "regenerator-transform@npm:0.15.2" + dependencies: + "@babel/runtime": ^7.8.4 + checksum: 20b6f9377d65954980fe044cfdd160de98df415b4bff38fbade67b3337efaf078308c4fed943067cd759827cc8cfeca9cb28ccda1f08333b85d6a2acbd022c27 + languageName: node + linkType: hard + +"regexp.prototype.flags@npm:^1.5.2": + version: 1.5.2 + resolution: "regexp.prototype.flags@npm:1.5.2" + dependencies: + call-bind: ^1.0.6 + define-properties: ^1.2.1 + es-errors: ^1.3.0 + set-function-name: ^2.0.1 + checksum: d7f333667d5c564e2d7a97c56c3075d64c722c9bb51b2b4df6822b2e8096d623a5e63088fb4c83df919b6951ef8113841de8b47de7224872fa6838bc5d8a7d64 + languageName: node + linkType: hard + +"regexpu-core@npm:^5.3.1": + version: 5.3.2 + resolution: "regexpu-core@npm:5.3.2" + dependencies: + "@babel/regjsgen": ^0.8.0 + regenerate: ^1.4.2 + regenerate-unicode-properties: ^10.1.0 + regjsparser: ^0.9.1 + unicode-match-property-ecmascript: ^2.0.0 + unicode-match-property-value-ecmascript: ^2.1.0 + checksum: 95bb97088419f5396e07769b7de96f995f58137ad75fac5811fb5fe53737766dfff35d66a0ee66babb1eb55386ef981feaef392f9df6d671f3c124812ba24da2 + languageName: node + linkType: hard + +"regjsparser@npm:^0.9.1": + version: 0.9.1 + resolution: "regjsparser@npm:0.9.1" + dependencies: + jsesc: ~0.5.0 + bin: + regjsparser: bin/parser + checksum: 5e1b76afe8f1d03c3beaf9e0d935dd467589c3625f6d65fb8ffa14f224d783a0fed4bf49c2c1b8211043ef92b6117313419edf055a098ed8342e340586741afc + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80 + languageName: node + linkType: hard + +"require-from-string@npm:^2.0.2": + version: 2.0.2 + resolution: "require-from-string@npm:2.0.2" + checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b + languageName: node + linkType: hard + +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff + languageName: node + linkType: hard + +"resolve-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-cwd@npm:3.0.0" + dependencies: + resolve-from: ^5.0.0 + checksum: 546e0816012d65778e580ad62b29e975a642989108d9a3c5beabfb2304192fa3c9f9146fbdfe213563c6ff51975ae41bac1d3c6e047dd9572c94863a057b4d81 + languageName: node + linkType: hard + +"resolve-from@npm:^4.0.0": + version: 4.0.0 + resolution: "resolve-from@npm:4.0.0" + checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f + languageName: node + linkType: hard + +"resolve-from@npm:^5.0.0": + version: 5.0.0 + resolution: "resolve-from@npm:5.0.0" + checksum: 4ceeb9113e1b1372d0cd969f3468fa042daa1dd9527b1b6bb88acb6ab55d8b9cd65dbf18819f9f9ddf0db804990901dcdaade80a215e7b2c23daae38e64f5bdf + languageName: node + linkType: hard + +"resolve.exports@npm:^2.0.0": + version: 2.0.2 + resolution: "resolve.exports@npm:2.0.2" + checksum: 1c7778ca1b86a94f8ab4055d196c7d87d1874b96df4d7c3e67bbf793140f0717fd506dcafd62785b079cd6086b9264424ad634fb904409764c3509c3df1653f2 + languageName: node + linkType: hard + +"resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.20.0": + version: 1.22.8 + resolution: "resolve@npm:1.22.8" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: f8a26958aa572c9b064562750b52131a37c29d072478ea32e129063e2da7f83e31f7f11e7087a18225a8561cfe8d2f0df9dbea7c9d331a897571c0a2527dbb4c + languageName: node + linkType: hard + +"resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.20.0#~builtin": + version: 1.22.8 + resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=c3c19d" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 5479b7d431cacd5185f8db64bfcb7286ae5e31eb299f4c4f404ad8aa6098b77599563ac4257cb2c37a42f59dfc06a1bec2bcf283bb448f319e37f0feb9a09847 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c + languageName: node + linkType: hard + +"reusify@npm:^1.0.4": + version: 1.0.4 + resolution: "reusify@npm:1.0.4" + checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc + languageName: node + linkType: hard + +"rimraf@npm:^3.0.2": + version: 3.0.2 + resolution: "rimraf@npm:3.0.2" + dependencies: + glob: ^7.1.3 + bin: + rimraf: bin.js + checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 + languageName: node + linkType: hard + +"rimraf@npm:^5.0.5": + version: 5.0.10 + resolution: "rimraf@npm:5.0.10" + dependencies: + glob: ^10.3.7 + bin: + rimraf: dist/esm/bin.mjs + checksum: 50e27388dd2b3fa6677385fc1e2966e9157c89c86853b96d02e6915663a96b7ff4d590e14f6f70e90f9b554093aa5dbc05ac3012876be558c06a65437337bc05 + languageName: node + linkType: hard + +"run-parallel@npm:^1.1.9": + version: 1.2.0 + resolution: "run-parallel@npm:1.2.0" + dependencies: + queue-microtask: ^1.2.2 + checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d + languageName: node + linkType: hard + +"safe-array-concat@npm:^1.1.2": + version: 1.1.2 + resolution: "safe-array-concat@npm:1.1.2" + dependencies: + call-bind: ^1.0.7 + get-intrinsic: ^1.2.4 + has-symbols: ^1.0.3 + isarray: ^2.0.5 + checksum: a3b259694754ddfb73ae0663829e396977b99ff21cbe8607f35a469655656da8e271753497e59da8a7575baa94d2e684bea3e10ddd74ba046c0c9b4418ffa0c4 + languageName: node + linkType: hard + +"safe-buffer@npm:^5.1.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 + languageName: node + linkType: hard + +"safe-regex-test@npm:^1.0.3": + version: 1.0.3 + resolution: "safe-regex-test@npm:1.0.3" + dependencies: + call-bind: ^1.0.6 + es-errors: ^1.3.0 + is-regex: ^1.1.4 + checksum: 6c7d392ff1ae7a3ae85273450ed02d1d131f1d2c76e177d6b03eb88e6df8fa062639070e7d311802c1615f351f18dc58f9454501c58e28d5ffd9b8f502ba6489 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 + languageName: node + linkType: hard + +"sanitize-html@npm:^2.3": + version: 2.13.0 + resolution: "sanitize-html@npm:2.13.0" + dependencies: + deepmerge: ^4.2.2 + escape-string-regexp: ^4.0.0 + htmlparser2: ^8.0.0 + is-plain-object: ^5.0.0 + parse-srcset: ^1.0.2 + postcss: ^8.3.11 + checksum: d88602328306dbbddb9c5e2a5798783a3b38977a7ef40bf81dae31220d7fb583149c1046a33ec6817e9d96d172b1aaa9ea159776eb1ee08f6a0571150114c9bf + languageName: node + linkType: hard + +"schema-utils@npm:^2.7.0": + version: 2.7.1 + resolution: "schema-utils@npm:2.7.1" + dependencies: + "@types/json-schema": ^7.0.5 + ajv: ^6.12.4 + ajv-keywords: ^3.5.2 + checksum: 32c62fc9e28edd101e1bd83453a4216eb9bd875cc4d3775e4452b541908fa8f61a7bbac8ffde57484f01d7096279d3ba0337078e85a918ecbeb72872fb09fb2b + languageName: node + linkType: hard + +"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.2.0": + version: 3.3.0 + resolution: "schema-utils@npm:3.3.0" + dependencies: + "@types/json-schema": ^7.0.8 + ajv: ^6.12.5 + ajv-keywords: ^3.5.2 + checksum: ea56971926fac2487f0757da939a871388891bc87c6a82220d125d587b388f1704788f3706e7f63a7b70e49fc2db974c41343528caea60444afd5ce0fe4b85c0 + languageName: node + linkType: hard + +"schema-utils@npm:^4.0.0": + version: 4.2.0 + resolution: "schema-utils@npm:4.2.0" + dependencies: + "@types/json-schema": ^7.0.9 + ajv: ^8.9.0 + ajv-formats: ^2.1.1 + ajv-keywords: ^5.1.0 + checksum: 26a0463d47683258106e6652e9aeb0823bf0b85843039e068b57da1892f7ae6b6b1094d48e9ed5ba5cbe9f7166469d880858b9d91abe8bd249421eb813850cde + languageName: node + linkType: hard + +"semver@npm:2 || 3 || 4 || 5, semver@npm:^5.4.1, semver@npm:^5.5.0": + version: 5.7.2 + resolution: "semver@npm:5.7.2" + bin: + semver: bin/semver + checksum: fb4ab5e0dd1c22ce0c937ea390b4a822147a9c53dbd2a9a0132f12fe382902beef4fbf12cf51bb955248d8d15874ce8cd89532569756384f994309825f10b686 + languageName: node + linkType: hard + +"semver@npm:^6.3.0, semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 + languageName: node + linkType: hard + +"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8 + languageName: node + linkType: hard + +"serialize-javascript@npm:^6.0.1": + version: 6.0.2 + resolution: "serialize-javascript@npm:6.0.2" + dependencies: + randombytes: ^2.1.0 + checksum: c4839c6206c1d143c0f80763997a361310305751171dd95e4b57efee69b8f6edd8960a0b7fbfc45042aadff98b206d55428aee0dc276efe54f100899c7fa8ab7 + languageName: node + linkType: hard + +"set-function-length@npm:^1.2.1": + version: 1.2.2 + resolution: "set-function-length@npm:1.2.2" + dependencies: + define-data-property: ^1.1.4 + es-errors: ^1.3.0 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.4 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.2 + checksum: a8248bdacdf84cb0fab4637774d9fb3c7a8e6089866d04c817583ff48e14149c87044ce683d7f50759a8c50fb87c7a7e173535b06169c87ef76f5fb276dfff72 + languageName: node + linkType: hard + +"set-function-name@npm:^2.0.1": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" + dependencies: + define-data-property: ^1.1.4 + es-errors: ^1.3.0 + functions-have-names: ^1.2.3 + has-property-descriptors: ^1.0.2 + checksum: d6229a71527fd0404399fc6227e0ff0652800362510822a291925c9d7b48a1ca1a468b11b281471c34cd5a2da0db4f5d7ff315a61d26655e77f6e971e6d0c80f + languageName: node + linkType: hard + +"shallow-clone@npm:^3.0.0": + version: 3.0.1 + resolution: "shallow-clone@npm:3.0.1" + dependencies: + kind-of: ^6.0.2 + checksum: 39b3dd9630a774aba288a680e7d2901f5c0eae7b8387fc5c8ea559918b29b3da144b7bdb990d7ccd9e11be05508ac9e459ce51d01fd65e583282f6ffafcba2e7 + languageName: node + linkType: hard + +"shebang-command@npm:^1.2.0": + version: 1.2.0 + resolution: "shebang-command@npm:1.2.0" + dependencies: + shebang-regex: ^1.0.0 + checksum: 9eed1750301e622961ba5d588af2212505e96770ec376a37ab678f965795e995ade7ed44910f5d3d3cb5e10165a1847f52d3348c64e146b8be922f7707958908 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: ^3.0.0 + checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa + languageName: node + linkType: hard + +"shebang-regex@npm:^1.0.0": + version: 1.0.0 + resolution: "shebang-regex@npm:1.0.0" + checksum: 404c5a752cd40f94591dfd9346da40a735a05139dac890ffc229afba610854d8799aaa52f87f7e0c94c5007f2c6af55bdcaeb584b56691926c5eaf41dc8f1372 + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 + languageName: node + linkType: hard + +"shell-quote@npm:^1.6.1": + version: 1.8.1 + resolution: "shell-quote@npm:1.8.1" + checksum: 5f01201f4ef504d4c6a9d0d283fa17075f6770bfbe4c5850b074974c68062f37929ca61700d95ad2ac8822e14e8c4b990ca0e6e9272e64befd74ce5e19f0736b + languageName: node + linkType: hard + +"side-channel@npm:^1.0.4": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.4 + object-inspect: ^1.13.1 + checksum: bfc1afc1827d712271453e91b7cd3878ac0efd767495fd4e594c4c2afaa7963b7b510e249572bfd54b0527e66e4a12b61b80c061389e129755f34c493aad9b97 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 + languageName: node + linkType: hard + +"sisteransi@npm:^1.0.5": + version: 1.0.5 + resolution: "sisteransi@npm:1.0.5" + checksum: aba6438f46d2bfcef94cf112c835ab395172c75f67453fe05c340c770d3c402363018ae1ab4172a1026a90c47eaccf3af7b6ff6fa749a680c2929bd7fa2b37a4 + languageName: node + linkType: hard + +"slash@npm:^3.0.0": + version: 3.0.0 + resolution: "slash@npm:3.0.0" + checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" + dependencies: + agent-base: ^7.1.1 + debug: ^4.3.4 + socks: ^2.8.3 + checksum: b2ec5051d85fe49072f9a250c427e0e9571fd09d5db133819192d078fd291276e1f0f50f6dbc04329b207738b1071314cee8bdbb4b12e27de42dbcf1d4233c67 + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.3 + resolution: "socks@npm:2.8.3" + dependencies: + ip-address: ^9.0.5 + smart-buffer: ^4.2.0 + checksum: 7a6b7f6eedf7482b9e4597d9a20e09505824208006ea8f2c49b71657427f3c137ca2ae662089baa73e1971c62322d535d9d0cf1c9235cf6f55e315c18203eadd + languageName: node + linkType: hard + +"source-list-map@npm:^2.0.0": + version: 2.0.1 + resolution: "source-list-map@npm:2.0.1" + checksum: 806efc6f75e7cd31e4815e7a3aaf75a45c704871ea4075cb2eb49882c6fca28998f44fc5ac91adb6de03b2882ee6fb02f951fdc85e6a22b338c32bfe19557938 + languageName: node + linkType: hard + +"source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97 + languageName: node + linkType: hard + +"source-map-loader@npm:^5.0.0": + version: 5.0.0 + resolution: "source-map-loader@npm:5.0.0" + dependencies: + iconv-lite: ^0.6.3 + source-map-js: ^1.0.2 + peerDependencies: + webpack: ^5.72.1 + checksum: 66d6fbaa87a14197647515f274b9a685a84d0ddb95c3d9801bfb1ce28fc24000954c73548fe09c52c0bad660eb10d963b0c60d5c5943ccf2c8292a8d957f2acb + languageName: node + linkType: hard + +"source-map-loader@npm:~1.0.2": + version: 1.0.2 + resolution: "source-map-loader@npm:1.0.2" + dependencies: + data-urls: ^2.0.0 + iconv-lite: ^0.6.2 + loader-utils: ^2.0.0 + schema-utils: ^2.7.0 + source-map: ^0.6.1 + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + checksum: 0360b536e904f8fea452d0e122b9199661765229dc62a4b8093cc9d14e985f2ddd146355ede6d11acdd0b9bf4639b364e2526afcf9d3218ed45af63aa5eb053f + languageName: node + linkType: hard + +"source-map-support@npm:0.5.13": + version: 0.5.13 + resolution: "source-map-support@npm:0.5.13" + dependencies: + buffer-from: ^1.0.0 + source-map: ^0.6.0 + checksum: 933550047b6c1a2328599a21d8b7666507427c0f5ef5eaadd56b5da0fd9505e239053c66fe181bf1df469a3b7af9d775778eee283cbb7ae16b902ddc09e93a97 + languageName: node + linkType: hard + +"source-map-support@npm:~0.5.20": + version: 0.5.21 + resolution: "source-map-support@npm:0.5.21" + dependencies: + buffer-from: ^1.0.0 + source-map: ^0.6.0 + checksum: 43e98d700d79af1d36f859bdb7318e601dfc918c7ba2e98456118ebc4c4872b327773e5a1df09b0524e9e5063bb18f0934538eace60cca2710d1fa687645d137 + languageName: node + linkType: hard + +"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 + languageName: node + linkType: hard + +"source-map@npm:^0.7.4": + version: 0.7.4 + resolution: "source-map@npm:0.7.4" + checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5 + languageName: node + linkType: hard + +"spdx-correct@npm:^3.0.0": + version: 3.2.0 + resolution: "spdx-correct@npm:3.2.0" + dependencies: + spdx-expression-parse: ^3.0.0 + spdx-license-ids: ^3.0.0 + checksum: e9ae98d22f69c88e7aff5b8778dc01c361ef635580e82d29e5c60a6533cc8f4d820803e67d7432581af0cc4fb49973125076ee3b90df191d153e223c004193b2 + languageName: node + linkType: hard + +"spdx-exceptions@npm:^2.1.0": + version: 2.5.0 + resolution: "spdx-exceptions@npm:2.5.0" + checksum: bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15 + languageName: node + linkType: hard + +"spdx-expression-parse@npm:^3.0.0": + version: 3.0.1 + resolution: "spdx-expression-parse@npm:3.0.1" + dependencies: + spdx-exceptions: ^2.1.0 + spdx-license-ids: ^3.0.0 + checksum: a1c6e104a2cbada7a593eaa9f430bd5e148ef5290d4c0409899855ce8b1c39652bcc88a725259491a82601159d6dc790bedefc9016c7472f7de8de7361f8ccde + languageName: node + linkType: hard + +"spdx-license-ids@npm:^3.0.0": + version: 3.0.18 + resolution: "spdx-license-ids@npm:3.0.18" + checksum: 457825df5dd1fc0135b0bb848c896143f70945cc2da148afc71c73ed0837d1d651f809006e406d82109c9dd71a8cb39785a3604815fe46bc0548e9d3976f6b69 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + +"sprintf-js@npm:~1.0.2": + version: 1.0.3 + resolution: "sprintf-js@npm:1.0.3" + checksum: 19d79aec211f09b99ec3099b5b2ae2f6e9cdefe50bc91ac4c69144b6d3928a640bb6ae5b3def70c2e85a2c3d9f5ec2719921e3a59d3ca3ef4b2fd1a4656a0df3 + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.6 + resolution: "ssri@npm:10.0.6" + dependencies: + minipass: ^7.0.3 + checksum: 4603d53a05bcd44188747d38f1cc43833b9951b5a1ee43ba50535bdfc5fe4a0897472dbe69837570a5417c3c073377ef4f8c1a272683b401857f72738ee57299 + languageName: node + linkType: hard + +"stack-utils@npm:^2.0.3": + version: 2.0.6 + resolution: "stack-utils@npm:2.0.6" + dependencies: + escape-string-regexp: ^2.0.0 + checksum: 052bf4d25bbf5f78e06c1d5e67de2e088b06871fa04107ca8d3f0e9d9263326e2942c8bedee3545795fc77d787d443a538345eef74db2f8e35db3558c6f91ff7 + languageName: node + linkType: hard + +"stitch@workspace:.": + version: 0.0.0-use.local + resolution: "stitch@workspace:." + dependencies: + "@babel/core": ^7.23.7 + "@babel/preset-env": ^7.23.8 + "@jupyter-widgets/base": ^1.1.10 || ^2 || ^3 || ^4 || ^5 || ^6 + "@jupyter-widgets/base-manager": ^1.0.7 + "@jupyterlab/builder": ^4.0.11 + "@lumino/application": ^2.3.0 + "@lumino/widgets": ^2.3.1 + "@types/jest": ^29.5.11 + "@types/webpack-env": ^1.18.4 + "@typescript-eslint/eslint-plugin": ^6.19.1 + "@typescript-eslint/parser": ^6.19.1 + acorn: ^8.11.3 + css-loader: ^6.9.1 + eslint: ^8.56.0 + eslint-config-prettier: ^9.1.0 + eslint-plugin-prettier: ^5.1.3 + fs-extra: ^11.2.0 + identity-obj-proxy: ^3.0.0 + jest: ^29.7.0 + mkdirp: ^3.0.1 + npm-run-all: ^4.1.5 + prettier: ^3.2.4 + rimraf: ^5.0.5 + source-map-loader: ^5.0.0 + style-loader: ^3.3.4 + ts-jest: ^29.1.2 + ts-loader: ^9.5.1 + typescript: ~5.3.3 + webpack: ^5.90.0 + webpack-cli: ^5.1.4 + languageName: unknown + linkType: soft + +"string-length@npm:^4.0.1": + version: 4.0.2 + resolution: "string-length@npm:4.0.2" + dependencies: + char-regex: ^1.0.2 + strip-ansi: ^6.0.0 + checksum: ce85533ef5113fcb7e522bcf9e62cb33871aa99b3729cec5595f4447f660b0cefd542ca6df4150c97a677d58b0cb727a3fe09ac1de94071d05526c73579bf505 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: ^8.0.0 + is-fullwidth-code-point: ^3.0.0 + strip-ansi: ^6.0.1 + checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: ^0.2.0 + emoji-regex: ^9.2.2 + strip-ansi: ^7.0.1 + checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 + languageName: node + linkType: hard + +"string.prototype.padend@npm:^3.0.0": + version: 3.1.6 + resolution: "string.prototype.padend@npm:3.1.6" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.2 + es-object-atoms: ^1.0.0 + checksum: d9fc23c21bdfb6850756002ef09cebc420882003f29eafbd8322df77a90726bc2a64892d01f94f1fc9fc6f809414fbcbd8615610bb3cddd33512c12b6b3643a2 + languageName: node + linkType: hard + +"string.prototype.trim@npm:^1.2.9": + version: 1.2.9 + resolution: "string.prototype.trim@npm:1.2.9" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.0 + es-object-atoms: ^1.0.0 + checksum: ea2df6ec1e914c9d4e2dc856fa08228e8b1be59b59e50b17578c94a66a176888f417264bb763d4aac638ad3b3dad56e7a03d9317086a178078d131aa293ba193 + languageName: node + linkType: hard + +"string.prototype.trimend@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimend@npm:1.0.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: cc3bd2de08d8968a28787deba9a3cb3f17ca5f9f770c91e7e8fa3e7d47f079bad70fadce16f05dda9f261788be2c6e84a942f618c3bed31e42abc5c1084f8dfd + languageName: node + linkType: hard + +"string.prototype.trimstart@npm:^1.0.8": + version: 1.0.8 + resolution: "string.prototype.trimstart@npm:1.0.8" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-object-atoms: ^1.0.0 + checksum: df1007a7f580a49d692375d996521dc14fd103acda7f3034b3c558a60b82beeed3a64fa91e494e164581793a8ab0ae2f59578a49896a7af6583c1f20472bce96 + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: ^5.0.1 + checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: ^6.0.1 + checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d + languageName: node + linkType: hard + +"strip-bom@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-bom@npm:3.0.0" + checksum: 8d50ff27b7ebe5ecc78f1fe1e00fcdff7af014e73cf724b46fb81ef889eeb1015fc5184b64e81a2efe002180f3ba431bdd77e300da5c6685d702780fbf0c8d5b + languageName: node + linkType: hard + +"strip-bom@npm:^4.0.0": + version: 4.0.0 + resolution: "strip-bom@npm:4.0.0" + checksum: 9dbcfbaf503c57c06af15fe2c8176fb1bf3af5ff65003851a102749f875a6dbe0ab3b30115eccf6e805e9d756830d3e40ec508b62b3f1ddf3761a20ebe29d3f3 + languageName: node + linkType: hard + +"strip-final-newline@npm:^2.0.0": + version: 2.0.0 + resolution: "strip-final-newline@npm:2.0.0" + checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 + languageName: node + linkType: hard + +"strip-json-comments@npm:^3.1.1": + version: 3.1.1 + resolution: "strip-json-comments@npm:3.1.1" + checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 + languageName: node + linkType: hard + +"style-loader@npm:^3.3.4, style-loader@npm:~3.3.1": + version: 3.3.4 + resolution: "style-loader@npm:3.3.4" + peerDependencies: + webpack: ^5.0.0 + checksum: caac3f2fe2c3c89e49b7a2a9329e1cfa515ecf5f36b9c4885f9b218019fda207a9029939b2c35821dec177a264a007e7c391ccdd3ff7401881ce6287b9c8f38b + languageName: node + linkType: hard + +"supports-color@npm:^5.3.0": + version: 5.5.0 + resolution: "supports-color@npm:5.5.0" + dependencies: + has-flag: ^3.0.0 + checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac + languageName: node + linkType: hard + +"supports-color@npm:^7.1.0, supports-color@npm:^7.2.0": + version: 7.2.0 + resolution: "supports-color@npm:7.2.0" + dependencies: + has-flag: ^4.0.0 + checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a + languageName: node + linkType: hard + +"supports-color@npm:^8.0.0": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: ^4.0.0 + checksum: c052193a7e43c6cdc741eb7f378df605636e01ad434badf7324f17fb60c69a880d8d8fcdcb562cf94c2350e57b937d7425ab5b8326c67c2adc48f7c87c1db406 + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae + languageName: node + linkType: hard + +"synckit@npm:^0.9.1": + version: 0.9.1 + resolution: "synckit@npm:0.9.1" + dependencies: + "@pkgr/core": ^0.1.0 + tslib: ^2.6.2 + checksum: 4042941a4d939675f1d7b01124b8405b6ac616f3e3f396d00e46c67f38d0d5b7f9a1de05bc7ceea4ce80d967b450cfa2460e5f6aca81f7cea8f1a28be9392985 + languageName: node + linkType: hard + +"tapable@npm:^2.1.1, tapable@npm:^2.2.0, tapable@npm:^2.2.1": + version: 2.2.1 + resolution: "tapable@npm:2.2.1" + checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51 + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.2.1": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + 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: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c + languageName: node + linkType: hard + +"terser-webpack-plugin@npm:^5.3.10, terser-webpack-plugin@npm:^5.3.7": + version: 5.3.10 + resolution: "terser-webpack-plugin@npm:5.3.10" + dependencies: + "@jridgewell/trace-mapping": ^0.3.20 + jest-worker: ^27.4.5 + schema-utils: ^3.1.1 + serialize-javascript: ^6.0.1 + terser: ^5.26.0 + peerDependencies: + webpack: ^5.1.0 + peerDependenciesMeta: + "@swc/core": + optional: true + esbuild: + optional: true + uglify-js: + optional: true + checksum: bd6e7596cf815f3353e2a53e79cbdec959a1b0276f5e5d4e63e9d7c3c5bb5306df567729da287d1c7b39d79093e56863c569c42c6c24cc34c76aa313bd2cbcea + languageName: node + linkType: hard + +"terser@npm:^5.26.0": + version: 5.31.6 + resolution: "terser@npm:5.31.6" + dependencies: + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 + commander: ^2.20.0 + source-map-support: ~0.5.20 + bin: + terser: bin/terser + checksum: 60d3faf39c9ad7acc891e17888bbd206e0b777f442649cf49873a5fa317b8b8a17179a46970d884d5f93e8addde0206193ed1e2e4f1ccb1cafb167f7d1ddee96 + languageName: node + linkType: hard + +"test-exclude@npm:^6.0.0": + version: 6.0.0 + resolution: "test-exclude@npm:6.0.0" + dependencies: + "@istanbuljs/schema": ^0.1.2 + glob: ^7.1.4 + minimatch: ^3.0.4 + checksum: 3b34a3d77165a2cb82b34014b3aba93b1c4637a5011807557dc2f3da826c59975a5ccad765721c4648b39817e3472789f9b0fa98fc854c5c1c7a1e632aacdc28 + languageName: node + linkType: hard + +"text-table@npm:^0.2.0": + version: 0.2.0 + resolution: "text-table@npm:0.2.0" + checksum: b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a + languageName: node + linkType: hard + +"tmpl@npm:1.0.5": + version: 1.0.5 + resolution: "tmpl@npm:1.0.5" + checksum: cd922d9b853c00fe414c5a774817be65b058d54a2d01ebb415840960406c669a0fc632f66df885e24cb022ec812739199ccbdb8d1164c3e513f85bfca5ab2873 + languageName: node + linkType: hard + +"to-fast-properties@npm:^2.0.0": + version: 2.0.0 + resolution: "to-fast-properties@npm:2.0.0" + checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: ^7.0.0 + checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed + languageName: node + linkType: hard + +"tr46@npm:^2.1.0": + version: 2.1.0 + resolution: "tr46@npm:2.1.0" + dependencies: + punycode: ^2.1.1 + checksum: ffe6049b9dca3ae329b059aada7f515b0f0064c611b39b51ff6b53897e954650f6f63d9319c6c008d36ead477c7b55e5f64c9dc60588ddc91ff720d64eb710b3 + languageName: node + linkType: hard + +"ts-api-utils@npm:^1.0.1": + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" + peerDependencies: + typescript: ">=4.2.0" + checksum: c746ddabfdffbf16cb0b0db32bb287236a19e583057f8649ee7c49995bb776e1d3ef384685181c11a1a480369e022ca97512cb08c517b2d2bd82c83754c97012 + languageName: node + linkType: hard + +"ts-jest@npm:^29.1.2": + version: 29.2.4 + resolution: "ts-jest@npm:29.2.4" + dependencies: + bs-logger: 0.x + ejs: ^3.1.10 + fast-json-stable-stringify: 2.x + jest-util: ^29.0.0 + json5: ^2.2.3 + lodash.memoize: 4.x + make-error: 1.x + semver: ^7.5.3 + yargs-parser: ^21.0.1 + peerDependencies: + "@babel/core": ">=7.0.0-beta.0 <8" + "@jest/transform": ^29.0.0 + "@jest/types": ^29.0.0 + babel-jest: ^29.0.0 + jest: ^29.0.0 + typescript: ">=4.3 <6" + peerDependenciesMeta: + "@babel/core": + optional: true + "@jest/transform": + optional: true + "@jest/types": + optional: true + babel-jest: + optional: true + esbuild: + optional: true + bin: + ts-jest: cli.js + checksum: 142246f12bb11d5edbfb5a65e298097667e2c4d390e316e356416ce00d3cd157220dbfb9de2a56b38f30776bc92ba59eff9fd78e9345ba4c6712783f27f5475a + languageName: node + linkType: hard + +"ts-loader@npm:^9.5.1": + version: 9.5.1 + resolution: "ts-loader@npm:9.5.1" + dependencies: + chalk: ^4.1.0 + enhanced-resolve: ^5.0.0 + micromatch: ^4.0.0 + semver: ^7.3.4 + source-map: ^0.7.4 + peerDependencies: + typescript: "*" + webpack: ^5.0.0 + checksum: 7cf396e656d905388ea2a9b5e82f16d3c955fda8d3df2fbf219f4bee16ff50a3c995c44ae3e584634e9443f056cec70bb3151add3917ffb4588ecd7394bac0ec + languageName: node + linkType: hard + +"tslib@npm:^2.6.2": + version: 2.6.3 + resolution: "tslib@npm:2.6.3" + checksum: 74fce0e100f1ebd95b8995fbbd0e6c91bdd8f4c35c00d4da62e285a3363aaa534de40a80db30ecfd388ed7c313c42d930ee0eaf108e8114214b180eec3dbe6f5 + languageName: node + linkType: hard + +"type-check@npm:^0.4.0, type-check@npm:~0.4.0": + version: 0.4.0 + resolution: "type-check@npm:0.4.0" + dependencies: + prelude-ls: ^1.2.1 + checksum: ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a + languageName: node + linkType: hard + +"type-detect@npm:4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 + languageName: node + linkType: hard + +"type-fest@npm:^0.20.2": + version: 0.20.2 + resolution: "type-fest@npm:0.20.2" + checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 + languageName: node + linkType: hard + +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: e6b32a3b3877f04339bae01c193b273c62ba7bfc9e325b8703c4ee1b32dc8fe4ef5dfa54bf78265e069f7667d058e360ae0f37be5af9f153b22382cd55a9afe0 + languageName: node + linkType: hard + +"typed-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-buffer@npm:1.0.2" + dependencies: + call-bind: ^1.0.7 + es-errors: ^1.3.0 + is-typed-array: ^1.1.13 + checksum: 02ffc185d29c6df07968272b15d5319a1610817916ec8d4cd670ded5d1efe72901541ff2202fcc622730d8a549c76e198a2f74e312eabbfb712ed907d45cbb0b + languageName: node + linkType: hard + +"typed-array-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "typed-array-byte-length@npm:1.0.1" + dependencies: + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: f65e5ecd1cf76b1a2d0d6f631f3ea3cdb5e08da106c6703ffe687d583e49954d570cc80434816d3746e18be889ffe53c58bf3e538081ea4077c26a41055b216d + languageName: node + linkType: hard + +"typed-array-byte-offset@npm:^1.0.2": + version: 1.0.2 + resolution: "typed-array-byte-offset@npm:1.0.2" + dependencies: + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: c8645c8794a621a0adcc142e0e2c57b1823bbfa4d590ad2c76b266aa3823895cf7afb9a893bf6685e18454ab1b0241e1a8d885a2d1340948efa4b56add4b5f67 + languageName: node + linkType: hard + +"typed-array-length@npm:^1.0.6": + version: 1.0.6 + resolution: "typed-array-length@npm:1.0.6" + dependencies: + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + possible-typed-array-names: ^1.0.0 + checksum: f0315e5b8f0168c29d390ff410ad13e4d511c78e6006df4a104576844812ee447fcc32daab1f3a76c9ef4f64eff808e134528b5b2439de335586b392e9750e5c + languageName: node + linkType: hard + +"typescript@npm:~5.3.3": + version: 5.3.3 + resolution: "typescript@npm:5.3.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 + languageName: node + linkType: hard + +"typescript@patch:typescript@~5.3.3#~builtin": + version: 5.3.3 + resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=85af82" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 + languageName: node + linkType: hard + +"unbox-primitive@npm:^1.0.2": + version: 1.0.2 + resolution: "unbox-primitive@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + has-bigints: ^1.0.2 + has-symbols: ^1.0.3 + which-boxed-primitive: ^1.0.2 + checksum: b7a1cf5862b5e4b5deb091672ffa579aa274f648410009c81cca63fed3b62b610c4f3b773f912ce545bb4e31edc3138975b5bc777fc6e4817dca51affb6380e9 + languageName: node + linkType: hard + +"underscore@npm:>=1.8.3": + version: 1.13.7 + resolution: "underscore@npm:1.13.7" + checksum: 174b011af29e4fbe2c70eb2baa8bfab0d0336cf2f5654f364484967bc6264a86224d0134b9176e4235c8cceae00d11839f0fd4824268de04b11c78aca1241684 + languageName: node + linkType: hard + +"undici-types@npm:~6.19.2": + version: 6.19.6 + resolution: "undici-types@npm:6.19.6" + checksum: e66df2447b6d93a48b0605a54269d8c3f228edcd1e9563229f6de37e48ed53b3e49b4bc965733643ed9717e0e0fa1ee664c929db91d787c9f488fb3f9e17c533 + languageName: node + linkType: hard + +"unicode-canonical-property-names-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" + checksum: 39be078afd014c14dcd957a7a46a60061bc37c4508ba146517f85f60361acf4c7539552645ece25de840e17e293baa5556268d091ca6762747fdd0c705001a45 + languageName: node + linkType: hard + +"unicode-match-property-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-match-property-ecmascript@npm:2.0.0" + dependencies: + unicode-canonical-property-names-ecmascript: ^2.0.0 + unicode-property-aliases-ecmascript: ^2.0.0 + checksum: 1f34a7434a23df4885b5890ac36c5b2161a809887000be560f56ad4b11126d433c0c1c39baf1016bdabed4ec54829a6190ee37aa24919aa116dc1a5a8a62965a + languageName: node + linkType: hard + +"unicode-match-property-value-ecmascript@npm:^2.1.0": + version: 2.1.0 + resolution: "unicode-match-property-value-ecmascript@npm:2.1.0" + checksum: 8d6f5f586b9ce1ed0e84a37df6b42fdba1317a05b5df0c249962bd5da89528771e2d149837cad11aa26bcb84c35355cb9f58a10c3d41fa3b899181ece6c85220 + languageName: node + linkType: hard + +"unicode-property-aliases-ecmascript@npm:^2.0.0": + version: 2.1.0 + resolution: "unicode-property-aliases-ecmascript@npm:2.1.0" + checksum: 243524431893649b62cc674d877bd64ef292d6071dd2fd01ab4d5ad26efbc104ffcd064f93f8a06b7e4ec54c172bf03f6417921a0d8c3a9994161fe1f88f815b + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: ^4.0.0 + checksum: 8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: ^0.1.4 + checksum: 0884b58365af59f89739e6f71e3feacb5b1b41f2df2d842d0757933620e6de08eff347d27e9d499b43c40476cbaf7988638d3acb2ffbcb9d35fd035591adfd15 + languageName: node + linkType: hard + +"universalify@npm:^2.0.0": + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: ecd8469fe0db28e7de9e5289d32bd1b6ba8f7183db34f3bfc4ca53c49891c2d6aa05f3fb3936a81285a905cc509fb641a0c3fc131ec786167eff41236ae32e60 + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.1.0": + version: 1.1.0 + resolution: "update-browserslist-db@npm:1.1.0" + dependencies: + escalade: ^3.1.2 + picocolors: ^1.0.1 + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 7b74694d96f0c360f01b702e72353dc5a49df4fe6663d3ee4e5c628f061576cddf56af35a3a886238c01dd3d8f231b7a86a8ceaa31e7a9220ae31c1c1238e562 + languageName: node + linkType: hard + +"uri-js@npm:^4.2.2": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" + dependencies: + punycode: ^2.1.0 + checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 + languageName: node + linkType: hard + +"url-parse@npm:~1.5.4": + version: 1.5.10 + resolution: "url-parse@npm:1.5.10" + dependencies: + querystringify: ^2.1.1 + requires-port: ^1.0.0 + checksum: fbdba6b1d83336aca2216bbdc38ba658d9cfb8fc7f665eb8b17852de638ff7d1a162c198a8e4ed66001ddbf6c9888d41e4798912c62b4fd777a31657989f7bdf + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.2": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 + languageName: node + linkType: hard + +"v8-to-istanbul@npm:^9.0.1": + version: 9.3.0 + resolution: "v8-to-istanbul@npm:9.3.0" + dependencies: + "@jridgewell/trace-mapping": ^0.3.12 + "@types/istanbul-lib-coverage": ^2.0.1 + convert-source-map: ^2.0.0 + checksum: ded42cd535d92b7fd09a71c4c67fb067487ef5551cc227bfbf2a1f159a842e4e4acddaef20b955789b8d3b455b9779d036853f4a27ce15007f6364a4d30317ae + languageName: node + linkType: hard + +"validate-npm-package-license@npm:^3.0.1": + version: 3.0.4 + resolution: "validate-npm-package-license@npm:3.0.4" + dependencies: + spdx-correct: ^3.0.0 + spdx-expression-parse: ^3.0.0 + checksum: 35703ac889d419cf2aceef63daeadbe4e77227c39ab6287eeb6c1b36a746b364f50ba22e88591f5d017bc54685d8137bc2d328d0a896e4d3fd22093c0f32a9ad + languageName: node + linkType: hard + +"validate.io-array@npm:^1.0.3": + version: 1.0.6 + resolution: "validate.io-array@npm:1.0.6" + checksum: 54eca83ebc702e3e46499f9d9e77287a95ae25c4e727cd2fafee29c7333b3a36cca0c5d8f090b9406262786de80750fba85e7e7ef41e20bf8cc67d5570de449b + languageName: node + linkType: hard + +"validate.io-function@npm:^1.0.2": + version: 1.0.2 + resolution: "validate.io-function@npm:1.0.2" + checksum: e4cce2479a20cb7c42e8630c777fb107059c27bc32925f769e3a73ca5fd62b4892d897b3c80227e14d5fcd1c5b7d05544e0579d63e59f14034c0052cda7f7c44 + languageName: node + linkType: hard + +"validate.io-integer-array@npm:^1.0.0": + version: 1.0.0 + resolution: "validate.io-integer-array@npm:1.0.0" + dependencies: + validate.io-array: ^1.0.3 + validate.io-integer: ^1.0.4 + checksum: 5f6d7fab8df7d2bf546a05e830201768464605539c75a2c2417b632b4411a00df84b462f81eac75e1be95303e7e0ac92f244c137424739f4e15cd21c2eb52c7f + languageName: node + linkType: hard + +"validate.io-integer@npm:^1.0.4": + version: 1.0.5 + resolution: "validate.io-integer@npm:1.0.5" + dependencies: + validate.io-number: ^1.0.3 + checksum: 88b3f8bb5a5277a95305d64abbfc437079220ce4f57a148cc6113e7ccec03dd86b10a69d413982602aa90a62b8d516148a78716f550dcd3aff863ac1c2a7a5e6 + languageName: node + linkType: hard + +"validate.io-number@npm:^1.0.3": + version: 1.0.3 + resolution: "validate.io-number@npm:1.0.3" + checksum: 42418aeb6c969efa745475154fe576809b02eccd0961aad0421b090d6e7a12d23a3e28b0d5dddd2c6347c1a6bdccb82bba5048c716131cd20207244d50e07282 + languageName: node + linkType: hard + +"walker@npm:^1.0.8": + version: 1.0.8 + resolution: "walker@npm:1.0.8" + dependencies: + makeerror: 1.0.12 + checksum: ad7a257ea1e662e57ef2e018f97b3c02a7240ad5093c392186ce0bcf1f1a60bbadd520d073b9beb921ed99f64f065efb63dfc8eec689a80e569f93c1c5d5e16c + languageName: node + linkType: hard + +"watchpack@npm:^2.4.1": + version: 2.4.2 + resolution: "watchpack@npm:2.4.2" + dependencies: + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.1.2 + checksum: 92d9d52ce3d16fd83ed6994d1dd66a4d146998882f4c362d37adfea9ab77748a5b4d1e0c65fa104797928b2d40f635efa8f9b925a6265428a69f1e1852ca3441 + languageName: node + linkType: hard + +"webidl-conversions@npm:^6.1.0": + version: 6.1.0 + resolution: "webidl-conversions@npm:6.1.0" + checksum: 1f526507aa491f972a0c1409d07f8444e1d28778dfa269a9971f2e157182f3d496dc33296e4ed45b157fdb3bf535bb90c90bf10c50dcf1dd6caacb2a34cc84fb + languageName: node + linkType: hard + +"webpack-cli@npm:^5.0.1, webpack-cli@npm:^5.1.4": + version: 5.1.4 + resolution: "webpack-cli@npm:5.1.4" + dependencies: + "@discoveryjs/json-ext": ^0.5.0 + "@webpack-cli/configtest": ^2.1.1 + "@webpack-cli/info": ^2.0.2 + "@webpack-cli/serve": ^2.0.5 + colorette: ^2.0.14 + commander: ^10.0.1 + cross-spawn: ^7.0.3 + envinfo: ^7.7.3 + fastest-levenshtein: ^1.0.12 + import-local: ^3.0.2 + interpret: ^3.1.1 + rechoir: ^0.8.0 + webpack-merge: ^5.7.3 + peerDependencies: + webpack: 5.x.x + peerDependenciesMeta: + "@webpack-cli/generators": + optional: true + webpack-bundle-analyzer: + optional: true + webpack-dev-server: + optional: true + bin: + webpack-cli: bin/cli.js + checksum: 3a4ad0d0342a6815c850ee4633cc2a8a5dae04f918e7847f180bf24ab400803cf8a8943707ffbed03eb20fe6ce647f996f60a2aade87b0b4a9954da3da172ce0 + languageName: node + linkType: hard + +"webpack-merge@npm:^5.7.3, webpack-merge@npm:^5.8.0": + version: 5.10.0 + resolution: "webpack-merge@npm:5.10.0" + dependencies: + clone-deep: ^4.0.1 + flat: ^5.0.2 + wildcard: ^2.0.0 + checksum: 1fe8bf5309add7298e1ac72fb3f2090e1dfa80c48c7e79fa48aa60b5961332c7d0d61efa8851acb805e6b91a4584537a347bc106e05e9aec87fa4f7088c62f2f + languageName: node + linkType: hard + +"webpack-sources@npm:^1.2.0": + version: 1.4.3 + resolution: "webpack-sources@npm:1.4.3" + dependencies: + source-list-map: ^2.0.0 + source-map: ~0.6.1 + checksum: 37463dad8d08114930f4bc4882a9602941f07c9f0efa9b6bc78738cd936275b990a596d801ef450d022bb005b109b9f451dd087db2f3c9baf53e8e22cf388f79 + languageName: node + linkType: hard + +"webpack-sources@npm:^3.2.3": + version: 3.2.3 + resolution: "webpack-sources@npm:3.2.3" + checksum: 989e401b9fe3536529e2a99dac8c1bdc50e3a0a2c8669cbafad31271eadd994bc9405f88a3039cd2e29db5e6d9d0926ceb7a1a4e7409ece021fe79c37d9c4607 + languageName: node + linkType: hard + +"webpack@npm:^5.76.1, webpack@npm:^5.90.0": + version: 5.93.0 + resolution: "webpack@npm:5.93.0" + dependencies: + "@types/eslint-scope": ^3.7.3 + "@types/estree": ^1.0.5 + "@webassemblyjs/ast": ^1.12.1 + "@webassemblyjs/wasm-edit": ^1.12.1 + "@webassemblyjs/wasm-parser": ^1.12.1 + acorn: ^8.7.1 + acorn-import-attributes: ^1.9.5 + browserslist: ^4.21.10 + chrome-trace-event: ^1.0.2 + enhanced-resolve: ^5.17.0 + es-module-lexer: ^1.2.1 + eslint-scope: 5.1.1 + events: ^3.2.0 + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.2.11 + json-parse-even-better-errors: ^2.3.1 + loader-runner: ^4.2.0 + mime-types: ^2.1.27 + neo-async: ^2.6.2 + schema-utils: ^3.2.0 + tapable: ^2.1.1 + terser-webpack-plugin: ^5.3.10 + watchpack: ^2.4.1 + webpack-sources: ^3.2.3 + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: c93bd73d9e1ab49b07e139582187f1c3760ee2cf0163b6288fab2ae210e39e59240a26284e7e5d29bec851255ef4b43c51642c882fa5a94e16ce7cb906deeb47 + languageName: node + linkType: hard + +"whatwg-mimetype@npm:^2.3.0": + version: 2.3.0 + resolution: "whatwg-mimetype@npm:2.3.0" + checksum: 23eb885940bcbcca4ff841c40a78e9cbb893ec42743993a42bf7aed16085b048b44b06f3402018931687153550f9a32d259dfa524e4f03577ab898b6965e5383 + languageName: node + linkType: hard + +"whatwg-url@npm:^8.0.0": + version: 8.7.0 + resolution: "whatwg-url@npm:8.7.0" + dependencies: + lodash: ^4.7.0 + tr46: ^2.1.0 + webidl-conversions: ^6.1.0 + checksum: a87abcc6cefcece5311eb642858c8fdb234e51ec74196bfacf8def2edae1bfbffdf6acb251646ed6301f8cee44262642d8769c707256125a91387e33f405dd1e + languageName: node + linkType: hard + +"which-boxed-primitive@npm:^1.0.2": + version: 1.0.2 + resolution: "which-boxed-primitive@npm:1.0.2" + dependencies: + is-bigint: ^1.0.1 + is-boolean-object: ^1.1.0 + is-number-object: ^1.0.4 + is-string: ^1.0.5 + is-symbol: ^1.0.3 + checksum: 53ce774c7379071729533922adcca47220228405e1895f26673bbd71bdf7fb09bee38c1d6399395927c6289476b5ae0629863427fd151491b71c4b6cb04f3a5e + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15": + version: 1.1.15 + resolution: "which-typed-array@npm:1.1.15" + dependencies: + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.2 + checksum: 65227dcbfadf5677aacc43ec84356d17b5500cb8b8753059bb4397de5cd0c2de681d24e1a7bd575633f976a95f88233abfd6549c2105ef4ebd58af8aa1807c75 + languageName: node + linkType: hard + +"which@npm:^1.2.9": + version: 1.3.1 + resolution: "which@npm:1.3.1" + dependencies: + isexe: ^2.0.0 + bin: + which: ./bin/which + checksum: f2e185c6242244b8426c9df1510e86629192d93c1a986a7d2a591f2c24869e7ffd03d6dac07ca863b2e4c06f59a4cc9916c585b72ee9fa1aa609d0124df15e04 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: ^2.0.0 + bin: + node-which: ./bin/node-which + checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: ^3.1.1 + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + +"wildcard@npm:^2.0.0": + version: 2.0.1 + resolution: "wildcard@npm:2.0.1" + checksum: e0c60a12a219e4b12065d1199802d81c27b841ed6ad6d9d28240980c73ceec6f856771d575af367cbec2982d9ae7838759168b551776577f155044f5a5ba843c + languageName: node + linkType: hard + +"word-wrap@npm:^1.2.5": + version: 1.2.5 + resolution: "word-wrap@npm:1.2.5" + checksum: f93ba3586fc181f94afdaff3a6fef27920b4b6d9eaefed0f428f8e07adea2a7f54a5f2830ce59406c8416f033f86902b91eb824072354645eea687dff3691ccb + languageName: node + linkType: hard + +"worker-loader@npm:^3.0.2": + version: 3.0.8 + resolution: "worker-loader@npm:3.0.8" + dependencies: + loader-utils: ^2.0.0 + schema-utils: ^3.0.0 + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + checksum: 84f4a7eeb2a1d8b9704425837e017c91eedfae67ac89e0b866a2dcf283323c1dcabe0258196278b7d5fd0041392da895c8a0c59ddf3a94f1b2e003df68ddfec3 + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: ^6.1.0 + string-width: ^5.0.1 + strip-ansi: ^7.0.1 + checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 + languageName: node + linkType: hard + +"write-file-atomic@npm:^4.0.2": + version: 4.0.2 + resolution: "write-file-atomic@npm:4.0.2" + dependencies: + imurmurhash: ^0.1.4 + signal-exit: ^3.0.7 + checksum: 5da60bd4eeeb935eec97ead3df6e28e5917a6bd317478e4a85a5285e8480b8ed96032bbcc6ecd07b236142a24f3ca871c924ec4a6575e623ec1b11bf8c1c253c + languageName: node + linkType: hard + +"ws@npm:^8.11.0": + version: 8.18.0 + resolution: "ws@npm:8.18.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 91d4d35bc99ff6df483bdf029b9ea4bfd7af1f16fc91231a96777a63d263e1eabf486e13a2353970efc534f9faa43bdbf9ee76525af22f4752cbc5ebda333975 + languageName: node + linkType: hard + +"y-protocols@npm:^1.0.5": + version: 1.0.6 + resolution: "y-protocols@npm:1.0.6" + dependencies: + lib0: ^0.2.85 + peerDependencies: + yjs: ^13.0.0 + checksum: 4b57c8811befcf2e45c3d47830005f8a33e626c734f78a42fe8a4fa3caad2233ba85a7c8bceefbd52ffc40130d3f3faee664fd0d1c324ff1fa8817a056ccdc1c + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 54f0fb95621ee60898a38c572c515659e51cc9d9f787fb109cef6fde4befbe1c4602dc999d30110feee37456ad0f1660fa2edcfde6a9a740f86a290999550d30 + languageName: node + linkType: hard + +"yallist@npm:^3.0.2": + version: 3.1.1 + resolution: "yallist@npm:3.1.1" + checksum: 48f7bb00dc19fc635a13a39fe547f527b10c9290e7b3e836b9a8f1ca04d4d342e85714416b3c2ab74949c9c66f9cebb0473e6bc353b79035356103b47641285d + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 + languageName: node + linkType: hard + +"yargs-parser@npm:^21.0.1, yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c + languageName: node + linkType: hard + +"yargs@npm:^17.3.1": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: ^8.0.1 + escalade: ^3.1.1 + get-caller-file: ^2.0.5 + require-directory: ^2.1.1 + string-width: ^4.2.3 + y18n: ^5.0.5 + yargs-parser: ^21.1.1 + checksum: 73b572e863aa4a8cbef323dd911d79d193b772defd5a51aab0aca2d446655216f5002c42c5306033968193bdbf892a7a4c110b0d77954a7fdf563e653967b56a + languageName: node + linkType: hard + +"yjs@npm:^13.5.40": + version: 13.6.18 + resolution: "yjs@npm:13.6.18" + dependencies: + lib0: ^0.2.86 + checksum: 5c9f8f31f5f9f30f17680a765b015e4274820fe10fb6bf6a7d39dee2ff0493a81ace02d11bff6f18c6799cade2bcfc9fc2d7b6ca8bc1eb167c4ac2f3789c0f01 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 + languageName: node + linkType: hard From b20780d152a13c775dd2915d8d8644b18f79862f Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 30 Sep 2024 13:06:09 -0700 Subject: [PATCH 015/133] Fix copyright for stitch package. Copyright headers now correctly pointing to Guidance Contributors. --- packages/python/stitch/LICENSE.txt | 2 +- packages/python/stitch/docs/source/conf.py | 6 +++--- packages/python/stitch/package.json | 4 ++-- packages/python/stitch/pyproject.toml | 4 ++-- packages/python/stitch/src/index.ts | 2 +- packages/python/stitch/src/plugin.ts | 2 +- packages/python/stitch/src/version.ts | 2 +- packages/python/stitch/src/widget.ts | 2 +- packages/python/stitch/stitch/__init__.py | 2 +- packages/python/stitch/stitch/_frontend.py | 2 +- packages/python/stitch/stitch/_version.py | 2 +- packages/python/stitch/stitch/stitch.py | 2 +- packages/python/stitch/stitch/tests/conftest.py | 2 +- packages/python/stitch/stitch/tests/test_example.py | 2 +- .../python/stitch/stitch/tests/test_nbextension_path.py | 2 +- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/python/stitch/LICENSE.txt b/packages/python/stitch/LICENSE.txt index 806ff2ed3..be5b7c6c6 100644 --- a/packages/python/stitch/LICENSE.txt +++ b/packages/python/stitch/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2024 nopdive +Copyright (c) 2024 Guidance Contributors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/packages/python/stitch/docs/source/conf.py b/packages/python/stitch/docs/source/conf.py index 540963ebd..d76c0c8ef 100644 --- a/packages/python/stitch/docs/source/conf.py +++ b/packages/python/stitch/docs/source/conf.py @@ -59,8 +59,8 @@ # General information about the project. project = 'stitch' -copyright = '2024, nopdive' -author = 'nopdive' +copyright = '2024, Guidance Contributors' +author = 'Guidance Contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -148,7 +148,7 @@ # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'stitch.tex', 'stitch Documentation', - 'nopdive', 'manual'), + 'Guidance Contributors', 'manual'), ] diff --git a/packages/python/stitch/package.json b/packages/python/stitch/package.json index e652191a5..90e06f562 100644 --- a/packages/python/stitch/package.json +++ b/packages/python/stitch/package.json @@ -19,8 +19,8 @@ }, "license": "BSD-3-Clause", "author": { - "name": "nopdive", - "email": "nopdive@gmail.com" + "name": "Guidance Contributors", + "email": "maintainers@guidance-ai.org" }, "main": "lib/index.js", "types": "./lib/index.d.ts", diff --git a/packages/python/stitch/pyproject.toml b/packages/python/stitch/pyproject.toml index 7b9b51630..032a04401 100644 --- a/packages/python/stitch/pyproject.toml +++ b/packages/python/stitch/pyproject.toml @@ -13,7 +13,7 @@ readme = "README.md" license = { file = "LICENSE.txt" } requires-python = ">=3.9" authors = [ - { name = "nopdive", email = "nopdive@gmail.com" }, + { name = "Guidance Maintainers", email = "maintainers@guidance-ai.org" }, ] keywords = [ "IPython", @@ -58,7 +58,7 @@ test = [ ] [project.urls] -Homepage = "https://github.com/guidance-ai/stitch" +Homepage = "https://github.com/guidance-ai/guidance" [tool.hatch.metadata] allow-direct-references = true diff --git a/packages/python/stitch/src/index.ts b/packages/python/stitch/src/index.ts index d9d81c9a7..182c4ca09 100644 --- a/packages/python/stitch/src/index.ts +++ b/packages/python/stitch/src/index.ts @@ -1,4 +1,4 @@ -// Copyright (c) nopdive +// Copyright (c) Guidance Contributors // Distributed under the terms of the Modified BSD License. export * from './version'; diff --git a/packages/python/stitch/src/plugin.ts b/packages/python/stitch/src/plugin.ts index 07ab72326..49bea2f54 100644 --- a/packages/python/stitch/src/plugin.ts +++ b/packages/python/stitch/src/plugin.ts @@ -1,4 +1,4 @@ -// Copyright (c) nopdive +// Copyright (c) Guidance Contributors // Distributed under the terms of the Modified BSD License. import { Application, IPlugin } from '@lumino/application'; diff --git a/packages/python/stitch/src/version.ts b/packages/python/stitch/src/version.ts index 7bf318155..eb22f91b3 100644 --- a/packages/python/stitch/src/version.ts +++ b/packages/python/stitch/src/version.ts @@ -1,4 +1,4 @@ -// Copyright (c) nopdive +// Copyright (c) Guidance Contributors // Distributed under the terms of the Modified BSD License. // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/packages/python/stitch/src/widget.ts b/packages/python/stitch/src/widget.ts index 267fd7f2d..558735316 100644 --- a/packages/python/stitch/src/widget.ts +++ b/packages/python/stitch/src/widget.ts @@ -1,4 +1,4 @@ -// Copyright (c) nopdive +// Copyright (c) Guidance Contributors // Distributed under the terms of the Modified BSD License. import { diff --git a/packages/python/stitch/stitch/__init__.py b/packages/python/stitch/stitch/__init__.py index 596e1a0e0..e984ee173 100644 --- a/packages/python/stitch/stitch/__init__.py +++ b/packages/python/stitch/stitch/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf-8 -# Copyright (c) nopdive. +# Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. from .stitch import StitchWidget diff --git a/packages/python/stitch/stitch/_frontend.py b/packages/python/stitch/stitch/_frontend.py index 880a63e74..4dcf81718 100644 --- a/packages/python/stitch/stitch/_frontend.py +++ b/packages/python/stitch/stitch/_frontend.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf-8 -# Copyright (c) nopdive. +# Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. """ diff --git a/packages/python/stitch/stitch/_version.py b/packages/python/stitch/stitch/_version.py index b56e345f8..618f06bdf 100644 --- a/packages/python/stitch/stitch/_version.py +++ b/packages/python/stitch/stitch/_version.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf-8 -# Copyright (c) nopdive. +# Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. version_info = (0, 1, 0, 'dev') diff --git a/packages/python/stitch/stitch/stitch.py b/packages/python/stitch/stitch/stitch.py index f383af105..66ebc29ab 100644 --- a/packages/python/stitch/stitch/stitch.py +++ b/packages/python/stitch/stitch/stitch.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf-8 -# Copyright (c) nopdive. +# Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. """ diff --git a/packages/python/stitch/stitch/tests/conftest.py b/packages/python/stitch/stitch/tests/conftest.py index 44382d8c1..ad3bd1758 100644 --- a/packages/python/stitch/stitch/tests/conftest.py +++ b/packages/python/stitch/stitch/tests/conftest.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf-8 -# Copyright (c) nopdive. +# Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. import pytest diff --git a/packages/python/stitch/stitch/tests/test_example.py b/packages/python/stitch/stitch/tests/test_example.py index dfce827e2..46fed8f90 100644 --- a/packages/python/stitch/stitch/tests/test_example.py +++ b/packages/python/stitch/stitch/tests/test_example.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf-8 -# Copyright (c) nopdive. +# Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. import pytest diff --git a/packages/python/stitch/stitch/tests/test_nbextension_path.py b/packages/python/stitch/stitch/tests/test_nbextension_path.py index 56a2cbe41..c134480ab 100644 --- a/packages/python/stitch/stitch/tests/test_nbextension_path.py +++ b/packages/python/stitch/stitch/tests/test_nbextension_path.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding: utf-8 -# Copyright (c) nopdive. +# Copyright (c) Guidance Contributors. # Distributed under the terms of the Modified BSD License. From a8a0f06697e749ec8c4ff96237e62cbd04ba7ad6 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 30 Sep 2024 14:36:13 -0700 Subject: [PATCH 016/133] Serialization for trace. Minor fixes. Trace messages are now JSON serializable. Some minor fixes like adding a manifest for package. --- MANIFEST.in | 1 + guidance/models/_model.py | 1 - guidance/trace/_trace.py | 14 ++++++++++++-- guidance/visual/_message.py | 7 +++---- guidance/visual/_renderer.py | 20 +++++++++----------- setup.py | 2 +- 6 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..176d59d7b --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include resources/graphpaper-inline.html \ No newline at end of file diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 370a87ed8..7f6bd122b 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -413,7 +413,6 @@ def _update_trace_node(self, identifier: int, parent_id: Optional[int], node_att TraceMessage( trace_id=identifier, parent_trace_id=parent_id, - trace_node=trace_node, node_attr=node_attr, ) ) diff --git a/guidance/trace/_trace.py b/guidance/trace/_trace.py index 1b459db23..bdee4bddc 100644 --- a/guidance/trace/_trace.py +++ b/guidance/trace/_trace.py @@ -12,6 +12,11 @@ class NodeAttr(BaseModel): """Attributes of a trace node.""" + class_name: str = "" + + def __init__(self, **kwargs): + kwargs["class_name"] = self.__class__.__name__ + super().__init__(**kwargs) def __repr__(self): return pydantic_no_default_repr(self) @@ -35,7 +40,8 @@ class OutputAttr(NodeAttr): class StatelessGuidanceInput(InputAttr): """Stateless guidance input (light wrapper).""" - value: Any + # NOTE(nopdive): Open to debate what we should serialize here, excluding for now. + value: Any = Field(exclude=True) def __repr__(self): return f"{self.__class__.__name__}({self.value})" @@ -44,7 +50,8 @@ def __repr__(self): class StatefulGuidanceInput(InputAttr): """Stateful guidance input (light wrapper).""" - value: Any + # NOTE(nopdive): Open to debate what we should serialize here, excluding for now. + value: Any = Field(exclude=True) def __repr__(self): return f"{self.__class__.__name__}({self.value})" @@ -221,6 +228,9 @@ class TraceHandler(BaseModel): id_node_map: Dict[int, TraceNode] = {} node_id_map: Dict[TraceNode, int] = {} + def __getitem__(self, item): + return self.id_node_map[item] + def update_node( self, identifier: int, parent_id: Optional[int], node_attr: Optional[NodeAttr] = None ) -> TraceNode: diff --git a/guidance/visual/_message.py b/guidance/visual/_message.py index 6f7866d55..bc14b46f0 100644 --- a/guidance/visual/_message.py +++ b/guidance/visual/_message.py @@ -1,20 +1,19 @@ from typing import Optional from pydantic import BaseModel -from ..trace import NodeAttr, TraceNode +from ..trace import NodeAttr class Message(BaseModel): - message_type: str = "" + class_name: str = "" def __init__(self, **kwargs): - kwargs["message_type"] = self.__class__.__name__ + kwargs["class_name"] = self.__class__.__name__ super().__init__(**kwargs) class TraceMessage(Message): trace_id: int parent_trace_id: Optional[int] - trace_node: TraceNode node_attr: Optional[NodeAttr] diff --git a/guidance/visual/_renderer.py b/guidance/visual/_renderer.py index abb2897ba..774a921bf 100644 --- a/guidance/visual/_renderer.py +++ b/guidance/visual/_renderer.py @@ -42,11 +42,10 @@ def __init__(self, trace_handler: TraceHandler): def update(self, message: Message) -> RenderUpdate: if not isinstance(message, TraceMessage): return RenderUpdate() + logger.debug(f"MSG:raw:{message}") + logger.debug(f"MSG:json:{message.model_dump_json(serialize_as_any=True)}") - # if type(message.node_attr) not in [TextOutput, RoleOpenerInput, RoleCloserInput]: - # return RenderUpdate() - - trace_node = message.trace_node + trace_node = self._trace_handler[message.trace_id] need_reset = False need_new_display = False @@ -60,7 +59,7 @@ def update(self, message: Message) -> RenderUpdate: last_trace_message = next( x for x in reversed(self._messages) if isinstance(x, TraceMessage) ) - last_trace_node = last_trace_message.trace_node + last_trace_node = self._trace_handler[last_trace_message.trace_id] if trace_node not in last_trace_node.path(): logger.debug(f"NEED_RESET:divergence:{last_trace_node}:{trace_node}") @@ -71,7 +70,7 @@ def update(self, message: Message) -> RenderUpdate: ancestors = set(trace_node.ancestors()) for idx, prev_message in enumerate(self._messages): if isinstance(prev_message, TraceMessage): - if prev_message.trace_node in ancestors: + if self._trace_handler[prev_message.trace_id] in ancestors: ancestor_idx = idx if ancestor_idx == -1: logger.debug(f"PARENT_NOT_FOUND:{trace_node}") @@ -118,16 +117,16 @@ class LegacyHtmlRenderer(Renderer): """Original HTML renderer for guidance.""" def __init__(self, trace_handler: TraceHandler) -> None: - pass + self._trace_handler = trace_handler def update(self, message: Message) -> None: if not isinstance(message, TraceMessage): return - last_trace_node = message.trace_node - if last_trace_node is not None: + trace_node = self._trace_handler[message.trace_id] + if trace_node is not None: clear_output(wait=True) - display(HTML(trace_node_to_html(last_trace_node, prettify_roles=False))) + display(HTML(trace_node_to_html(trace_node, prettify_roles=False))) def _create_stitch_widget(): @@ -165,7 +164,6 @@ def update(self, message: Message) -> None: for out_message in display_update.messages: message_json = out_message.model_dump_json(indent=2) - logger.debug(f"OUT_MSG: {message_json}") self._jupyter_widget.kernelmsg = message_json diff --git a/setup.py b/setup.py index 7ab61e72a..b30a19d72 100644 --- a/setup.py +++ b/setup.py @@ -37,6 +37,7 @@ "openai": ["openai>=1.0"], "schemas": ["jsonschema"], "server": ["fastapi-slim", "uvicorn"], + "visual": ["stitch"], # TODO(nopdive): Shouldn't this be a core requirement? } # Create the union of all our requirements @@ -70,7 +71,6 @@ "types-regex", "types-requests", "types-jsonschema", - "anytree", ] bench_requires = [ "pandas", From a65379b58d38863d7968ef9ca353d415f0580c1d Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Mon, 30 Sep 2024 16:00:21 -0700 Subject: [PATCH 017/133] WIP messaging in client. Client has a race condition where it skips messages that have been fired by stitch before it loads. --- client/graphpaper-inline/build-to-guidance.sh | 5 + client/graphpaper-inline/src/App.svelte | 33 ++--- client/graphpaper-inline/src/TokenGrid.svelte | 113 +++++++++--------- client/graphpaper-inline/src/stitch.ts | 44 ++++--- guidance/models/_model.py | 2 +- guidance/resources/graphpaper-inline.html | 2 +- guidance/visual/__init__.py | 2 +- guidance/visual/_message.py | 6 +- guidance/visual/_renderer.py | 28 ++--- notebooks/unstable/State Debugging.ipynb | 43 ++++--- tests/unit/test_model.py | 12 -- tests/visual/test_e2e.py | 14 +++ 12 files changed, 157 insertions(+), 147 deletions(-) create mode 100644 client/graphpaper-inline/build-to-guidance.sh diff --git a/client/graphpaper-inline/build-to-guidance.sh b/client/graphpaper-inline/build-to-guidance.sh new file mode 100644 index 000000000..4b71d7f04 --- /dev/null +++ b/client/graphpaper-inline/build-to-guidance.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -x + +npm run build +cp dist/index.html ../../guidance/resources/graphpaper-inline.html \ No newline at end of file diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 1a565cd23..96da862a4 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -3,17 +3,18 @@ import Minibar from './Minibar.svelte'; import TokenGrid from './TokenGrid.svelte'; import ResizeListener from './ResizeListener.svelte'; - import { kernelmsg, type StitchMessage } from './stitch'; + import { kernelmsg, type TextOutput, type TraceMessage } from './stitch'; import StitchHandler from './StitchHandler.svelte'; let msg: any; - let tokens: string[] = []; + let tokens: Array = []; $: if ($kernelmsg !== undefined) { msg = JSON.parse($kernelmsg.content); + console.log(msg); - if (msg.message_type === "ModelUpdateMessage") { - tokens.push(msg); - } else if (msg.message_type === "ModelResetMessage") { + if (msg.class_name === "TraceMessage" && msg.node_attr?.class_name === "TextOutput") { + tokens.push(msg.node_attr); + } else if (msg.class_name === "ResetDisplayMessage") { tokens = []; } tokens = tokens; @@ -67,20 +68,6 @@ 'desc': 'How expected the emitted sequence of tokens is relative to the language model.', }, ] - const ctxTokenCandidates = [ - { - 'id': 15042, - 'token': 'liquor ', - }, - { - 'id': 59108, - 'token': 'jugs', - }, - { - 'id': 89734, - 'token': ' valued', - }, - ]; const padding = { 'left': 0, 'right': 0, @@ -101,12 +88,12 @@
- +
\ No newline at end of file diff --git a/client/graphpaper-inline/src/TokenGrid.svelte b/client/graphpaper-inline/src/TokenGrid.svelte index a4dae79e0..5a1007e81 100644 --- a/client/graphpaper-inline/src/TokenGrid.svelte +++ b/client/graphpaper-inline/src/TokenGrid.svelte @@ -1,110 +1,85 @@
- {#each nodeAttrs as nodeAttr, i} - {#if nodeAttr.class_name === 'RoleOpenerInput'} - - - - - - - - - - - - - - - - - - - - {:else if nodeAttr.class_name === 'RoleCloserInput'} - - {:else if nodeAttr.class_name === 'TextOutput'} - {#if nodeAttr.value.match(imagePattern)} - - inlined img - - - - - - - - - - - - - - - - - + {#each tokens as token, i} + {#if token.special === true} + {#if token.role !== ""} + + {#if i === 0} +
+ {:else} + {#each {length: 2} as _} + +   + {/each} + + {/if} - - - - - - - - - - - - + + + + {token.role} + + + {:else} - - {#each nodeAttr.value as ch} - {#if ch === ' '} - -   - - {:else if ch === '\t'} - - \t   - - {:else if ch === '\n'} - - \n - -
- {:else} - - {ch} - - {/if} - {/each} + + + + + {/if} + {:else if token.special === false} + + {/if} {/each} - - - + {#if isCompleted === false} + +   + + {/if}
\ No newline at end of file diff --git a/client/graphpaper-inline/src/TokenGridItem.svelte b/client/graphpaper-inline/src/TokenGridItem.svelte new file mode 100644 index 000000000..7c62448ff --- /dev/null +++ b/client/graphpaper-inline/src/TokenGridItem.svelte @@ -0,0 +1,30 @@ + + +{#each token.value as ch} + {#if ch === ' '} + +   + + {:else if ch === '\t'} + + \t   + + {:else if ch === '\n'} + + \n + +
+ {:else} + + {ch} + + {/if} +{/each} \ No newline at end of file diff --git a/client/graphpaper-inline/src/mocks.ts b/client/graphpaper-inline/src/mocks.ts index 5ede381dd..8f57ac109 100644 --- a/client/graphpaper-inline/src/mocks.ts +++ b/client/graphpaper-inline/src/mocks.ts @@ -13,7 +13,7 @@ const textToNodeAttrs = (texts: Array) => { const roleOpenerInput: RoleOpenerInput = { class_name: 'RoleOpenerInput', name: 'system', - text: "<|system|>\n", + text: "<|system|>", } activeRole = 'system'; results.push(roleOpenerInput); @@ -21,7 +21,7 @@ const textToNodeAttrs = (texts: Array) => { const roleOpenerInput: RoleOpenerInput = { class_name: 'RoleOpenerInput', name: 'assistant', - text: "<|assistant|>\n", + text: "<|assistant|>", } activeRole = 'user'; results.push(roleOpenerInput); @@ -29,7 +29,7 @@ const textToNodeAttrs = (texts: Array) => { const roleOpenerInput: RoleOpenerInput = { class_name: 'RoleOpenerInput', name: 'user', - text: "<|user|>\n", + text: "<|user|>", } activeRole = 'user'; results.push(roleOpenerInput); @@ -40,7 +40,7 @@ const textToNodeAttrs = (texts: Array) => { const roleCloserInput: RoleCloserInput = { class_name: 'RoleCloserInput', name: activeRole, - text: "<|end|>\n", + text: "<|end|>", } activeRole = undefined; results.push(roleCloserInput); @@ -70,4 +70,4 @@ text += " <|end|>\n" // text += "A language model is a probabilistic model of a natural language.[1]\nIn 1980, the first significant statistical language model was proposed, and during the decade IBM performed Shannon-style experiments, in which potential sources for language modeling improvement were identified by observing and analyzing the performance of human subjects in predicting or correcting text.[2] Language models are useful for a variety of tasks, including speech recognition[3] (helping prevent predictions of low-probability (e.g. nonsense) sequences), machine translation,[4] natural language generation (generating more human-like text), optical character recognition, handwriting recognition,[5] grammar induction,[6] and information retrieval.[7][8] Large language models, currently their most advanced form, are a combination of larger datasets (frequently using words scraped from the public internet), feedforward neural networks, and transformers. They have superseded recurrent neural network-based models, which had previously superseded the pure statistical models, such as word n-gram language model."; // text += " <|end|>\n <|endoftext|>" -export let mockTokens = textToNodeAttrs(text.match(/(\s+|\S+)/g) || []); \ No newline at end of file +export let mockTokens = textToNodeAttrs(text.match(/([\S]+|[\s]+)/g) || []); \ No newline at end of file diff --git a/client/graphpaper-inline/src/stitch.ts b/client/graphpaper-inline/src/stitch.ts index eb10d0691..bfcd01bfe 100644 --- a/client/graphpaper-inline/src/stitch.ts +++ b/client/graphpaper-inline/src/stitch.ts @@ -1,4 +1,4 @@ -import { writable } from 'svelte/store'; +import {writable} from 'svelte/store'; export interface NodeAttr { class_name: string @@ -64,6 +64,26 @@ export interface StitchMessage { content: any } +export function isTraceMessage(o: NodeAttr | undefined): o is TraceMessage { + if (o === undefined) return false; + return o.class_name === "TraceMessage"; +} + +export function isRoleOpenerInput(o: NodeAttr | undefined): o is RoleOpenerInput { + if (o === undefined) return false; + return o.class_name === "RoleOpenerInput"; +} + +export function isRoleCloserInput(o: NodeAttr | undefined): o is RoleOpenerInput { + if (o === undefined) return false; + return o.class_name === "RoleCloserInput"; +} + +export function isTextOutput(o: NodeAttr | undefined): o is TextOutput { + if (o === undefined) return false; + return o.class_name === "TextOutput"; +} export const kernelmsg = writable(undefined); -export const clientmsg = writable(undefined); \ No newline at end of file +export const clientmsg = writable(undefined); + From 661761550d035bd99972ad632fc3c44d93ae0380 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Tue, 8 Oct 2024 15:50:54 -0700 Subject: [PATCH 046/133] Fix more-than-two-tokens need to be merged to single token in state string --- guidance/models/_model.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 063a55966..e523acfca 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -205,10 +205,19 @@ def _msg_recv(self, message: GuidanceMessage) -> None: continue # we have a mismatch due to backtracking - next_gen_token = gen_tokens.pop(0) - merged_text = gen_token.text + next_gen_token.text + # next_gen_token = gen_tokens.pop(0) + # merged_text = gen_token.text + next_gen_token.text + # merged_tokens = self.tokenizer.encode(merged_text.encode("utf-8")) + # assert len(merged_tokens) == 1, f"Expected merged tokens to be of length 1, got {len(merged_tokens)}" + + merged_text = gen_token.text + token_text = self.tokenizer.decode([tokens[idx]]).decode("utf-8") + while len(merged_text) < len(token_text) and token_text.startswith(merged_text): + next_gen_token = gen_tokens.pop(0) + merged_text += next_gen_token.text + + assert token_text == merged_text, f"Expected merged text to be {token_text}, got {merged_text}" merged_tokens = self.tokenizer.encode(merged_text.encode("utf-8")) - assert len(merged_tokens) == 1, f"Expected merged tokens to be of length 1, got {len(merged_tokens)}" if tokens[idx] == merged_tokens[0]: # create new GenToken @@ -420,7 +429,8 @@ def get_top_k(_probs: np.ndarray, _k: int = 5) -> list[GenToken]: # compute top-k with masking masked_top_k: list[GenToken] = [] if mask is not None: - masked_logits = np.abs(_logits * np.frombuffer(mask, dtype=np.uint8)) + # shift logits to [0 - max] range first and apply mask + masked_logits = (_logits - np.min(_logits)) * np.frombuffer(mask, dtype=np.uint8) masked_probs = ( softmax(masked_logits) if temperature < 0.0001 From 4080cfdc0672746d265e8fc5fc166b955e92fb9f Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 8 Oct 2024 21:59:54 -0700 Subject: [PATCH 047/133] Mouse hover now works correctly on text. Hover now highlights correct chunks / tokens. --- client/graphpaper-inline/src/TokenGrid.svelte | 57 +++++++++---------- .../src/TokenGridItem.svelte | 23 ++++++-- client/graphpaper-inline/src/mocks.ts | 3 + client/graphpaper-inline/src/stitch.ts | 3 +- guidance/resources/graphpaper-inline.html | 2 +- 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/client/graphpaper-inline/src/TokenGrid.svelte b/client/graphpaper-inline/src/TokenGrid.svelte index 5a1007e81..98ac78383 100644 --- a/client/graphpaper-inline/src/TokenGrid.svelte +++ b/client/graphpaper-inline/src/TokenGrid.svelte @@ -13,17 +13,24 @@ export let isCompleted: boolean = false; let tokens: Array = []; - $: { let activeOpenerRoles: Array = []; + let activeCloserRoleText: Array = []; + for (let nodeAttr of nodeAttrs) { - console.log(nodeAttr); if (isRoleOpenerInput(nodeAttr)) { activeOpenerRoles.push(nodeAttr); + activeCloserRoleText.push(nodeAttr.closer_text || ""); } else if (isTextOutput(nodeAttr)) { if (activeOpenerRoles.length === 0) { - const token = {value: nodeAttr.value, prob: 1, role: "", special: false}; - tokens.push(token); + if (activeCloserRoleText.length !== 0 && activeCloserRoleText[activeCloserRoleText.length - 1] === nodeAttr.value) { + const token = {value: nodeAttr.value, prob: 1, role: "", special: true}; + tokens.push(token); + activeCloserRoleText.pop(); + } else { + const token = {value: nodeAttr.value, prob: 1, role: "", special: false}; + tokens.push(token); + } } else { const activeOpenerRole = activeOpenerRoles[activeOpenerRoles.length - 1]; if (activeOpenerRole.text && activeOpenerRole.text !== nodeAttr.value) { @@ -35,7 +42,12 @@ } } } + if (activeOpenerRoles.length !== 0 || activeCloserRoleText.length !== 0) { + console.log("Opener and closer role texts did not balance.") + } + tokens = tokens; } +
@@ -43,38 +55,21 @@
{#each tokens as token, i} - {#if token.special === true} - {#if token.role !== ""} - - {#if i === 0} -
- {:else} - {#each {length: 2} as _} - -   - {/each} - - {/if} - - - - - {token.role} - - - + {#if token.special === true && token.role !== ""} + + {#if i === 0} +
{:else} - + {#each {length: 2} as _} + +   + {/each} - - - {/if} - {:else if token.special === false} - - {/if} + {/each} + {#if isCompleted === false}   diff --git a/client/graphpaper-inline/src/TokenGridItem.svelte b/client/graphpaper-inline/src/TokenGridItem.svelte index 7c62448ff..478dedc8a 100644 --- a/client/graphpaper-inline/src/TokenGridItem.svelte +++ b/client/graphpaper-inline/src/TokenGridItem.svelte @@ -6,24 +6,37 @@ const color = (x: number) => { return scaleSequential(interpolateSpectral)(1.0 - x) }; + + let hovered: boolean = false; + const handleMouseEnter = () => { + hovered = true; + } + const handleMouseLeave = () => { + hovered = false; + } -{#each token.value as ch} +{#each token.value as ch, i} {#if ch === ' '} - +   {:else if ch === '\t'} - + \t   {:else if ch === '\n'} - + \n
{:else} - + + {#if i === 0} + + {token.role} + + {/if} {ch} {/if} diff --git a/client/graphpaper-inline/src/mocks.ts b/client/graphpaper-inline/src/mocks.ts index 8f57ac109..0260ede33 100644 --- a/client/graphpaper-inline/src/mocks.ts +++ b/client/graphpaper-inline/src/mocks.ts @@ -14,6 +14,7 @@ const textToNodeAttrs = (texts: Array) => { class_name: 'RoleOpenerInput', name: 'system', text: "<|system|>", + closer_text: "<|end|>", } activeRole = 'system'; results.push(roleOpenerInput); @@ -22,6 +23,7 @@ const textToNodeAttrs = (texts: Array) => { class_name: 'RoleOpenerInput', name: 'assistant', text: "<|assistant|>", + closer_text: "<|end|>", } activeRole = 'user'; results.push(roleOpenerInput); @@ -30,6 +32,7 @@ const textToNodeAttrs = (texts: Array) => { class_name: 'RoleOpenerInput', name: 'user', text: "<|user|>", + closer_text: "<|end|>", } activeRole = 'user'; results.push(roleOpenerInput); diff --git a/client/graphpaper-inline/src/stitch.ts b/client/graphpaper-inline/src/stitch.ts index bfcd01bfe..374d3b142 100644 --- a/client/graphpaper-inline/src/stitch.ts +++ b/client/graphpaper-inline/src/stitch.ts @@ -16,6 +16,7 @@ export interface RoleOpenerInput extends NodeAttr { class_name: 'RoleOpenerInput', name?: string, text?: string, + closer_text?: string, } export interface RoleCloserInput extends NodeAttr { @@ -74,7 +75,7 @@ export function isRoleOpenerInput(o: NodeAttr | undefined): o is RoleOpenerInput return o.class_name === "RoleOpenerInput"; } -export function isRoleCloserInput(o: NodeAttr | undefined): o is RoleOpenerInput { +export function isRoleCloserInput(o: NodeAttr | undefined): o is RoleCloserInput { if (o === undefined) return false; return o.class_name === "RoleCloserInput"; } diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index 40b7e8600..051b7a2b9 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,7 +9,7 @@ From a80d95ac50b9c6966c5ec878b3f36a573e1bfdf5 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 8 Oct 2024 22:13:28 -0700 Subject: [PATCH 048/133] Minor style change on token grid items. --- client/graphpaper-inline/src/TokenGridItem.svelte | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/graphpaper-inline/src/TokenGridItem.svelte b/client/graphpaper-inline/src/TokenGridItem.svelte index 478dedc8a..0a4ac3078 100644 --- a/client/graphpaper-inline/src/TokenGridItem.svelte +++ b/client/graphpaper-inline/src/TokenGridItem.svelte @@ -18,20 +18,20 @@ {#each token.value as ch, i} {#if ch === ' '} - +   {:else if ch === '\t'} - + \t   {:else if ch === '\n'} - + \n
{:else} - + {#if i === 0} {token.role} From 6dc22c348cd4e604a298e1aef9f161c19172b76d Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Wed, 9 Oct 2024 13:42:19 -0700 Subject: [PATCH 049/133] Tooltip & highlight groundwork done. Still need to hook up tooltip to token information. --- client/graphpaper-inline/rollup.config.mjs | 2 +- client/graphpaper-inline/src/App.svelte | 1 + client/graphpaper-inline/src/TokenGrid.svelte | 92 ++++++++++++++++++- .../src/TokenGridItem.svelte | 18 ++-- client/graphpaper-inline/src/longhover.ts | 26 ++++++ client/graphpaper-inline/src/mocks.ts | 3 +- client/graphpaper-inline/src/stitch.ts | 16 ++-- 7 files changed, 131 insertions(+), 27 deletions(-) create mode 100644 client/graphpaper-inline/src/longhover.ts diff --git a/client/graphpaper-inline/rollup.config.mjs b/client/graphpaper-inline/rollup.config.mjs index 64ba8af66..ff60f8b76 100644 --- a/client/graphpaper-inline/rollup.config.mjs +++ b/client/graphpaper-inline/rollup.config.mjs @@ -21,6 +21,7 @@ export default [{ sourcemap: !production, }, plugins: [ + typescript(), svelte({ compilerOptions: { dev: !production @@ -33,7 +34,6 @@ export default [{ extensions: ['.svelte', '.mjs', '.ts', '.js', '.json', '.node'] }), commonjs(), - typescript(), postcss(), copy({ targets: [ diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 79515b3c8..172224c58 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -55,6 +55,7 @@ nodeAttrs = nodeAttrs; } } + nodeAttrs = mockTokens; // TODO(nopdive): Restrict metrics while updating style. diff --git a/client/graphpaper-inline/src/TokenGrid.svelte b/client/graphpaper-inline/src/TokenGrid.svelte index 98ac78383..9f4c08273 100644 --- a/client/graphpaper-inline/src/TokenGrid.svelte +++ b/client/graphpaper-inline/src/TokenGrid.svelte @@ -1,6 +1,9 @@ + + + +
+ {tooltipText} +
+
- + {#each tokens as token, i} {#if token.special === true && token.role !== ""} @@ -67,7 +151,7 @@ {/if} {/if} - + {/each} {#if isCompleted === false} diff --git a/client/graphpaper-inline/src/TokenGridItem.svelte b/client/graphpaper-inline/src/TokenGridItem.svelte index 0a4ac3078..8d1055cba 100644 --- a/client/graphpaper-inline/src/TokenGridItem.svelte +++ b/client/graphpaper-inline/src/TokenGridItem.svelte @@ -3,35 +3,29 @@ import {interpolateSpectral} from "d3-scale-chromatic"; export let token; + export let index; + const color = (x: number) => { return scaleSequential(interpolateSpectral)(1.0 - x) }; - - let hovered: boolean = false; - const handleMouseEnter = () => { - hovered = true; - } - const handleMouseLeave = () => { - hovered = false; - } {#each token.value as ch, i} {#if ch === ' '} - +   {:else if ch === '\t'} - + \t   {:else if ch === '\n'} - + \n
{:else} - + {#if i === 0} {token.role} diff --git a/client/graphpaper-inline/src/longhover.ts b/client/graphpaper-inline/src/longhover.ts new file mode 100644 index 000000000..4b3d0646f --- /dev/null +++ b/client/graphpaper-inline/src/longhover.ts @@ -0,0 +1,26 @@ +export function longhover(node: HTMLElement, duration: number) { + let timer: any; + + const handleMouseOver = (event: MouseEvent) => { + timer = setTimeout(() => { + node.dispatchEvent(new CustomEvent('longmouseover', {detail: event})); + }, duration); + }; + const handleMouseOut = (event: MouseEvent) => { + clearTimeout(timer); + node.dispatchEvent(new CustomEvent('longmouseout', {detail: event})); + } + + node.addEventListener('mouseover', handleMouseOver); + node.addEventListener('mouseout', handleMouseOut); + + return { + update(newDuration: number) { + duration = newDuration + }, + destroy() { + node.removeEventListener('mouseover', handleMouseOver); + node.removeEventListener('mouseout', handleMouseOut); + } + }; +} diff --git a/client/graphpaper-inline/src/mocks.ts b/client/graphpaper-inline/src/mocks.ts index 0260ede33..d3be0f696 100644 --- a/client/graphpaper-inline/src/mocks.ts +++ b/client/graphpaper-inline/src/mocks.ts @@ -60,7 +60,6 @@ const textToNodeAttrs = (texts: Array) => { results.push(textOutput); } - console.log(results); return results; } @@ -68,7 +67,7 @@ let text = "Pack my box with five dozen liquor jugs valued at $12.95, according // text += "\n<-img:/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCACWAGQDASIAAhEBAxEB/8QAHQAAAQUBAQEBAAAAAAAAAAAABQADBAYHAggBCf/EAEMQAAEDAwMCBAIIAgcGBwAAAAECAwQABREGEiExQQcTIlFhcQgUFSMygaGxM5EWFyRCUnLBQ3OCotHwGCZFY3aywv/EABoBAAIDAQEAAAAAAAAAAAAAAAIDAAEEBQb/xAAtEQACAQMDAgMIAwEAAAAAAAAAAQIDESEEEjEiQQVRcRNhkaGx0eHwFIHB8f/aAAwDAQACEQMRAD8A9YQ/LcSCgg0QbaBoOyypGFJJB+FEY8xbZw+nI9xSkEychgGnkxx2TX2M8y8AULB/OpyG0nsKNK5VyImOa+/V8daIBpOK4dehsDL0lpv/ADLA/ersUQvJA5peVjtivjt+sTfBuTKj7IO8/pmoj2pbYjPlMyXfiGSB/wA2KmC8kzyxSKQngmgUnVoAPkW9ZwRnLicjPwBNDn9UXFZ+7iNp/wAyiarckWk2W30fCvh8s8ZFUhy9XpwcPNo/yo/61HVMuzp9dwe/4Tj9qreTaX0soJyCKVZ6pEhZ3KkvKPuXFf8AWlU3l7S0NpA4p4NpPU120zlQGKNQbW2+BuSDmq2g3K7IjPJSVx1qSrHVJ5qkSdfSLW+zCnyrzJkyEKdQ3DjqUNoKh1QnA/DjBOa3RvTsIRnnVoAKWlkfPBqh2BuO7oS1uuJTuVfQlRJ6pBTwfhyajTTJcpCdYXea2Fx9B6qfChkKlgR0kfN1wftX1+XrlwufZuk7GylPR6RcA5ke+1tJP61afDLw/Ra7/fLvdHLbb4kyQJdrckvokq+sBTja1FKyottqRt+7wAFJ3Dqc2i4T5Rt2oYj+oGC7MQlqKzHQksNkABSwepOSFdx6SPakVKsoVFCMbp9/IV7R3tYzK12XxU1F5UeJe7YxIdClhqHbXXvuxgZBURznIOfhUFuwXd67PW65ar1DKciyFxJCWYLMVhDyWysoU6o8YHOc9Rj4Vo1hcsEfT7ka7zZHnAhbBawlQyeRuPwz8D0qLpy4adtV0myrgEiG44l5qKwvcVuJ4BcUrjGOcBPJPJwORnUrOeyEVbzf2x8bv0ZU5VE7RRWLNpqLp1VwiMyp0haHWW1qkTUyE/hCxsKfSnhfIHeiKmx1AqddF2xx+XJtilkS5y5Kwv8Au7toSkY4GAntUbFOjust3I+nfbkYLYxwK42D2qSpNcFNEGMbBSp3B7ClUIWhCxuyO1FIc5TYwnJxQxtoqUAKPW2EMDIzTRR9lXGeuI4lhKxlCs/LFZxaIUyXpGDsfU005ciylST0WVdf1FbQ1CQITytg/hL7fA1lWmyE6EsY7rv5A/mD/pQS5LRIsehL5f7cLi0w+jeQG2n5p3uArUncNiCMApOeeMVOuHhfdbPGnTbsxGaZhhOFeY655xUeAk8D88dqv+gpa2LDFTISnfDU6/FcKsJKFPL3tEA9e4JHxo7reemTpi7uNuoVFVEGw8epZI6H5UhSvJpvhgrczBW7Qp2IbiFxm4zTPmPkx/NdKt+PSCsA8Hp1zQt0EQvtCPqNlpjzkMJUi3NguKUdo2pUCSSojgZ4zkjpV30lpJ/VjbTCFOeQygl9KFAFSFKAI578cEDIoXqeE6JLmjdOS3Lk/aUOOKeSdrbKkHeUNAYG70gEcdOCSayayu6TSd7NpeXK8/cZqu9SbvjsBmpTsqCEvqWtxh8tLcK0kLIxkhISNnyPzBIIp/HSpkhEA6XsUiE55i3myp5wN7ErVkYI9/TtyT344ximAn081qoScqab5NlJSUEpcjW2udlP7RmuQnJpwY1s+dKnSnFKoQs8dGFCrHbUZA4oAyPWKstrTnFNFB4NgW94Y/2Sv2rGtOp/8jWD/wCQGtqUP7E8P/bV+1Y3plsnQ1i+F+JoXyWXmxMXFvTkBbVx3svOuJSz5gTtUXVDYeMjqFA+/fmpl4ssn7JvQkPSFMwmSEJcb2J35wCAD8Dz7KHvU/SsqBcdIRLP/Yly0lSUBUnY4kh1Sgfw9cgcA8jvQe9Tj9mXy2yWlJdubQafcB2FsErJ2+5yVYx8650oQjWbk28/DP3Bi0uQDpWebbZpaxPchAspUuQSUtNIDoClrKfVgZ4Axkn4VHi3GdC1Cp3RVualPhgrbkSEONh9tRWC6Ar8OSlQCiQTg4Hc0vXeqf6CaJlOxZ8oRV2+VMeixo3nSZnk7SG20EHdnJynGSSMdyIcTxS1KuyzrZMftFqk3ZtxyO6mPlwtp2bWzuQNyEhSu+RhQPaud4glPUWfa1uPl+/kJ1KcZdfYIW2DcYUOU1MbU2wu5uPxEFSlBLLm1eE7gCE5OQO2SKY1I07IXaLeiVJYbmXBLTyo7xaWpAZdVt3J5AylPT2o6/fpepm3rjM8pbiZiWvrDWwJfAbb9QCQAMfh9zjNCNRKDMuxv4J8uepeAcZ2xXz/AKV1tO37BXNFFqVmu5kjGtre94rPeHMmBNTGQHlomq1NKU44lCVnPlAgJOUEEEjgpIyDWiM2lmxa6jQID8zyH7U+66h6Y88lS0vtBKsOKVggKUOMdaynS0nybvf9fW6yx1u3pDF3kMOtpBYiuKcThpQTu2qKAs9yUk4O4VqOntSRNZ36zalhsPsomWKSotPtlDjSxKbStCknnKVJI+OM1dN5yaqkUk2kW7ZSp8oNKtBmLDHSd4qx2vgihNviJlOOJjutOKZXsdCHEq8tXsrB4Pzo2xGeiLCXUYPBHOeKbyKDuQYjv+7V+1ZTpGMV6GsoxnF8Uf1rSnJaWITq3FBIDaup+FZjpG8tNaTtcRkNqeYuCpTgWraAntjg5Oe1U8MiCplx4lhYdfuTiPK88BHmqRhW9WQgN/eLIGOAO455qj2i+uayvEe46dQybJkKS8xuAeCQvO7dg4BI465J9qNazmaR05p25aqlWibczAYceUy3cNhDYO9ZQVJ2oICSc/lnmqV4OsIul0u+qEwrf9gOTfr1hSxIfTJY81vctp9DuUEgLzlBABJwMHNYKmlbnui+9/mZ3p5Se/sg7q5tEe5aUW++7Fjtolqfkozhprc3uJwQeR7fzHWhuvIUDUsuy2LTTDM5bjC3ZFxEXzcgrQgrfwVBLY6nnedgJJJwNNjKgvKYdfckRXmGXGEuR30BWxZG7k++BVDv2ndKRdWQ4Ue0aveVPSRJu0ctfV0AhKUNuOBaRnckrPoySevPCNTpJ1KrqRSd7c+ljRJbobGsfvc+aXs0Wy2B2NElCQ39pqSXE7/LKkobSQgK6DI6DjOepp/UFtl3BENyA/GbehyPPAkNqW2sFtbZSQlQPRwnr2qy3SzWCzWeFb9Pj0h7e8fTlSvSkE4JycJAySSccmq/d5aoA+9bWkkcZSa2UYOFNRnyHBKCSRVJGmLmLR9hGFpowPqyYnk+XLSPJAwEZDucY465p/SOmZFqlRnx9nMwocFcKKxDLysBbwcUoqdUo9RjHx+VNTNRnBKEOcdTsPFSNP6gh/UWAFAKdkPJyT1A24/eiUeq6Guo2rMt+M9aVcNkuICsdaVMAMe0bchfrcjXOg5s+JOhxyJ9vQ+ViS0CVK25IIUncohPQ5OMEjOvaL8SpF5ix0LvhlJxlKyAnr2OeleUvol3mQb8kBwlLaUqSlCiUgHqOvXHuOcGtrcFwsuo7nZ7Dpe53dLT5cZTb7e6792v1JG5KdvQ469qzJuNpx4Y6SUm4S7Gv3m73eTaZcJ4ebI8xYHkp9SmVElslI77eDjglJqpaeV9Xihl1BQtBIUlScEH2IPShWtdD+JOrbbb59o0o/b7hbE+hmXMZbMlpWNzasElJB9QJI5yO4qxNaV8Q5FitT8mxSpFyZStiSC62twNjBb3EK9RGVDOScAU6M25WafqJlBKN0zrUFttl609Ot91ClRXWT5iUnG4DsR0UD3Scg9CDVa8GIlstWm52lY99RcJNkuDjDzZe8xyM2v1sIcGBg+WU44GRg0W1LD1ha9MXda7VLt8pFukLZefY3obWG1FKinPqSFYyO44qp+DNxlP2G43F6Ol2ZKfjuzHo7G1LjhjN5VgZOM5xk8DA7UbfVYpX2M1ENIz2xUeSy2p9hPcKU4PyGP/ANUMVfA2r1JWkj/Egj96gw9TmbqGREMVaGIjLaUSCobXXF5UpKR19ISjJ91Y7GowUWGV6Iz6gTlLayOehCTisK0boXSt8noFzsyJI/o9ZJGVvvfxXWHC4vhf4lEAk9yK2yXJSqE/tUDlpzp/lNYHoDxW0NEvRirvzKlN6csSFFttxaQpDDiVDcE44VkHHcVQSL0vwg0HghuyONZ4PlXGWj9naqOpvCnSOh9O/XtJxbhbHET4gCWbrLLZ8yQhC8oU6UnKVEdKvjfihoJ7hOp4YJ/x7kf/AGAoB4jax0tO0opuJqC3PKM+3namSgnAltZ4zUwEXzQEuRN0Pp+ZMeU6+/a4jjrizlS1qZQVKJ9ySTSpjw3UP6vtNZH/AKPC6/7hFKrKGvDr6OPgP4OoCLIzcmSpvy1KmXpxxTg+JyCT8veisvQ/gnCjONxdNXBSVKU4XE3KUn1E8kLcd/YVkDniO028s25BdAOcx2M/85wP1oNK1Xqy/wApMdltEZDisJC1l11XPZIwB+tZHqoNWsaVppJ3uX6Zq57ws1fAh6Zuc9djmy2Yb8SXOXJaw82VIcRvJLa0qAB2naoHpRu+fSMs2kcNarjzLFc3ituMLi24qE+UKAXh6MHDgA55QDyMgVRr94P6pnXbTGr58JTdntshty4CVNx5zrhS00UsgklQJT1AAAPyoX9Ny3w2Y+jg0w0gFdwJSlI4JSz7UqtXnQoyqR7f6PoUKderGnLv39BzX3jcrWGqbRcLNrzSsa1tWa5wJkRm+OFDzkhspQ6UPpaBWjsFA98c1M+jf4m2DRVmucDV+q9GPqeWjyVKn+QRsQlO7HqwCByATyOnevCmrIDYSxjBKMqzj4GqTp6KHZ7TSkjO4jn4LSa5kPE6ibnZX/vy9fcdifhFJpQu/wB/6fs1bPFzwbvDrUWDqBu4SXh6WrYiQ+VKxkhOE4Peh/iDMiv2V5VqVOisqCilTyUJd4GT0zgdueeteV/o9WyfJt9nttiTi5SIshLBDnl7VbHcK3dsYz+VXv8Aq0+kI6h+Lf7+/NYVI3tx1PKUgN7MAbiSSN3OMfnXS0utnXp75r4J/k4+s0MNNUUIO/qX2BdkqtbqgdoWwo4B4GUHpWEWW1aif1Um5Wyxw5yE6WsERaH3UgpIbcUFA4IwQs8EZ9Nagu062s9vdZm2FLqwytIDLh5O01TdEO3qySVTrrY5bSXrRao3lD+IhxhgpcCgcd1D+RrQtRTtl2MzoTvhHE2Dcy4tU7w7U0rd/sYyXUqGByCEiq3qy1x5GmJa2dHPtPofjJbJjqbJWp9ASAFEA5JxWtDVMdzAMO4JJ7GOVftQbWmoGndNrbSHwTNg4C47ic/2tn4UcakXlMFwksNGjeEynh4X6SElX3oscAObjk7hHRnJ7nOaVV3w41KiJoHT0WYlTL7NsjNuNOoUhaFBpIKSCMggilTNyA2s8oDx5m3IpagWpMcH8KEJLq/54wP5V9tmsdemTJnxrRKdQ+oKSp19KAMdhk8fKtY8O/ogWhmHHmamuj7hUlJcbSdieOoJz8D7VtelfDrww0U2W7dp+KH2FhIfdAW4e4IKs9v2rnxot84NzrRXGTH/AAttvjReLrFubtleetzag6WW3QhpR/uFTi1bSAeeATU/6ZSLhFt2j5N2fhJC/roSiO4pwpwln8SzgEn4DHFbsdXphrVFgx2yQN7JWokbc8jgdv2Irzn9Jy1XTxPkWa2Lujkdm3OOrWGo+U73NgCE5PAOzOeeTjvS9XTh7CUIu7dvqM0dWX8iM5KyV/oeQ9X3FryQpOQA2pQPvVU0s+j68ysqyrzDz8CRW7Tvo+OSmUpmOzZLSBsUkEIJB7+nnjv8K+/+EXVTnlStNRVRVNKS5skOZQ4Ac4BPOT75xXFjp5uNksnfespqV28HoT6JMtld/wBMIUN60okApHX+G5XswpQrO1PmIJ4wOU/pzXm/6O+m52hNDwIV5RHTdY63g4WlKcbUCrgb8DBH6d63GJfGJqPPZ3JeTwpOxOPkRn9R+td7QUnQobXy8/Q874jVWor7lwsBk2+K9kuRkOII4WE4UPyofI0hY5yiXIqT7KSeRTf2p96FF9TDuPwrWAFD8h6vy5FMyLw46dratqs5JSonI/PmtMnFR6kZaak30sFTtI2yKAiKsLXnk/D27c1Cc0/bFJSxIgpfPmIXtcSVJSpKgpJ54yFAEHsQKNpVt9RVkkdPavjSXEEuqbJUfwjjk0mLTeFY0tOPLJ8KHEbjhJYGe/pBpUXtsdwxEFTXJ5ORzSp6sIcncwpLzwDjTa21lt1RSfxcH1Djt1wPlUGS1PEtt9aynzfulEIwSeqMDHxUKFW7R5txLtg1VfoRWAFebJEpKgOgKXAenzri8RfFVKg3arxZLkwrPEhCozrZ/ulOwKSrBGcEj50i7fKY3Zbhk2XBnTgFodc89o7mxuAye4AHuDj86aYs+mpEYSZvkOqfRu+9eP4T1B+III+YofcrlfIcVx+9aIuLpScqMRaZCO2SMKyPfGKG2/VOl1yxHROah+cCsNzWlM7FAjck7hjnORz71XRw/mF1cotltlQITaY7P1NDjQ2pcQhJLg7L479j8a7euIhJKg8/9UznKUY8sk+5H4ef+H5dB6mWpmxUe4xC6wS40G1J54IIOCeCOv5HtXbaPrLI8x97HIcSkD8XcHAz/wB/GjvZYACyJ8wFT8Rb4OPUhx0AOfH4Hj/Q0Vh3ZSwhUQp88HBynK0q7gj/AE6VUYsNTD7cdhmS8hZ2tpUSpWemCCclPPB/L2rXtE6GiWYJu9waaVPUMJAAw2Ov5n9qkW2DJWJFviTPqyXrs20h8+oNtghI9lEHv8O1dKbCFEpOCTlR/wC+9EZq0+YfUD8aFSHOQEAkk4AqSVy4YHCsE7AQB3OOgqbBSHHEnnjoPYUKHUJByPcdzRi3I8tPGT3NSNkE8lqiPJbYSkDPzNKmIw+6BKMk0qZcW0ecmJqlK2IGMjvRuEkBKXFjJJwKVKhWEHLIcistOhJUnPt8Kcn6dtdxYLUyGxIQRkpebCxj5EUqVOSTWRDbTwUO8+EmjVumS1akQ3eQHIa1MqHy28UMj+Et9Dx/oz4gXCM64lOW5yfrLRAzgdQR1NKlWOpTipYVjVCpJrLNZ0RohVghsuXh5mVdNoDrzQOwHvszyM/p0+dyJKE+QngkZz7D2FKlTUrIS3dg+UnaCOuKHKj7UqWhQSpw5JxnPalSq0WR/vGSVuBKkj/CcGj9uebcZbWhJAUM4NKlVdxq4LFHKVNA4xSpUqNCGf/Z->"; text = "<|system|>\n" + text + " <|end|>\n<|assistant|>\n"; text += "{\n 'glossary': {\n 'title': 'example glossary',\n 'GlossDiv': {\n 'title': 'S',\n 'GlossList': {\n 'GlossEntry': {\n 'ID': 'SGML',\n 'SortAs': 'SGML',\n 'GlossTerm': 'Standard Generalized Markup Language',\n 'Acronym': 'SGML',\n 'Abbrev': 'ISO 8879:1986',\n 'GlossDef': {\n 'para': 'A meta-markup language, used to create markup languages such as DocBook.',\n 'GlossSeeAlso': ['GML', 'XML']\n },\n 'GlossSee': 'markup'\n }\n }\n }\n }\n}"; -text += " <|end|>\n" +// text += " <|end|>\n" // text += "<|user|>\n" // text += "A language model is a probabilistic model of a natural language.[1]\nIn 1980, the first significant statistical language model was proposed, and during the decade IBM performed Shannon-style experiments, in which potential sources for language modeling improvement were identified by observing and analyzing the performance of human subjects in predicting or correcting text.[2] Language models are useful for a variety of tasks, including speech recognition[3] (helping prevent predictions of low-probability (e.g. nonsense) sequences), machine translation,[4] natural language generation (generating more human-like text), optical character recognition, handwriting recognition,[5] grammar induction,[6] and information retrieval.[7][8] Large language models, currently their most advanced form, are a combination of larger datasets (frequently using words scraped from the public internet), feedforward neural networks, and transformers. They have superseded recurrent neural network-based models, which had previously superseded the pure statistical models, such as word n-gram language model."; // text += " <|end|>\n <|endoftext|>" diff --git a/client/graphpaper-inline/src/stitch.ts b/client/graphpaper-inline/src/stitch.ts index 374d3b142..787db62ac 100644 --- a/client/graphpaper-inline/src/stitch.ts +++ b/client/graphpaper-inline/src/stitch.ts @@ -65,23 +65,23 @@ export interface StitchMessage { content: any } -export function isTraceMessage(o: NodeAttr | undefined): o is TraceMessage { - if (o === undefined) return false; +export function isTraceMessage(o: NodeAttr | undefined | null): o is TraceMessage { + if (o === undefined || o === null) return false; return o.class_name === "TraceMessage"; } -export function isRoleOpenerInput(o: NodeAttr | undefined): o is RoleOpenerInput { - if (o === undefined) return false; +export function isRoleOpenerInput(o: NodeAttr | undefined | null): o is RoleOpenerInput { + if (o === undefined || o === null) return false; return o.class_name === "RoleOpenerInput"; } -export function isRoleCloserInput(o: NodeAttr | undefined): o is RoleCloserInput { - if (o === undefined) return false; +export function isRoleCloserInput(o: NodeAttr | undefined | null): o is RoleCloserInput { + if (o === undefined || o === null) return false; return o.class_name === "RoleCloserInput"; } -export function isTextOutput(o: NodeAttr | undefined): o is TextOutput { - if (o === undefined) return false; +export function isTextOutput(o: NodeAttr | undefined | null): o is TextOutput { + if (o === undefined || o === null) return false; return o.class_name === "TextOutput"; } From 22080a041406fcd39f1b4e93e41181783b9bf7ac Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 9 Oct 2024 15:01:59 -0700 Subject: [PATCH 050/133] return JupyterCellExecutionCompletedOutputMessage only if we can match tokens with issued chunks --- guidance/models/_model.py | 174 +++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 86 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 010dd080e..0ec301a8a 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -156,107 +156,109 @@ def _msg_recv(self, message: GuidanceMessage) -> None: vis_chunks: list[VisBytesChunk] = [path.vis_chunk for path in paths if path.vis_chunk is not None] - # tokens = [] + text = last_model._state # gen_tokens: list[GenToken] = [] # for vis_chunk in vis_chunks: - # if vis_chunk.backtrack: - # tokens = tokens[:-vis_chunk.backtrack] - # gen_tokens = gen_tokens[:-vis_chunk.backtrack] - - # if vis_chunk.is_input: - # for gen_token in vis_chunk.input_tokens: - # tokens.append(gen_token.token) - # gen_tokens.append(gen_token) - # else: - # for gen_token in vis_chunk.generated_tokens: - # tokens.append(gen_token.token) - # gen_tokens.append(gen_token) - - # for gen_token in vis_chunk.force_forwarded_tokens: - # tokens.append(gen_token.token) - # gen_tokens.append(gen_token) - - text = "" - gen_tokens: list[GenToken] = [] - for vis_chunk in vis_chunks: - text += vis_chunk.bytes.decode("utf-8") - gen_tokens.extend(vis_chunk.input_tokens) - gen_tokens.extend(vis_chunk.generated_tokens) - gen_tokens.extend(vis_chunk.force_forwarded_tokens) + # text += vis_chunk.bytes.decode("utf-8") + # gen_tokens.extend(vis_chunk.input_tokens) + # gen_tokens.extend(vis_chunk.generated_tokens) + # gen_tokens.extend(vis_chunk.force_forwarded_tokens) tokens = self.tokenizer.encode(text.encode("utf-8")) probs = self.get_token_probs(tokens) + tokens_texts: list[str] = [] + for idx in range(len(tokens)): + tokens_texts.append(self.tokenizer.decode([tokens[idx]]).decode("utf-8")) + + start_idx = 0 + end_idx = 1 + start_pos = 0 + remainder = "" + failed = False - idx = 0 processed_gen_tokens = [] - while gen_tokens: - gen_token = gen_tokens.pop(0) - - if gen_token.token == tokens[idx]: - gen_token.top_k = probs[idx] - for _token in probs[idx]: - if _token.token == gen_token.token: - gen_token.prob = _token.prob - break - processed_gen_tokens.append(gen_token) - text = text[len(gen_token.text):] - idx += 1 + for vis_chunk in vis_chunks: + vis_text = vis_chunk.bytes.decode("utf-8") + + if not vis_text: continue - # we have a mismatch due to backtracking - # next_gen_token = gen_tokens.pop(0) - # merged_text = gen_token.text + next_gen_token.text - # merged_tokens = self.tokenizer.encode(merged_text.encode("utf-8")) - # assert len(merged_tokens) == 1, f"Expected merged tokens to be of length 1, got {len(merged_tokens)}" - - merged_text = gen_token.text - token_text = self.tokenizer.decode([tokens[idx]]).decode("utf-8") - while len(merged_text) < len(token_text) and token_text.startswith(merged_text): - next_gen_token = gen_tokens.pop(0) - merged_text += next_gen_token.text - - assert token_text == merged_text, f"Expected merged text to be {token_text}, got {merged_text}" - merged_tokens = self.tokenizer.encode(merged_text.encode("utf-8")) - - if tokens[idx] == merged_tokens[0]: - # create new GenToken - prob = 0 - for _token in probs[idx]: - if _token.token == merged_tokens[0]: + end_idx = start_idx + _chunk = "".join(tokens_texts[start_idx:end_idx+1]) + while vis_text not in _chunk and end_idx < len(tokens_texts): + # expand the chunk + end_idx += 1 + _chunk = "".join(tokens_texts[start_idx:end_idx+1]) + + if vis_text not in _chunk and end_idx >= len(tokens_texts): + failed = True + break + + if vis_text == _chunk: + # perfect match + pass + else: + start_pos = _chunk.index(vis_text) + remainder = _chunk[start_pos + len(vis_text):] + + if remainder: + # we have a current chunk that is larger than the vis_text + # probably the last token is a partial token + # we should not issue that token for now + end_idx -= 1 + + real_chunk_tokens = tokens[start_idx:end_idx+1] + real_chunk_probs = probs[start_idx:end_idx+1] + + is_input = len(vis_chunk.input_tokens) > 0 + is_force_forwarded = len(vis_chunk.force_forwarded_tokens) > 0 + + _gen_tokens: list[GenToken] = [] + for token, top_k_prob in zip(real_chunk_tokens, real_chunk_probs): + prob = -1 + for _token in top_k_prob: + if _token.token == token: prob = _token.prob break _gen_token = GenToken( - token=merged_tokens[0], + token=token, prob=prob, - text=merged_text, - latency_ms=gen_token.latency_ms + next_gen_token.latency_ms, - is_generated=gen_token.is_generated or next_gen_token.is_generated, - is_force_forwarded=gen_token.is_force_forwarded or next_gen_token.is_force_forwarded, + text=self.tokenizer.decode([token]).decode("utf-8"), + latency_ms=0, + is_input=is_input, + is_generated=False, + is_force_forwarded=False ) - _gen_token.top_k = probs[idx] - processed_gen_tokens.append( - _gen_token - ) - idx += 1 - else: - assert next_gen_token.token == merged_tokens[0], f"Expected next_gen_token token to be {merged_tokens[0]}, got {next_gen_token.token}" - - final_text = "".join([gen_token.text for gen_token in processed_gen_tokens]) - logger.debug(f"ENGINE:final_text:{final_text}") - - self.renderer.update(JupyterCellExecutionCompletedOutputMessage( - trace_id=message.last_trace_id, - text=self.tokenizer.decode(tokens).decode("utf-8"), - tokens=processed_gen_tokens, - )) - - # self.renderer.update(JupyterCellExecutionCompletedOutputMessage( - # trace_id=message.last_trace_id, - # text=self.tokenizer.decode(tokens).decode("utf-8"), - # tokens=tokens, - # probs=probs - # )) + _gen_token.top_k = top_k_prob + _gen_tokens.append(_gen_token) + + for i, _gen_token in enumerate(_gen_tokens): + if i < len(vis_chunk.generated_tokens): + _gen_token.latency_ms = vis_chunk.generated_tokens[i].latency_ms + _gen_token.is_generated = True + else: + if is_force_forwarded: + _gen_token.is_force_forwarded = True + if i - len(vis_chunk.generated_tokens) < len(vis_chunk.force_forwarded_tokens): + _gen_token.latency_ms = vis_chunk.force_forwarded_tokens[i - len(vis_chunk.generated_tokens)].latency_ms + + processed_gen_tokens.extend(_gen_tokens) + + start_idx = end_idx + 1 + + start_pos = 0 + remainder = "" + + if not failed: + final_text = "".join([gen_token.text for gen_token in processed_gen_tokens]) + logger.debug(f"ENGINE:final_text:{final_text}") + + self.renderer.update(JupyterCellExecutionCompletedOutputMessage( + trace_id=message.last_trace_id, + text=self.tokenizer.decode(tokens).decode("utf-8"), + tokens=processed_gen_tokens, + )) def get_chat_template(self): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? return self.tokenizer.chat_template() # Instantiate the class before returning to client for now From 4af0a04c3721c447329f420a9b3a681ac8903fbc Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Wed, 9 Oct 2024 15:45:37 -0700 Subject: [PATCH 051/133] Minor adj to model. --- guidance/models/_model.py | 6 +++--- guidance/trace/_trace.py | 1 + guidance/visual/_async.py | 4 ++-- guidance/visual/_renderer.py | 15 ++++++++++----- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 010dd080e..d91e4de92 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -782,13 +782,13 @@ def __add__(self, value): for context in enter_blocks: # add opener opener_text = self.role_opener(context.name) - self._update_trace_node(lm._id, lm._parent_id, RoleOpenerInput(name=context.name, text=opener_text)) + closer_text = self.role_closer(context.name) + self._update_trace_node(lm._id, lm._parent_id, RoleOpenerInput(name=context.name, text=opener_text, closer_text=closer_text)) lm += context.opener lm = lm.copy() # store closer for state extraction later - close_text = self.role_closer(context.name) - lm.opened_blocks[context] = (len(lm._state), close_text) + lm.opened_blocks[context] = (len(lm._state), closer_text) # handle variables # NOTE(nopdive): No stack for variables, this process removes shadowed variables? diff --git a/guidance/trace/_trace.py b/guidance/trace/_trace.py index 6ad73a56d..473afb62c 100644 --- a/guidance/trace/_trace.py +++ b/guidance/trace/_trace.py @@ -86,6 +86,7 @@ class RoleOpenerInput(InputAttr): name: Optional[str] text: Optional[str] + closer_text: Optional[str] class RoleCloserInput(InputAttr): diff --git a/guidance/visual/_async.py b/guidance/visual/_async.py index 82445c204..c56d7f78b 100644 --- a/guidance/visual/_async.py +++ b/guidance/visual/_async.py @@ -5,8 +5,8 @@ import asyncio import threading -from asyncio import AbstractEventLoop, Queue, Future -from typing import Tuple, Any +from asyncio import AbstractEventLoop, Future +from typing import Tuple class ThreadSafeAsyncCondVar: diff --git a/guidance/visual/_renderer.py b/guidance/visual/_renderer.py index fc85e1c53..e8851a758 100644 --- a/guidance/visual/_renderer.py +++ b/guidance/visual/_renderer.py @@ -217,6 +217,7 @@ def update(self, message: GuidanceMessage) -> None: self._loop.call_soon_threadsafe(self._send_queue.put_nowait, out_message) def _handle_jupyter_cell_completion(self): + # TODO(nopdive): Review interaction of primary/UI thread here. if self._jupyter_change_detector.has_changed(): if self._is_alive_cell_cb: get_ipython().events.unregister('post_execute', self._cell_completion_cb) @@ -251,7 +252,7 @@ async def _handle_recv_messages(self): value = await self._recv_queue.get() # logger.debug(f"RECV:raw:{value}") message = deserialize_message(value) - logger.debug(f"RECV:msg:{message}") + # logger.debug(f"RECV:msg:{message}") if isinstance(message, ClientReadyMessage): logger.debug("RECV:clientready") self._client_ready.notify() @@ -264,14 +265,19 @@ async def _handle_send_messages(self): logger.debug("SEND:init") # Wait until ready - if self._wait_for_client: - await self._client_ready.wait() + # TODO(nopdive): This blocks until cell completion. Not what we want. + # if self._wait_for_client: + # await self._client_ready.wait() + + # What if we only used 1% of our brain? + import asyncio + await asyncio.sleep(0.5) logger.debug("SEND:ready") while True: try: message = await self._send_queue.get() - logger.debug(f"SEND:msg:{message}") + # logger.debug(f"SEND:msg:{message}") message_json = serialize_message(message) # logger.debug(f"SEND:json:{message_json}") if self._jupyter_widget is not None: @@ -316,7 +322,6 @@ def __init__(self, trace_handler: TraceHandler, use_legacy_renderer=False): self._renderer = JupyterWidgetRenderer(trace_handler=trace_handler) else: self._renderer = LegacyHtmlRenderer(trace_handler=trace_handler) - super().__init__() def notify(self, message: GuidanceMessage): From 19f894328ec452e4805649ade1250bc0fb6bdd2e Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Wed, 9 Oct 2024 15:57:07 -0700 Subject: [PATCH 052/133] Additional changes. Minor changes included. --- client/graphpaper-inline/rollup.config.mjs | 2 ++ guidance/models/_model.py | 2 +- guidance/resources/graphpaper-inline.html | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/graphpaper-inline/rollup.config.mjs b/client/graphpaper-inline/rollup.config.mjs index ff60f8b76..ff11355b8 100644 --- a/client/graphpaper-inline/rollup.config.mjs +++ b/client/graphpaper-inline/rollup.config.mjs @@ -6,7 +6,9 @@ import terser from '@rollup/plugin-terser'; import typescript from '@rollup/plugin-typescript'; import postcss from 'rollup-plugin-postcss'; import livereload from 'rollup-plugin-livereload'; +// @ts-ignore import serve from 'rollup-plugin-serve'; +// @ts-ignore import htmlBundle from 'rollup-plugin-html-bundle'; import copy from 'rollup-plugin-copy'; diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 6da7dc05d..0f7a8d343 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -120,7 +120,7 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False, **kwargs): self.metrics = GuidanceEngineMetrics() self.trace_handler = TraceHandler() - self.renderer = AutoRenderer(self.trace_handler, use_legacy_renderer=kwargs.get("use_legacy_renderer", True)) + self.renderer = AutoRenderer(self.trace_handler, use_legacy_renderer=kwargs.get("use_legacy_renderer", False)) self.renderer.subscribe(self._msg_recv) self.model_dict: dict[int, Model] = {} diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index 051b7a2b9..b98079888 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,7 +9,7 @@ From 61b4786e928ee9a72de953065e9e62cc49f3ca7f Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 9 Oct 2024 16:47:00 -0700 Subject: [PATCH 053/133] Optimize latency per token metric --- guidance/_parser.py | 2 ++ guidance/_schema.py | 1 + guidance/models/_model.py | 39 +++++++++++++++++++++++++++++++-------- guidance/visual/_trace.py | 6 ++++-- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/guidance/_parser.py b/guidance/_parser.py index 55f435c7b..c66b69f71 100644 --- a/guidance/_parser.py +++ b/guidance/_parser.py @@ -104,6 +104,8 @@ def _parse( response = r.progress.to_engine_call_response() response.backtrack = backtrack + if engine_output: + response.engine_outputs.append(engine_output) # if ff_tokens: # if engine_output.issued_token.token == ff_tokens[0]: diff --git a/guidance/_schema.py b/guidance/_schema.py index 198fc3166..88b134732 100644 --- a/guidance/_schema.py +++ b/guidance/_schema.py @@ -57,6 +57,7 @@ class VisBytesChunk(BaseModel): force_forwarded_bytes: bytes = b"" force_forwarded_tokens: list["GenToken"] = [] backtrack: NonNegativeInt = 0 + engine_outputs: list[EngineOutput] = [] class GenData(BaseModel): tokens: list[int] diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 0f7a8d343..2beec8f84 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -155,6 +155,11 @@ def _msg_recv(self, message: GuidanceMessage) -> None: paths.reverse() vis_chunks: list[VisBytesChunk] = [path.vis_chunk for path in paths if path.vis_chunk is not None] + gen_tokens_lats = [] + for vis_chunk in vis_chunks: + for engine_output in vis_chunk.engine_outputs: + gen_tokens_lats.append((engine_output.issued_token.token, engine_output.issued_token.latency_ms)) + gen_tokens_lats_idx = 0 text = last_model._state # gen_tokens: list[GenToken] = [] @@ -234,14 +239,30 @@ def _msg_recv(self, message: GuidanceMessage) -> None: _gen_tokens.append(_gen_token) for i, _gen_token in enumerate(_gen_tokens): - if i < len(vis_chunk.generated_tokens): - _gen_token.latency_ms = vis_chunk.generated_tokens[i].latency_ms - _gen_token.is_generated = True - else: - if is_force_forwarded: - _gen_token.is_force_forwarded = True - if i - len(vis_chunk.generated_tokens) < len(vis_chunk.force_forwarded_tokens): - _gen_token.latency_ms = vis_chunk.force_forwarded_tokens[i - len(vis_chunk.generated_tokens)].latency_ms + # if i < len(vis_chunk.generated_tokens): + # _gen_token.latency_ms = vis_chunk.generated_tokens[i].latency_ms + # _gen_token.is_generated = True + # else: + # if is_force_forwarded: + # _gen_token.is_force_forwarded = True + # if i - len(vis_chunk.generated_tokens) < len(vis_chunk.force_forwarded_tokens): + # _gen_token.latency_ms = vis_chunk.force_forwarded_tokens[i - len(vis_chunk.generated_tokens)].latency_ms + + if not is_input: + if i < len(vis_chunk.generated_tokens): + _gen_token.is_generated = True + else: + if is_force_forwarded: + _gen_token.is_force_forwarded = True + + base_idx = gen_tokens_lats_idx + while base_idx < len(gen_tokens_lats): + if _gen_token.token == gen_tokens_lats[base_idx][0]: + _gen_token.latency_ms = gen_tokens_lats[base_idx][1] + gen_tokens_lats_idx = base_idx + 1 + break + + base_idx += 1 processed_gen_tokens.extend(_gen_tokens) @@ -1153,6 +1174,7 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): force_forwarded_bytes=chunk.force_forwarded_bytes, force_forwarded_tokens=chunk.force_forwarded_tokens, backtrack=chunk.backtrack, + engine_outputs=chunk.engine_outputs, ) else: # append to existing VisBytesChunk @@ -1160,6 +1182,7 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): lm.vis_chunk.generated_bytes += chunk.generated_bytes lm.vis_chunk.force_forwarded_bytes += chunk.force_forwarded_bytes lm.vis_chunk.backtrack += chunk.backtrack + lm.vis_chunk.engine_outputs += chunk.engine_outputs # last_is_generated = chunk.is_generated if len(chunk.capture_groups) > 0: diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index 3e6b5ca5d..094ed91b2 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -88,10 +88,12 @@ def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: Jupy top_k[f"{_item.text}"] = f"{_item.prob}" top_k = json.dumps(top_k, indent=2) + latency = f"{complete_msg.tokens[prob_idx].latency_ms:.2f}" + if attr.is_generated: - fmt += f"{html.escape(token_str)}" + fmt += f"{html.escape(token_str)}" elif attr.is_force_forwarded: - fmt += f"{html.escape(token_str)}" + fmt += f"{html.escape(token_str)}" else: fmt += f"{html.escape(token_str)}" From 146cfb91d7e4faa76a1c39de8362d84da546c855 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 9 Oct 2024 17:10:17 -0700 Subject: [PATCH 054/133] Update per token latency metric --- guidance/models/_model.py | 24 ++++++++++++++++-------- guidance/visual/_trace.py | 6 +++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 2beec8f84..8dde4ece6 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -156,9 +156,11 @@ def _msg_recv(self, message: GuidanceMessage) -> None: vis_chunks: list[VisBytesChunk] = [path.vis_chunk for path in paths if path.vis_chunk is not None] gen_tokens_lats = [] + gen_tokens_indices = [] for vis_chunk in vis_chunks: for engine_output in vis_chunk.engine_outputs: gen_tokens_lats.append((engine_output.issued_token.token, engine_output.issued_token.latency_ms)) + gen_tokens_indices.append(len(gen_tokens_lats) - 1) gen_tokens_lats_idx = 0 text = last_model._state @@ -182,7 +184,7 @@ def _msg_recv(self, message: GuidanceMessage) -> None: failed = False processed_gen_tokens = [] - for vis_chunk in vis_chunks: + for vis_chunk_idx, vis_chunk in enumerate(vis_chunks): vis_text = vis_chunk.bytes.decode("utf-8") if not vis_text: @@ -255,14 +257,20 @@ def _msg_recv(self, message: GuidanceMessage) -> None: if is_force_forwarded: _gen_token.is_force_forwarded = True - base_idx = gen_tokens_lats_idx - while base_idx < len(gen_tokens_lats): - if _gen_token.token == gen_tokens_lats[base_idx][0]: - _gen_token.latency_ms = gen_tokens_lats[base_idx][1] - gen_tokens_lats_idx = base_idx + 1 - break + # base_idx = gen_tokens_lats_idx + # while base_idx < len(gen_tokens_lats): + # if _gen_token.token == gen_tokens_lats[base_idx][0]: + # _gen_token.latency_ms = gen_tokens_lats[base_idx][1] + # gen_tokens_lats_idx = base_idx + 1 + # break - base_idx += 1 + # base_idx += 1 + + max_idx = gen_tokens_indices[vis_chunk_idx] + for idx in range(max_idx, -1, -1): + if _gen_token.token == gen_tokens_lats[idx][0]: + _gen_token.latency_ms = gen_tokens_lats[idx][1] + break processed_gen_tokens.extend(_gen_tokens) diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index 094ed91b2..c21f21adc 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -91,11 +91,11 @@ def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: Jupy latency = f"{complete_msg.tokens[prob_idx].latency_ms:.2f}" if attr.is_generated: - fmt += f"{html.escape(token_str)}" + fmt += f"{html.escape(token_str)}" elif attr.is_force_forwarded: - fmt += f"{html.escape(token_str)}" + fmt += f"{html.escape(token_str)}" else: - fmt += f"{html.escape(token_str)}" + fmt += f"{html.escape(token_str)}" full_text = full_text[len(token_str):] prob_idx += 1 From 6141e37fc24ef1efdac17326320d35238984bad3 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Wed, 9 Oct 2024 17:10:25 -0700 Subject: [PATCH 055/133] Basic tooltip exposed. Not connected yet to token info. --- client/graphpaper-inline/package.json | 4 +- client/graphpaper-inline/pnpm-lock.yaml | 23 +++++++++ client/graphpaper-inline/src/TokenGrid.svelte | 50 +++++++++++++++++-- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/client/graphpaper-inline/package.json b/client/graphpaper-inline/package.json index f590ae321..3dc659ded 100644 --- a/client/graphpaper-inline/package.json +++ b/client/graphpaper-inline/package.json @@ -13,6 +13,7 @@ "@rollup/plugin-typescript": "^11.1.6", "@types/d3-scale": "^4.0.8", "@types/d3-scale-chromatic": "^3.0.3", + "@types/dompurify": "^3.0.5", "autoprefixer": "^10.4.20", "cssnano": "^7.0.5", "postcss": "^8.4.41", @@ -32,6 +33,7 @@ }, "dependencies": { "d3-scale": "^4.0.2", - "d3-scale-chromatic": "^3.1.0" + "d3-scale-chromatic": "^3.1.0", + "dompurify": "^3.1.7" } } \ No newline at end of file diff --git a/client/graphpaper-inline/pnpm-lock.yaml b/client/graphpaper-inline/pnpm-lock.yaml index f7dac1004..065b74962 100644 --- a/client/graphpaper-inline/pnpm-lock.yaml +++ b/client/graphpaper-inline/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: d3-scale-chromatic: specifier: ^3.1.0 version: 3.1.0 + dompurify: + specifier: ^3.1.7 + version: 3.1.7 devDependencies: '@rollup/plugin-commonjs': specifier: ^26.0.1 @@ -33,6 +36,9 @@ importers: '@types/d3-scale-chromatic': specifier: ^3.0.3 version: 3.0.3 + '@types/dompurify': + specifier: ^3.0.5 + version: 3.0.5 autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.41) @@ -282,6 +288,9 @@ packages: '@types/d3-time@3.0.3': resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==} + '@types/dompurify@3.0.5': + resolution: {integrity: sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==} + '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -300,6 +309,9 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + acorn@8.12.1: resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} @@ -593,6 +605,9 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} + dompurify@3.1.7: + resolution: {integrity: sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==} + domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} @@ -1875,6 +1890,10 @@ snapshots: '@types/d3-time@3.0.3': {} + '@types/dompurify@3.0.5': + dependencies: + '@types/trusted-types': 2.0.7 + '@types/estree@1.0.5': {} '@types/fs-extra@8.1.5': @@ -1894,6 +1913,8 @@ snapshots: '@types/resolve@1.20.2': {} + '@types/trusted-types@2.0.7': {} + acorn@8.12.1: {} ansi-regex@5.0.1: {} @@ -2237,6 +2258,8 @@ snapshots: dependencies: domelementtype: 2.3.0 + dompurify@3.1.7: {} + domutils@2.8.0: dependencies: dom-serializer: 1.4.1 diff --git a/client/graphpaper-inline/src/TokenGrid.svelte b/client/graphpaper-inline/src/TokenGrid.svelte index 9f4c08273..24bb12599 100644 --- a/client/graphpaper-inline/src/TokenGrid.svelte +++ b/client/graphpaper-inline/src/TokenGrid.svelte @@ -4,6 +4,7 @@ import {isRoleOpenerInput, isTextOutput, type NodeAttr, type RoleOpenerInput} from './stitch'; import TokenGridItem from "./TokenGridItem.svelte"; import {longhover} from "./longhover"; + import DOMPurify from "dompurify"; interface Token { value: string, @@ -59,7 +60,7 @@ let tooltip: HTMLElement; let tooltipX = 0; let tooltipY = 0; - let tooltipText = ''; + let tooltipToken: Token; const mouseLongHoverDuration = 200; const handleLongMouseOver = (event: CustomEvent) => { @@ -70,11 +71,12 @@ const positionYOffset = 10; // Add tooltip - tooltipText = index || ""; const rect = target.getBoundingClientRect(); tooltipX = (rect.left + window.scrollX + rect.width / 2) + positionXOffset; tooltipY = (rect.bottom + window.scrollY) + positionYOffset; tooltip.style.display = 'block'; + const indexNum = Number(index); + tooltipToken = tokens[indexNum]; // Adjust if near edge of viewport if (tooltipX + tooltip.offsetWidth > window.innerWidth) { @@ -126,12 +128,50 @@ } } const doNothing = (_: any) => {} - + const escapeWhitespaceCharacters = (text: string) => { + return text.replaceAll(' ', ' ').replaceAll('\t', '\\t').replaceAll('\n', '\\n'); + } -
- {tooltipText} +
+
+ {#if tooltipToken} +
+
+ + {@html DOMPurify.sanitize(escapeWhitespaceCharacters(tooltipToken.value))} + +
+ + + + + + + + + + + + + + + + + + + + + +
+ Token + + Prob +
degenerates0.983
jugs0.201
madness0.005
+
+ {/if} +
From a666cc4d5608ea4bd0d2577c0bef5c67ab1cbe21 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Wed, 9 Oct 2024 17:10:49 -0700 Subject: [PATCH 056/133] Updated html bundle. --- guidance/resources/graphpaper-inline.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index b98079888..35da23738 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,7 +9,8 @@ From e3f047715e8887a9a478535f9a7901c6cafd242f Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 9 Oct 2024 17:37:44 -0700 Subject: [PATCH 057/133] Add metric worker --- guidance/models/_model.py | 165 +++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 8dde4ece6..203252f6d 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -6,7 +6,10 @@ import time from typing import Iterator, Optional, TYPE_CHECKING - +from multiprocessing import Manager, Process +from typing import Any, Union +from enum import Enum +import psutil import numpy as np @@ -1384,3 +1387,163 @@ def __init__(self, *args, **kwargs): self.prompt = kwargs.pop("prompt", None) self.data = kwargs.pop("data", None) super().__init__(*args, **kwargs) + +class MonitoringMetric(str, Enum): + CPU_USAGE = "cpu_usage" + MEM_USAGE = "mem_usage" + GPU_USAGE = "gpu_usage" + GPU_USED_MEM = "gpu_used_mem" + GPU_TOTAL_MEM = "gpu_total_mem" + INPUT_TOKENS = "input_tokens" + OUTPUT_TOKENS = "output_tokens" + BACKTRACK_TOKENS = "backtrack_tokens" + TOKEN_COUNT = "token_count" + TOKEN_REDUCTION = "token_reduction" + +ALL_METRICS = [ + MonitoringMetric.CPU_USAGE, + MonitoringMetric.MEM_USAGE, + MonitoringMetric.GPU_USAGE, + MonitoringMetric.GPU_USED_MEM, + MonitoringMetric.GPU_TOTAL_MEM, + MonitoringMetric.INPUT_TOKENS, + MonitoringMetric.OUTPUT_TOKENS, + MonitoringMetric.BACKTRACK_TOKENS, + MonitoringMetric.TOKEN_COUNT, + MonitoringMetric.TOKEN_REDUCTION +] + +def _monitor_fn(stop_flag, metrics_dict: dict[MonitoringMetric, list], max_size: int = 100, interval_ms: float = 1000): + print("Monitoring started") + + to_collect_gpu_stats = False + try: + import gpustat + gpu_stats = gpustat.GPUStatCollection.new_query() + if len(gpu_stats) > 0: + # only collect GPU stats if there is at least one GPU + to_collect_gpu_stats = True + except: + pass + + try: + while not stop_flag.value: + t0 = time.time() + + #cpu_percent = psutil.cpu_percent(interval=1) + cpu_percent = psutil.cpu_percent() + memory_usage = psutil.virtual_memory() + + metrics_dict[MonitoringMetric.CPU_USAGE].append(cpu_percent) + metrics_dict[MonitoringMetric.MEM_USAGE].append(memory_usage.percent) + + t1 = time.time() + + if to_collect_gpu_stats: + gpu_stats = gpustat.GPUStatCollection.new_query() + + usage = [gpu.utilization for gpu in gpu_stats.gpus] + mem_usage = [gpu.memory_used for gpu in gpu_stats.gpus] + mem_total = [gpu.memory_total for gpu in gpu_stats.gpus] + + metrics_dict[MonitoringMetric.GPU_USAGE].append(usage) + metrics_dict[MonitoringMetric.GPU_USED_MEM].append(mem_usage) + metrics_dict[MonitoringMetric.GPU_TOTAL_MEM].append(mem_total) + + t2 = time.time() + + for metrics in metrics_dict.values(): + if len(metrics) > max_size: + metrics.pop(0) + + lat = time.time() - t0 + cpu_lat = t1 - t0 + gpu_lat = t2 - t1 + + # print(f"Monitoring took {lat*1000:.1f}ms") + # print(f"CPU/MEM: {cpu_lat*1000:.1f}ms, GPU: {gpu_lat*1000:.1f}ms") + + # sleep for the remaining time of the interval + sleep_time = interval_ms / 1000.0 - lat + if sleep_time < 0: + time.sleep(sleep_time) + except Exception as e: + # print(f"Error in monitoring: {e}") + pass + + print("Monitoring stopped") + +class Monitor: + """Monitoring service to collect neccessary metrics for visualizatoin + """ + + def __init__(self, engine: Engine, **kwargs): + self.engine = engine + self.mp_manager = Manager() + + # use list instead of queue for easily accessing each item, e.g., last item + self.max_size = kwargs.get("max_size", 100) + + self.metrics_dict = { + MonitoringMetric.CPU_USAGE: self.mp_manager.list(), + MonitoringMetric.MEM_USAGE: self.mp_manager.list(), + MonitoringMetric.GPU_USAGE: self.mp_manager.list(), + MonitoringMetric.GPU_USED_MEM: self.mp_manager.list(), + MonitoringMetric.GPU_TOTAL_MEM: self.mp_manager.list() + } + + self.stop_flag = self.mp_manager.Value("b", False) + self.process = None + + self.per_token_metrics = [] # store metrics per token in token list + + def start(self): + self.process = Process(target=_monitor_fn, args=(self.stop_flag, self.metrics_dict, self.max_size)) + self.process.start() + + def stop(self): + if self.process: + self.stop_flag.value = True + self.process.join() + + for metrics in self.metrics_dict.values(): + metrics.clear() + + def reset(self): + self.stop() + + for metrics in self.metrics_dict.values(): + metrics.clear() + + self.start() + + def get_metrics(self, metrics: list[MonitoringMetric] = ALL_METRICS, lm: Union[Model, None] = None) -> dict[MonitoringMetric, Any]: + result = {} + + for metric in metrics: + if metric in [ + MonitoringMetric.CPU_USAGE, + MonitoringMetric.MEM_USAGE, + MonitoringMetric.GPU_USAGE, + MonitoringMetric.GPU_USED_MEM, + MonitoringMetric.GPU_TOTAL_MEM + ]: + result[metric] = self.metrics_dict[metric][-1] if len(self.metrics_dict[metric]) > 0 else None + elif metric == MonitoringMetric.INPUT_TOKENS: + result[metric] = self.engine.metrics.engine_input_tokens + elif metric == MonitoringMetric.OUTPUT_TOKENS: + result[metric] = self.engine.metrics.engine_output_tokens + elif metric == MonitoringMetric.BACKTRACK_TOKENS: + result[metric] = self.engine.metrics.engine_backtrack_tokens + elif metric == MonitoringMetric.TOKEN_COUNT: + result[metric] = lm.token_count if lm is not None else None + elif metric == MonitoringMetric.TOKEN_REDUCTION: + if lm is not None and lm.token_count > 0: + result[metric] = 1 - (self.engine.metrics.engine_output_tokens / lm.token_count) + else: + result[metric] = None + + return result + + def get_metric(self, metric: MonitoringMetric, lm: Union[Model, None] = None) -> Any: + return self.get_metrics([metric], lm)[metric] \ No newline at end of file From 9b36c7feaaf6bbd5121207fac6fd9f4fa48e6df2 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 9 Oct 2024 17:55:22 -0700 Subject: [PATCH 058/133] Add basic metric worker --- guidance/models/_model.py | 46 ++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 203252f6d..4b009f4ca 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -58,10 +58,11 @@ # TODO(nopdive): Remove on implementation. class MockMetricsGenerator: - def __init__(self, renderer: Renderer, sleep_sec = 0.1): + def __init__(self, renderer: Renderer, monitor: "Monitor", sleep_sec = 0.5): from ..visual._async import run_async_task self._renderer = renderer + self._monitor = monitor self._sleep_sec = sleep_sec run_async_task(self._emit()) @@ -73,22 +74,52 @@ async def _emit(self): time_start = time.time() while True: await asyncio.sleep(self._sleep_sec) + + cpu_percent = self._monitor.get_metric(MonitoringMetric.CPU_USAGE) + mem_percent = self._monitor.get_metric(MonitoringMetric.MEM_USAGE) + gpu_percent = self._monitor.get_metric(MonitoringMetric.GPU_USAGE) + gpu_used_vram = self._monitor.get_metric(MonitoringMetric.GPU_USED_MEM) + + if gpu_percent: + gpu_percent = max(gpu_percent) + else: + gpu_percent = 0 + + if gpu_used_vram: + gpu_used_vram = max(gpu_used_vram) + else: + gpu_used_vram = 0 + + if not cpu_percent: + cpu_percent = 0 + + if not mem_percent: + mem_percent = 0 + + # print(f"CPU: {cpu_percent}, RAM: {mem_percent}") + # print("gpu_percent", gpu_percent) + # print("gpu_used_vram",gpu_used_vram) + time_end = time.time() time_elapsed = time_end - time_start self._renderer.update( MetricMessage(name='wall time', value=time_elapsed) ) + self._renderer.update( - MetricMessage(name='gpu', value=random.uniform(0, 1)) + MetricMessage(name='cpu', value=self._monitor.get_metric(MonitoringMetric.CPU_USAGE)) ) + self._renderer.update( - MetricMessage(name='cpu', value=random.uniform(0, 1)) + MetricMessage(name='ram', value=self._monitor.get_metric(MonitoringMetric.MEM_USAGE)) ) + self._renderer.update( - MetricMessage(name='ram', value=random.uniform(0, 128)) + MetricMessage(name='gpu', value=gpu_percent) ) + self._renderer.update( - MetricMessage(name='vram', value=random.uniform(0, 24)) + MetricMessage(name='vram', value=gpu_used_vram) ) @@ -127,8 +158,11 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False, **kwargs): self.renderer.subscribe(self._msg_recv) self.model_dict: dict[int, Model] = {} + self.monitor = Monitor(self) + self.monitor.start() + # TODO(nopdive): Remove on implementation. - self.metrics_generator = MockMetricsGenerator(self.renderer) + self.metrics_generator = MockMetricsGenerator(self.renderer, self.monitor) self.post_exec_generator = MockPostExecGenerator(self.renderer) def _msg_recv(self, message: GuidanceMessage) -> None: From b5ee7a0c307106d40b585f5f1f20343985c10186 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Wed, 9 Oct 2024 18:36:38 -0700 Subject: [PATCH 059/133] Styling with big font. --- client/graphpaper-inline/src/TokenGrid.svelte | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/client/graphpaper-inline/src/TokenGrid.svelte b/client/graphpaper-inline/src/TokenGrid.svelte index 24bb12599..82b8639f4 100644 --- a/client/graphpaper-inline/src/TokenGrid.svelte +++ b/client/graphpaper-inline/src/TokenGrid.svelte @@ -129,42 +129,44 @@ } const doNothing = (_: any) => {} const escapeWhitespaceCharacters = (text: string) => { - return text.replaceAll(' ', ' ').replaceAll('\t', '\\t').replaceAll('\n', '\\n'); + return text.replaceAll(' ', '\\s').replaceAll('\t', '\\t').replaceAll('\n', '\\n'); } -
+
{#if tooltipToken} -
-
- +
+
+
+ Token +
+
{@html DOMPurify.sanitize(escapeWhitespaceCharacters(tooltipToken.value))} - +
- +
- - - + - + - + - + From 5ddd90d7438493e806bc488d491903fc599ba0ea Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Wed, 9 Oct 2024 19:04:11 -0700 Subject: [PATCH 060/133] UI works with minimal real-estate. Min height required to allow tooltip not to overflow. --- client/graphpaper-inline/src/App.svelte | 4 +-- client/graphpaper-inline/src/TokenGrid.svelte | 26 +++++++++---------- guidance/resources/graphpaper-inline.html | 4 +-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 172224c58..36fa21d12 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -153,9 +153,9 @@ -
+
-
- Token + + Prob
degeneratesdegenerates 0.983
jugsjugs 0.201
madnessmadness 0.005
- - - + - - + + - - + + - - + +
+ + Prob
degenerates0.983degenerates0.983
jugs0.201jugs0.201
madness0.005madness0.005
diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index 35da23738..67628ee29 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,8 +9,8 @@ From 8dbd57ef33b04e19606830b8bab28a02ef3dbafb Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Wed, 9 Oct 2024 19:28:45 -0700 Subject: [PATCH 061/133] Minimum widths for metric cards. This is important so that the layout doesn't mess up in near-real-time. --- client/graphpaper-inline/src/App.svelte | 3 +-- client/graphpaper-inline/src/MetricCard.svelte | 4 ++-- guidance/resources/graphpaper-inline.html | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 36fa21d12..a6c33be65 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -55,8 +55,7 @@ nodeAttrs = nodeAttrs; } } - - nodeAttrs = mockTokens; + // nodeAttrs = mockTokens; // TODO(nopdive): Restrict metrics while updating style. const metricDefs: Record = { diff --git a/client/graphpaper-inline/src/MetricCard.svelte b/client/graphpaper-inline/src/MetricCard.svelte index da36a7cfe..269fef180 100644 --- a/client/graphpaper-inline/src/MetricCard.svelte +++ b/client/graphpaper-inline/src/MetricCard.svelte @@ -30,9 +30,9 @@ {:else} {#if typeof value === "number"} -
{value.toFixed(metricDef.precision)}{metricDef.units}
+
{value.toFixed(metricDef.precision)}{metricDef.units}
{:else} -
{value}{metricDef.units}
+
{value}{metricDef.units}
{/if} {/if}
\ No newline at end of file diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index 67628ee29..07d265d69 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,8 +9,8 @@ From e155f86e786e7e1e5cb630dd06324f72dda6b989 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Thu, 10 Oct 2024 16:55:23 -0700 Subject: [PATCH 062/133] return if the token was filtered out by the parser (is_masked) --- guidance/_schema.py | 1 + guidance/models/_model.py | 61 +++++++++++++++++++++++++++------------ guidance/visual/_trace.py | 2 +- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/guidance/_schema.py b/guidance/_schema.py index 88b134732..70dd6a9b8 100644 --- a/guidance/_schema.py +++ b/guidance/_schema.py @@ -30,6 +30,7 @@ class BaseGenToken(BaseModel): prob: float # bytes: bytes text: str = "" + is_masked: bool = False class GenToken(BaseGenToken): latency_ms: float diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 4b009f4ca..e22f294f2 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -196,7 +196,7 @@ def _msg_recv(self, message: GuidanceMessage) -> None: gen_tokens_indices = [] for vis_chunk in vis_chunks: for engine_output in vis_chunk.engine_outputs: - gen_tokens_lats.append((engine_output.issued_token.token, engine_output.issued_token.latency_ms)) + gen_tokens_lats.append((engine_output.issued_token.token, engine_output.issued_token.latency_ms, engine_output.masked_top_k)) gen_tokens_indices.append(len(gen_tokens_lats) - 1) gen_tokens_lats_idx = 0 @@ -278,15 +278,6 @@ def _msg_recv(self, message: GuidanceMessage) -> None: _gen_tokens.append(_gen_token) for i, _gen_token in enumerate(_gen_tokens): - # if i < len(vis_chunk.generated_tokens): - # _gen_token.latency_ms = vis_chunk.generated_tokens[i].latency_ms - # _gen_token.is_generated = True - # else: - # if is_force_forwarded: - # _gen_token.is_force_forwarded = True - # if i - len(vis_chunk.generated_tokens) < len(vis_chunk.force_forwarded_tokens): - # _gen_token.latency_ms = vis_chunk.force_forwarded_tokens[i - len(vis_chunk.generated_tokens)].latency_ms - if not is_input: if i < len(vis_chunk.generated_tokens): _gen_token.is_generated = True @@ -294,21 +285,53 @@ def _msg_recv(self, message: GuidanceMessage) -> None: if is_force_forwarded: _gen_token.is_force_forwarded = True - # base_idx = gen_tokens_lats_idx - # while base_idx < len(gen_tokens_lats): - # if _gen_token.token == gen_tokens_lats[base_idx][0]: - # _gen_token.latency_ms = gen_tokens_lats[base_idx][1] - # gen_tokens_lats_idx = base_idx + 1 - # break - - # base_idx += 1 - + found_perfect_match = False max_idx = gen_tokens_indices[vis_chunk_idx] for idx in range(max_idx, -1, -1): if _gen_token.token == gen_tokens_lats[idx][0]: _gen_token.latency_ms = gen_tokens_lats[idx][1] + _masked_top_k = gen_tokens_lats[idx][2] + if _masked_top_k is None: + # in free accepting state, no masking + for _token in _gen_token.top_k: + _token.is_masked = False + else: + _masked_tokens = [token.token for token in _masked_top_k] + for _token in _gen_token.top_k: + if _token.token not in _masked_tokens: + _token.is_masked = True + else: + _token.is_masked = False + + found_perfect_match = True break + if not found_perfect_match: + # only search within this chunk + max_idx = gen_tokens_indices[vis_chunk_idx] + prev_max_idx = -1 if vis_chunk_idx == 0 else gen_tokens_indices[vis_chunk_idx - 1] - 1 + for idx in range(max_idx, prev_max_idx, -1): + if self.tokenizer.decode([gen_tokens_lats[idx][0]]).decode("utf-8") in _gen_token.text: + _gen_token.latency_ms = gen_tokens_lats[idx][1] + _masked_top_k = gen_tokens_lats[idx][2] + if _masked_top_k is None: + # in free accepting state, no masking + for _token in _gen_token.top_k: + _token.is_masked = False + else: + _masked_tokens = [token.token for token in _masked_top_k] + for _token in _gen_token.top_k: + if _token.token not in _masked_tokens and _token.token != _gen_token.token: + _token.is_masked = True + else: + _token.is_masked = False + + break + else: + # input tokens are not masked + for _token in _gen_token.top_k: + _token.is_masked = False + processed_gen_tokens.extend(_gen_tokens) start_idx = end_idx + 1 diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index c21f21adc..5b122529c 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -85,7 +85,7 @@ def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: Jupy top_k = {} # find the correct token for _item in complete_msg.tokens[prob_idx].top_k: - top_k[f"{_item.text}"] = f"{_item.prob}" + top_k[f"{_item.text}"] = f"{_item.prob} - Masked: {_item.is_masked}" top_k = json.dumps(top_k, indent=2) latency = f"{complete_msg.tokens[prob_idx].latency_ms:.2f}" From 1afa737ce14a0a0915d7bb5d988af67fb30aa9c6 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Fri, 11 Oct 2024 00:26:56 -0700 Subject: [PATCH 063/133] Working tooltip. Still needs strikethroughs. --- client/graphpaper-inline/src/App.svelte | 45 +- .../graphpaper-inline/src/MetricCard.svelte | 2 +- client/graphpaper-inline/src/TokenGrid.svelte | 146 +- .../src/TokenGridItem.svelte | 16 +- client/graphpaper-inline/src/mocks.ts | 2175 ++++++++++++++++- client/graphpaper-inline/src/stitch.ts | 53 +- guidance/models/_model.py | 23 +- guidance/resources/graphpaper-inline.html | 4 +- guidance/trace/_trace.py | 1 + guidance/visual/_message.py | 16 +- guidance/visual/_renderer.py | 27 +- guidance/visual/_trace.py | 4 +- 12 files changed, 2347 insertions(+), 165 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index a6c33be65..9487492c5 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -7,16 +7,26 @@ clientmsg, type StitchMessage, type NodeAttr, + type GenToken, isTraceMessage, - isTextOutput, isRoleOpenerInput, isRoleCloserInput + isTextOutput, + isRoleOpenerInput, + isRoleCloserInput, + isResetDisplayMessage, + isMetricMessage, + isExecutionCompletedMessage, + isExecutionCompletedOutputMessage, } from './stitch'; import StitchHandler from './StitchHandler.svelte'; import {onMount} from "svelte"; import MetricCard, {type MetricDef, type MetricVal} from "./MetricCard.svelte"; - import {mockTokens} from "./mocks"; + // import {mockGenTokens, mockNodeAttrs} from "./mocks"; let msg: any; - let nodeAttrs: Array = []; + let textComponents: Array = []; + let tokenDetails: Array = []; + // textComponents = mockNodeAttrs; + // tokenDetails = mockGenTokens; let completedExecution: boolean = false; $: if ($kernelmsg !== undefined) { @@ -24,38 +34,39 @@ msg = JSON.parse($kernelmsg.content); if (isTraceMessage(msg)) { if (isTextOutput(msg.node_attr)) { - nodeAttrs.push(msg.node_attr); + textComponents.push(msg.node_attr); } else if (isRoleOpenerInput(msg.node_attr)) { - nodeAttrs.push(msg.node_attr) + textComponents.push(msg.node_attr) } else if (isRoleCloserInput(msg.node_attr)) { - nodeAttrs.push(msg.node_attr) + textComponents.push(msg.node_attr) } - } else if (msg.class_name === "TokenBatchMessage") { - console.log(msg.tokens); - } else if (msg.class_name === "ResetDisplayMessage") { - nodeAttrs = []; - } else if (msg.class_name === "MetricMessage") { + } else if (isResetDisplayMessage(msg)) { + textComponents = []; + } else if (isMetricMessage(msg)) { + // TODO(nopdive): Move aggregation to server-side. const name = msg.name; const value = msg.value; if (name in metrics && name in metricDefs) { let currVal = metrics[name]; const metricDef = metricDefs[name]; - if (metricDef.isScalar === false && currVal instanceof Array) { - metrics[name] = [...currVal.slice(1), value]; + if (metricDef.isScalar === false) { + currVal = currVal as Array; + metrics[name] = [...currVal.slice(1), value as string | number]; } else if (metricDef.isScalar === true) { metrics[name] = value; } else { console.log(`Cannot handle metric: ${name}: ${value}.`) } } - } else if (msg.class_name === 'JupyterCellExecutionCompletedMessage') { + } else if (isExecutionCompletedMessage(msg)) { completedExecution = true; + } else if (isExecutionCompletedOutputMessage(msg)) { + tokenDetails = msg.tokens; } - nodeAttrs = nodeAttrs; + textComponents = textComponents; } } - // nodeAttrs = mockTokens; // TODO(nopdive): Restrict metrics while updating style. const metricDefs: Record = { @@ -163,6 +174,6 @@
- +
\ No newline at end of file diff --git a/client/graphpaper-inline/src/MetricCard.svelte b/client/graphpaper-inline/src/MetricCard.svelte index 269fef180..07f82a9fa 100644 --- a/client/graphpaper-inline/src/MetricCard.svelte +++ b/client/graphpaper-inline/src/MetricCard.svelte @@ -6,7 +6,7 @@ isScalar: boolean, precision: number, } - export type MetricVal = string | number | ArrayLike | ArrayLike; + export type MetricVal = string | number | Array; + -{#each token.value as ch, i} +{#each token.text as ch, i} {#if ch === ' '}   @@ -25,7 +37,7 @@
{:else} - + {#if i === 0} {token.role} diff --git a/client/graphpaper-inline/src/mocks.ts b/client/graphpaper-inline/src/mocks.ts index d3be0f696..67fb88c02 100644 --- a/client/graphpaper-inline/src/mocks.ts +++ b/client/graphpaper-inline/src/mocks.ts @@ -1,75 +1,2110 @@ // Mocks for interactive testing -import {type TextOutput, type RoleOpenerInput, type RoleCloserInput} from './stitch'; +import {type TextOutput, type RoleOpenerInput, type RoleCloserInput, type GenToken} from './stitch'; -const textToNodeAttrs = (texts: Array) => { - let results = []; +export const mockNodeAttrs: Array = [ + { + "class_name": "RoleOpenerInput", + "name": "system", + "text": "<|im_start|>system\n", + "closer_text": "<|im_end|>\n" + }, + { + "class_name": "TextOutput", + "value": "<|im_start|>system\n", + "is_input": true, + "is_generated": false, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "TextOutput", + "value": "You are responsible for autocompleting a sentence.", + "is_input": true, + "is_generated": false, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "RoleCloserInput", + "name": "system", + "text": "<|im_end|>\n" + }, + { + "class_name": "TextOutput", + "value": "<|im_end|>\n", + "is_input": true, + "is_generated": false, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "RoleOpenerInput", + "name": "user", + "text": "<|im_start|>user\n", + "closer_text": "<|im_end|>\n" + }, + { + "class_name": "TextOutput", + "value": "<|im_start|>user\n", + "is_input": true, + "is_generated": false, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "TextOutput", + "value": "Roses are red and ", + "is_input": true, + "is_generated": false, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "TextOutput", + "value": "you", + "is_input": false, + "is_generated": false, + "is_force_forwarded": true, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "TextOutput", + "value": " are", + "is_input": false, + "is_generated": true, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "TextOutput", + "value": " responsible", + "is_input": false, + "is_generated": true, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "RoleCloserInput", + "name": "user", + "text": "<|im_end|>\n" + }, + { + "class_name": "TextOutput", + "value": "<|im_end|>\n", + "is_input": true, + "is_generated": false, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + }, + { + "class_name": "TextOutput", + "value": ">:(", + "is_input": true, + "is_generated": false, + "is_force_forwarded": false, + "token_count": 0, + "prob": 0 + } +]; - // NOTE: Mock does not work with nested roles. Would need a stack for that. - let activeRole: string | undefined = undefined; - - for (text of texts) { - if (text === "<|system|>") { - const roleOpenerInput: RoleOpenerInput = { - class_name: 'RoleOpenerInput', - name: 'system', - text: "<|system|>", - closer_text: "<|end|>", - } - activeRole = 'system'; - results.push(roleOpenerInput); - } else if (text === "<|assistant|>") { - const roleOpenerInput: RoleOpenerInput = { - class_name: 'RoleOpenerInput', - name: 'assistant', - text: "<|assistant|>", - closer_text: "<|end|>", - } - activeRole = 'user'; - results.push(roleOpenerInput); - } else if (text === "<|user|>") { - const roleOpenerInput: RoleOpenerInput = { - class_name: 'RoleOpenerInput', - name: 'user', - text: "<|user|>", - closer_text: "<|end|>", - } - activeRole = 'user'; - results.push(roleOpenerInput); - } else if (text === "<|end|>") { - if (activeRole === undefined) { - console.log("Active role not set for mock.") - } - const roleCloserInput: RoleCloserInput = { - class_name: 'RoleCloserInput', - name: activeRole, - text: "<|end|>", - } - activeRole = undefined; - results.push(roleCloserInput); - } else if (text === "<|endoftext|>") { - // Do nothing. - } - const textOutput: TextOutput = { - class_name: "TextOutput", - value: text, - is_generated: false, - token_count: 0, - prob: 0. - } - results.push(textOutput); +export const mockGenTokens: Array = + [ + { + "token": 27, + "prob": 1, + "text": "<", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 27, + "prob": 1, + "text": "<" + } + ] + }, + { + "token": 91, + "prob": 0.0008722934871912003, + "text": "|", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 198, + "prob": 0.029958423227071762, + "text": "\n" + }, + { + "token": 13, + "prob": 0.013489649631083012, + "text": "." + }, + { + "token": 16, + "prob": 0.011806909926235676, + "text": "1" + }, + { + "token": 12, + "prob": 0.010169479995965958, + "text": "-" + }, + { + "token": 15, + "prob": 0.009271609596908092, + "text": "0" + }, + { + "token": 91, + "prob": 0.0008722934871912003, + "text": "|" + } + ] + }, + { + "token": 320, + "prob": 0.000027396810764912516, + "text": "im", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 930, + "prob": 0.12004928290843964, + "text": " |" + }, + { + "token": 29, + "prob": 0.06939840316772461, + "text": ">" + }, + { + "token": 27, + "prob": 0.03129403665661812, + "text": "<" + }, + { + "token": 198, + "prob": 0.028110388666391373, + "text": "\n" + }, + { + "token": 60, + "prob": 0.02136152982711792, + "text": "]" + }, + { + "token": 320, + "prob": 0.000027396810764912516, + "text": "im" + } + ] + }, + { + "token": 62, + "prob": 0.01482831034809351, + "text": "_", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.42150357365608215, + "text": "|" + }, + { + "token": 7629, + "prob": 0.023308370262384415, + "text": "perial" + }, + { + "token": 60, + "prob": 0.020157789811491966, + "text": "]" + }, + { + "token": 14, + "prob": 0.018618104979395866, + "text": "/" + }, + { + "token": 92, + "prob": 0.015273063443601131, + "text": "}" + }, + { + "token": 62, + "prob": 0.01482831034809351, + "text": "_" + } + ] + }, + { + "token": 9688, + "prob": 0.0003535318828653544, + "text": "start", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.017649956047534943, + "text": "|" + }, + { + "token": 79, + "prob": 0.011138186790049076, + "text": "p" + }, + { + "token": 16366, + "prob": 0.011045439168810844, + "text": "client" + }, + { + "token": 82, + "prob": 0.008266090415418148, + "text": "s" + }, + { + "token": 15908, + "prob": 0.00811094231903553, + "text": "dir" + }, + { + "token": 9688, + "prob": 0.0003535318828653544, + "text": "start" + } + ] + }, + { + "token": 91, + "prob": 0.12612135708332062, + "text": "|", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 62, + "prob": 0.3673606216907501, + "text": "_" + }, + { + "token": 91, + "prob": 0.12612135708332062, + "text": "|" + }, + { + "token": 929, + "prob": 0.041732169687747955, + "text": "up" + }, + { + "token": 92, + "prob": 0.032134898006916046, + "text": "}" + }, + { + "token": 28, + "prob": 0.024743985384702682, + "text": "=" + } + ] + }, + { + "token": 29, + "prob": 0.012729871086776257, + "text": ">", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 259, + "prob": 0.028011340647935867, + "text": "in" + }, + { + "token": 4023, + "prob": 0.01824311725795269, + "text": "http" + }, + { + "token": 27, + "prob": 0.015950094908475876, + "text": "<" + }, + { + "token": 929, + "prob": 0.01563503034412861, + "text": "up" + }, + { + "token": 29, + "prob": 0.012729871086776257, + "text": ">" + } + ] + }, + { + "token": 10057, + "prob": 0.00004459881893126294, + "text": "system", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.2632869482040405, + "text": "|" + }, + { + "token": 198, + "prob": 0.05016319826245308, + "text": "\n" + }, + { + "token": 1279, + "prob": 0.04930492863059044, + "text": " <" + }, + { + "token": 930, + "prob": 0.045030541718006134, + "text": " |" + }, + { + "token": 28, + "prob": 0.023192651569843292, + "text": "=" + }, + { + "token": 10057, + "prob": 0.00004459881893126294, + "text": "system" + } + ] + }, + { + "token": 198, + "prob": 0.01464146375656128, + "text": "\n", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.20154249668121338, + "text": "|" + }, + { + "token": 3556, + "prob": 0.11300163716077805, + "text": "" + }, + { + "token": 361, + "prob": 0.02362215332686901, + "text": "if" + }, + { + "token": 3546, + "prob": 0.019490960985422134, + "text": "Im" + }, + { + "token": 930, + "prob": 0.016572270542383194, + "text": " |" + } + ] + }, + { + "token": 62, + "prob": 0.9976491332054138, + "text": "_", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 62, + "prob": 0.9976491332054138, + "text": "_" + }, + { + "token": 91, + "prob": 0.000336194148985669, + "text": "|" + }, + { + "token": 41052, + "prob": 0.00012316853099036962, + "text": "_(" + }, + { + "token": 29, + "prob": 0.000117526447866112, + "text": ">" + }, + { + "token": 59, + "prob": 0.00009838600090006366, + "text": "\\" + } + ] + }, + { + "token": 437, + "prob": 0.4462008774280548, + "text": "end", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 437, + "prob": 0.4462008774280548, + "text": "end" + }, + { + "token": 9688, + "prob": 0.09380462765693665, + "text": "start" + }, + { + "token": 12957, + "prob": 0.017503555864095688, + "text": "last" + }, + { + "token": 11338, + "prob": 0.016530489549040794, + "text": "stop" + }, + { + "token": 27471, + "prob": 0.012605799362063408, + "text": "begin" + } + ] + }, + { + "token": 91, + "prob": 0.9823351502418518, + "text": "|", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.9823351502418518, + "text": "|" + }, + { + "token": 29, + "prob": 0.002384455408900976, + "text": ">" + }, + { + "token": 60, + "prob": 0.0023481370881199837, + "text": "]" + }, + { + "token": 15886, + "prob": 0.002319696359336376, + "text": "||" + }, + { + "token": 930, + "prob": 0.0013476606691256166, + "text": " |" + } + ] + }, + { + "token": 29, + "prob": 0.9560039639472961, + "text": ">", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 29, + "prob": 0.9560039639472961, + "text": ">" + }, + { + "token": 6927, + "prob": 0.005681615322828293, + "text": "><" + }, + { + "token": 60, + "prob": 0.0032080409582704306, + "text": "]" + }, + { + "token": 27, + "prob": 0.002467683283612132, + "text": "<" + }, + { + "token": 4211, + "prob": 0.0021098603028804064, + "text": ">>" + } + ] + }, + { + "token": 198, + "prob": 0.02139684557914734, + "text": "\n", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 10057, + "prob": 0.35756662487983704, + "text": "system" + }, + { + "token": 198, + "prob": 0.02139684557914734, + "text": "\n" + }, + { + "token": 11964, + "prob": 0.01934202015399933, + "text": "System" + }, + { + "token": 1662, + "prob": 0.010047300718724728, + "text": "not" + }, + { + "token": 1169, + "prob": 0.006138301454484463, + "text": "the" + } + ] + }, + { + "token": 27, + "prob": 0.039419274777173996, + "text": "<", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 1639, + "prob": 0.1665498912334442, + "text": "You" + }, + { + "token": 464, + "prob": 0.06005862355232239, + "text": "The" + }, + { + "token": 27, + "prob": 0.039419274777173996, + "text": "<" + }, + { + "token": 1212, + "prob": 0.027387971058487892, + "text": "This" + }, + { + "token": 1532, + "prob": 0.022758493199944496, + "text": "If" + } + ] + }, + { + "token": 91, + "prob": 0.7559300065040588, + "text": "|", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.7559300065040588, + "text": "|" + }, + { + "token": 320, + "prob": 0.006860977970063686, + "text": "im" + }, + { + "token": 15886, + "prob": 0.0064566307701170444, + "text": "||" + }, + { + "token": 1671, + "prob": 0.004361273255199194, + "text": "br" + }, + { + "token": 930, + "prob": 0.004342366941273212, + "text": " |" + } + ] + }, + { + "token": 320, + "prob": 0.8291174173355103, + "text": "im", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 320, + "prob": 0.8291174173355103, + "text": "im" + }, + { + "token": 3546, + "prob": 0.012388699688017368, + "text": "Im" + }, + { + "token": 361, + "prob": 0.007399916183203459, + "text": "if" + }, + { + "token": 72, + "prob": 0.004467112943530083, + "text": "i" + }, + { + "token": 29, + "prob": 0.0026658582501113415, + "text": ">" + } + ] + }, + { + "token": 62, + "prob": 0.9993433356285095, + "text": "_", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 62, + "prob": 0.9993433356285095, + "text": "_" + }, + { + "token": 7, + "prob": 0.0000683960533933714, + "text": "(" + }, + { + "token": 59, + "prob": 0.00006206566467881203, + "text": "\\" + }, + { + "token": 13, + "prob": 0.00004414364229887724, + "text": "." + }, + { + "token": 29, + "prob": 0.00002257493724755477, + "text": ">" + } + ] + }, + { + "token": 9688, + "prob": 0.6440587043762207, + "text": "start", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 9688, + "prob": 0.6440587043762207, + "text": "start" + }, + { + "token": 437, + "prob": 0.05475924164056778, + "text": "end" + }, + { + "token": 27471, + "prob": 0.043713200837373734, + "text": "begin" + }, + { + "token": 11338, + "prob": 0.003659052774310112, + "text": "stop" + }, + { + "token": 38690, + "prob": 0.003096950938925147, + "text": "starting" + } + ] + }, + { + "token": 91, + "prob": 0.9499432444572449, + "text": "|", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.9499432444572449, + "text": "|" + }, + { + "token": 62, + "prob": 0.00848131813108921, + "text": "_" + }, + { + "token": 15886, + "prob": 0.005286256782710552, + "text": "||" + }, + { + "token": 930, + "prob": 0.003634629538282752, + "text": " |" + }, + { + "token": 29, + "prob": 0.0032877251505851746, + "text": ">" + } + ] + }, + { + "token": 29, + "prob": 0.9690060615539551, + "text": ">", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 29, + "prob": 0.9690060615539551, + "text": ">" + }, + { + "token": 6927, + "prob": 0.004052347969263792, + "text": "><" + }, + { + "token": 24618, + "prob": 0.0019232694758102298, + "text": ">\"" + }, + { + "token": 27, + "prob": 0.0012727173743769526, + "text": "<" + }, + { + "token": 4211, + "prob": 0.0011409870348870754, + "text": ">>" + } + ] + }, + { + "token": 7220, + "prob": 0.003625249955803156, + "text": "user", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 10057, + "prob": 0.43270590901374817, + "text": "system" + }, + { + "token": 11964, + "prob": 0.012400631792843342, + "text": "System" + }, + { + "token": 9688, + "prob": 0.008726297877728939, + "text": "start" + }, + { + "token": 847, + "prob": 0.007208186201751232, + "text": "other" + }, + { + "token": 198, + "prob": 0.006247976794838905, + "text": "\n" + }, + { + "token": 7220, + "prob": 0.003625249955803156, + "text": "user" + } + ] + }, + { + "token": 198, + "prob": 0.5544214248657227, + "text": "\n", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 198, + "prob": 0.5544214248657227, + "text": "\n" + }, + { + "token": 62, + "prob": 0.04264130815863609, + "text": "_" + }, + { + "token": 12, + "prob": 0.029624110087752342, + "text": "-" + }, + { + "token": 29, + "prob": 0.014048474840819836, + "text": ">" + }, + { + "token": 14, + "prob": 0.011965525336563587, + "text": "/" + } + ] + }, + { + "token": 49, + "prob": 0.00022193520271684974, + "text": "R", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 1639, + "prob": 0.39992958307266235, + "text": "You" + }, + { + "token": 27, + "prob": 0.11402493715286255, + "text": "<" + }, + { + "token": 464, + "prob": 0.05199533700942993, + "text": "The" + }, + { + "token": 1212, + "prob": 0.01731906458735466, + "text": "This" + }, + { + "token": 3556, + "prob": 0.016215169802308083, + "text": "" + }, + { + "token": 361, + "prob": 0.0009765964932739735, + "text": "if" + } + ] + }, + { + "token": 62, + "prob": 0.9997590184211731, + "text": "_", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 62, + "prob": 0.9997590184211731, + "text": "_" + }, + { + "token": 13, + "prob": 0.000022090805941843428, + "text": "." + }, + { + "token": 59, + "prob": 0.000015420928320963867, + "text": "\\" + }, + { + "token": 834, + "prob": 0.000013038138604315463, + "text": "__" + }, + { + "token": 12, + "prob": 0.000011890577297890559, + "text": "-" + } + ] + }, + { + "token": 437, + "prob": 0.7618218064308167, + "text": "end", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 437, + "prob": 0.7618218064308167, + "text": "end" + }, + { + "token": 9688, + "prob": 0.17939522862434387, + "text": "start" + }, + { + "token": 27471, + "prob": 0.00941860768944025, + "text": "begin" + }, + { + "token": 11338, + "prob": 0.005442698486149311, + "text": "stop" + }, + { + "token": 1571, + "prob": 0.0011666559148579836, + "text": "ending" + } + ] + }, + { + "token": 91, + "prob": 0.9977994561195374, + "text": "|", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.9977994561195374, + "text": "|" + }, + { + "token": 62, + "prob": 0.00038299127481877804, + "text": "_" + }, + { + "token": 15886, + "prob": 0.00029917186475358903, + "text": "||" + }, + { + "token": 29, + "prob": 0.0001353792322333902, + "text": ">" + }, + { + "token": 10, + "prob": 0.00012695405166596174, + "text": "+" + } + ] + }, + { + "token": 29, + "prob": 0.9984844326972961, + "text": ">", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 29, + "prob": 0.9984844326972961, + "text": ">" + }, + { + "token": 60, + "prob": 0.00033915083622559905, + "text": "]" + }, + { + "token": 6927, + "prob": 0.00010037984611699358, + "text": "><" + }, + { + "token": 28, + "prob": 0.00008626521594123915, + "text": "=" + }, + { + "token": 24618, + "prob": 0.00007595126226078719, + "text": ">\"" + } + ] + }, + { + "token": 198, + "prob": 0.5057048797607422, + "text": "\n", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 198, + "prob": 0.5057048797607422, + "text": "\n" + }, + { + "token": 1640, + "prob": 0.21033842861652374, + "text": "for" + }, + { + "token": 10057, + "prob": 0.032438330352306366, + "text": "system" + }, + { + "token": 7220, + "prob": 0.028024563565850258, + "text": "user" + }, + { + "token": 329, + "prob": 0.010914873331785202, + "text": " for" + } + ] + }, + { + "token": 31175, + "prob": 0.0000045710116864938755, + "text": ">:", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 27, + "prob": 0.3989731967449188, + "text": "<" + }, + { + "token": 1639, + "prob": 0.1570923775434494, + "text": "You" + }, + { + "token": 49, + "prob": 0.03772936016321182, + "text": "R" + }, + { + "token": 464, + "prob": 0.027823705226182938, + "text": "The" + }, + { + "token": 3556, + "prob": 0.01715909130871296, + "text": ":" + } + ] + }, + { + "token": 7, + "prob": 0.0029301203321665525, + "text": "(", + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 16, + "prob": 0.0514117032289505, + "text": "1" + }, + { + "token": 27, + "prob": 0.03453383222222328, + "text": "<" + }, + { + "token": 15, + "prob": 0.03179513290524483, + "text": "0" + }, + { + "token": 352, + "prob": 0.01785029098391533, + "text": " 1" + }, + { + "token": 198, + "prob": 0.0139352697879076, + "text": "\n" + }, + { + "token": 7, + "prob": 0.0029301203321665525, + "text": "(" + } + ] } - - return results; -} - -let text = "Pack my box with five dozen liquor jugs valued at $12.95, according to sources."; -// text += "\n<-img:/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCACWAGQDASIAAhEBAxEB/8QAHQAAAQUBAQEBAAAAAAAAAAAABQADBAYHAggBCf/EAEMQAAEDAwMCBAIIAgcGBwAAAAECAwQABREGEiExQQcTIlFhcQgUFSMygaGxM5EWFyRCUnLBQ3OCotHwGCZFY3aywv/EABoBAAIDAQEAAAAAAAAAAAAAAAIDAAEEBQb/xAAtEQACAQMDAgMIAwEAAAAAAAAAAQIDESEEEjEiQQVRcRNhkaGx0eHwFIHB8f/aAAwDAQACEQMRAD8A9YQ/LcSCgg0QbaBoOyypGFJJB+FEY8xbZw+nI9xSkEychgGnkxx2TX2M8y8AULB/OpyG0nsKNK5VyImOa+/V8daIBpOK4dehsDL0lpv/ADLA/ersUQvJA5peVjtivjt+sTfBuTKj7IO8/pmoj2pbYjPlMyXfiGSB/wA2KmC8kzyxSKQngmgUnVoAPkW9ZwRnLicjPwBNDn9UXFZ+7iNp/wAyiarckWk2W30fCvh8s8ZFUhy9XpwcPNo/yo/61HVMuzp9dwe/4Tj9qreTaX0soJyCKVZ6pEhZ3KkvKPuXFf8AWlU3l7S0NpA4p4NpPU120zlQGKNQbW2+BuSDmq2g3K7IjPJSVx1qSrHVJ5qkSdfSLW+zCnyrzJkyEKdQ3DjqUNoKh1QnA/DjBOa3RvTsIRnnVoAKWlkfPBqh2BuO7oS1uuJTuVfQlRJ6pBTwfhyajTTJcpCdYXea2Fx9B6qfChkKlgR0kfN1wftX1+XrlwufZuk7GylPR6RcA5ke+1tJP61afDLw/Ra7/fLvdHLbb4kyQJdrckvokq+sBTja1FKyottqRt+7wAFJ3Dqc2i4T5Rt2oYj+oGC7MQlqKzHQksNkABSwepOSFdx6SPakVKsoVFCMbp9/IV7R3tYzK12XxU1F5UeJe7YxIdClhqHbXXvuxgZBURznIOfhUFuwXd67PW65ar1DKciyFxJCWYLMVhDyWysoU6o8YHOc9Rj4Vo1hcsEfT7ka7zZHnAhbBawlQyeRuPwz8D0qLpy4adtV0myrgEiG44l5qKwvcVuJ4BcUrjGOcBPJPJwORnUrOeyEVbzf2x8bv0ZU5VE7RRWLNpqLp1VwiMyp0haHWW1qkTUyE/hCxsKfSnhfIHeiKmx1AqddF2xx+XJtilkS5y5Kwv8Au7toSkY4GAntUbFOjust3I+nfbkYLYxwK42D2qSpNcFNEGMbBSp3B7ClUIWhCxuyO1FIc5TYwnJxQxtoqUAKPW2EMDIzTRR9lXGeuI4lhKxlCs/LFZxaIUyXpGDsfU005ciylST0WVdf1FbQ1CQITytg/hL7fA1lWmyE6EsY7rv5A/mD/pQS5LRIsehL5f7cLi0w+jeQG2n5p3uArUncNiCMApOeeMVOuHhfdbPGnTbsxGaZhhOFeY655xUeAk8D88dqv+gpa2LDFTISnfDU6/FcKsJKFPL3tEA9e4JHxo7reemTpi7uNuoVFVEGw8epZI6H5UhSvJpvhgrczBW7Qp2IbiFxm4zTPmPkx/NdKt+PSCsA8Hp1zQt0EQvtCPqNlpjzkMJUi3NguKUdo2pUCSSojgZ4zkjpV30lpJ/VjbTCFOeQygl9KFAFSFKAI578cEDIoXqeE6JLmjdOS3Lk/aUOOKeSdrbKkHeUNAYG70gEcdOCSayayu6TSd7NpeXK8/cZqu9SbvjsBmpTsqCEvqWtxh8tLcK0kLIxkhISNnyPzBIIp/HSpkhEA6XsUiE55i3myp5wN7ErVkYI9/TtyT344ximAn081qoScqab5NlJSUEpcjW2udlP7RmuQnJpwY1s+dKnSnFKoQs8dGFCrHbUZA4oAyPWKstrTnFNFB4NgW94Y/2Sv2rGtOp/8jWD/wCQGtqUP7E8P/bV+1Y3plsnQ1i+F+JoXyWXmxMXFvTkBbVx3svOuJSz5gTtUXVDYeMjqFA+/fmpl4ssn7JvQkPSFMwmSEJcb2J35wCAD8Dz7KHvU/SsqBcdIRLP/Yly0lSUBUnY4kh1Sgfw9cgcA8jvQe9Tj9mXy2yWlJdubQafcB2FsErJ2+5yVYx8650oQjWbk28/DP3Bi0uQDpWebbZpaxPchAspUuQSUtNIDoClrKfVgZ4Axkn4VHi3GdC1Cp3RVualPhgrbkSEONh9tRWC6Ar8OSlQCiQTg4Hc0vXeqf6CaJlOxZ8oRV2+VMeixo3nSZnk7SG20EHdnJynGSSMdyIcTxS1KuyzrZMftFqk3ZtxyO6mPlwtp2bWzuQNyEhSu+RhQPaud4glPUWfa1uPl+/kJ1KcZdfYIW2DcYUOU1MbU2wu5uPxEFSlBLLm1eE7gCE5OQO2SKY1I07IXaLeiVJYbmXBLTyo7xaWpAZdVt3J5AylPT2o6/fpepm3rjM8pbiZiWvrDWwJfAbb9QCQAMfh9zjNCNRKDMuxv4J8uepeAcZ2xXz/AKV1tO37BXNFFqVmu5kjGtre94rPeHMmBNTGQHlomq1NKU44lCVnPlAgJOUEEEjgpIyDWiM2lmxa6jQID8zyH7U+66h6Y88lS0vtBKsOKVggKUOMdaynS0nybvf9fW6yx1u3pDF3kMOtpBYiuKcThpQTu2qKAs9yUk4O4VqOntSRNZ36zalhsPsomWKSotPtlDjSxKbStCknnKVJI+OM1dN5yaqkUk2kW7ZSp8oNKtBmLDHSd4qx2vgihNviJlOOJjutOKZXsdCHEq8tXsrB4Pzo2xGeiLCXUYPBHOeKbyKDuQYjv+7V+1ZTpGMV6GsoxnF8Uf1rSnJaWITq3FBIDaup+FZjpG8tNaTtcRkNqeYuCpTgWraAntjg5Oe1U8MiCplx4lhYdfuTiPK88BHmqRhW9WQgN/eLIGOAO455qj2i+uayvEe46dQybJkKS8xuAeCQvO7dg4BI465J9qNazmaR05p25aqlWibczAYceUy3cNhDYO9ZQVJ2oICSc/lnmqV4OsIul0u+qEwrf9gOTfr1hSxIfTJY81vctp9DuUEgLzlBABJwMHNYKmlbnui+9/mZ3p5Se/sg7q5tEe5aUW++7Fjtolqfkozhprc3uJwQeR7fzHWhuvIUDUsuy2LTTDM5bjC3ZFxEXzcgrQgrfwVBLY6nnedgJJJwNNjKgvKYdfckRXmGXGEuR30BWxZG7k++BVDv2ndKRdWQ4Ue0aveVPSRJu0ctfV0AhKUNuOBaRnckrPoySevPCNTpJ1KrqRSd7c+ljRJbobGsfvc+aXs0Wy2B2NElCQ39pqSXE7/LKkobSQgK6DI6DjOepp/UFtl3BENyA/GbehyPPAkNqW2sFtbZSQlQPRwnr2qy3SzWCzWeFb9Pj0h7e8fTlSvSkE4JycJAySSccmq/d5aoA+9bWkkcZSa2UYOFNRnyHBKCSRVJGmLmLR9hGFpowPqyYnk+XLSPJAwEZDucY465p/SOmZFqlRnx9nMwocFcKKxDLysBbwcUoqdUo9RjHx+VNTNRnBKEOcdTsPFSNP6gh/UWAFAKdkPJyT1A24/eiUeq6Guo2rMt+M9aVcNkuICsdaVMAMe0bchfrcjXOg5s+JOhxyJ9vQ+ViS0CVK25IIUncohPQ5OMEjOvaL8SpF5ix0LvhlJxlKyAnr2OeleUvol3mQb8kBwlLaUqSlCiUgHqOvXHuOcGtrcFwsuo7nZ7Dpe53dLT5cZTb7e6792v1JG5KdvQ469qzJuNpx4Y6SUm4S7Gv3m73eTaZcJ4ebI8xYHkp9SmVElslI77eDjglJqpaeV9Xihl1BQtBIUlScEH2IPShWtdD+JOrbbb59o0o/b7hbE+hmXMZbMlpWNzasElJB9QJI5yO4qxNaV8Q5FitT8mxSpFyZStiSC62twNjBb3EK9RGVDOScAU6M25WafqJlBKN0zrUFttl609Ot91ClRXWT5iUnG4DsR0UD3Scg9CDVa8GIlstWm52lY99RcJNkuDjDzZe8xyM2v1sIcGBg+WU44GRg0W1LD1ha9MXda7VLt8pFukLZefY3obWG1FKinPqSFYyO44qp+DNxlP2G43F6Ol2ZKfjuzHo7G1LjhjN5VgZOM5xk8DA7UbfVYpX2M1ENIz2xUeSy2p9hPcKU4PyGP/ANUMVfA2r1JWkj/Egj96gw9TmbqGREMVaGIjLaUSCobXXF5UpKR19ISjJ91Y7GowUWGV6Iz6gTlLayOehCTisK0boXSt8noFzsyJI/o9ZJGVvvfxXWHC4vhf4lEAk9yK2yXJSqE/tUDlpzp/lNYHoDxW0NEvRirvzKlN6csSFFttxaQpDDiVDcE44VkHHcVQSL0vwg0HghuyONZ4PlXGWj9naqOpvCnSOh9O/XtJxbhbHET4gCWbrLLZ8yQhC8oU6UnKVEdKvjfihoJ7hOp4YJ/x7kf/AGAoB4jax0tO0opuJqC3PKM+3namSgnAltZ4zUwEXzQEuRN0Pp+ZMeU6+/a4jjrizlS1qZQVKJ9ySTSpjw3UP6vtNZH/AKPC6/7hFKrKGvDr6OPgP4OoCLIzcmSpvy1KmXpxxTg+JyCT8veisvQ/gnCjONxdNXBSVKU4XE3KUn1E8kLcd/YVkDniO028s25BdAOcx2M/85wP1oNK1Xqy/wApMdltEZDisJC1l11XPZIwB+tZHqoNWsaVppJ3uX6Zq57ws1fAh6Zuc9djmy2Yb8SXOXJaw82VIcRvJLa0qAB2naoHpRu+fSMs2kcNarjzLFc3ituMLi24qE+UKAXh6MHDgA55QDyMgVRr94P6pnXbTGr58JTdntshty4CVNx5zrhS00UsgklQJT1AAAPyoX9Ny3w2Y+jg0w0gFdwJSlI4JSz7UqtXnQoyqR7f6PoUKderGnLv39BzX3jcrWGqbRcLNrzSsa1tWa5wJkRm+OFDzkhspQ6UPpaBWjsFA98c1M+jf4m2DRVmucDV+q9GPqeWjyVKn+QRsQlO7HqwCByATyOnevCmrIDYSxjBKMqzj4GqTp6KHZ7TSkjO4jn4LSa5kPE6ibnZX/vy9fcdifhFJpQu/wB/6fs1bPFzwbvDrUWDqBu4SXh6WrYiQ+VKxkhOE4Peh/iDMiv2V5VqVOisqCilTyUJd4GT0zgdueeteV/o9WyfJt9nttiTi5SIshLBDnl7VbHcK3dsYz+VXv8Aq0+kI6h+Lf7+/NYVI3tx1PKUgN7MAbiSSN3OMfnXS0utnXp75r4J/k4+s0MNNUUIO/qX2BdkqtbqgdoWwo4B4GUHpWEWW1aif1Um5Wyxw5yE6WsERaH3UgpIbcUFA4IwQs8EZ9Nagu062s9vdZm2FLqwytIDLh5O01TdEO3qySVTrrY5bSXrRao3lD+IhxhgpcCgcd1D+RrQtRTtl2MzoTvhHE2Dcy4tU7w7U0rd/sYyXUqGByCEiq3qy1x5GmJa2dHPtPofjJbJjqbJWp9ASAFEA5JxWtDVMdzAMO4JJ7GOVftQbWmoGndNrbSHwTNg4C47ic/2tn4UcakXlMFwksNGjeEynh4X6SElX3oscAObjk7hHRnJ7nOaVV3w41KiJoHT0WYlTL7NsjNuNOoUhaFBpIKSCMggilTNyA2s8oDx5m3IpagWpMcH8KEJLq/54wP5V9tmsdemTJnxrRKdQ+oKSp19KAMdhk8fKtY8O/ogWhmHHmamuj7hUlJcbSdieOoJz8D7VtelfDrww0U2W7dp+KH2FhIfdAW4e4IKs9v2rnxot84NzrRXGTH/AAttvjReLrFubtleetzag6WW3QhpR/uFTi1bSAeeATU/6ZSLhFt2j5N2fhJC/roSiO4pwpwln8SzgEn4DHFbsdXphrVFgx2yQN7JWokbc8jgdv2Irzn9Jy1XTxPkWa2Lujkdm3OOrWGo+U73NgCE5PAOzOeeTjvS9XTh7CUIu7dvqM0dWX8iM5KyV/oeQ9X3FryQpOQA2pQPvVU0s+j68ysqyrzDz8CRW7Tvo+OSmUpmOzZLSBsUkEIJB7+nnjv8K+/+EXVTnlStNRVRVNKS5skOZQ4Ac4BPOT75xXFjp5uNksnfespqV28HoT6JMtld/wBMIUN60okApHX+G5XswpQrO1PmIJ4wOU/pzXm/6O+m52hNDwIV5RHTdY63g4WlKcbUCrgb8DBH6d63GJfGJqPPZ3JeTwpOxOPkRn9R+td7QUnQobXy8/Q874jVWor7lwsBk2+K9kuRkOII4WE4UPyofI0hY5yiXIqT7KSeRTf2p96FF9TDuPwrWAFD8h6vy5FMyLw46dratqs5JSonI/PmtMnFR6kZaak30sFTtI2yKAiKsLXnk/D27c1Cc0/bFJSxIgpfPmIXtcSVJSpKgpJ54yFAEHsQKNpVt9RVkkdPavjSXEEuqbJUfwjjk0mLTeFY0tOPLJ8KHEbjhJYGe/pBpUXtsdwxEFTXJ5ORzSp6sIcncwpLzwDjTa21lt1RSfxcH1Djt1wPlUGS1PEtt9aynzfulEIwSeqMDHxUKFW7R5txLtg1VfoRWAFebJEpKgOgKXAenzri8RfFVKg3arxZLkwrPEhCozrZ/ulOwKSrBGcEj50i7fKY3Zbhk2XBnTgFodc89o7mxuAye4AHuDj86aYs+mpEYSZvkOqfRu+9eP4T1B+III+YofcrlfIcVx+9aIuLpScqMRaZCO2SMKyPfGKG2/VOl1yxHROah+cCsNzWlM7FAjck7hjnORz71XRw/mF1cotltlQITaY7P1NDjQ2pcQhJLg7L479j8a7euIhJKg8/9UznKUY8sk+5H4ef+H5dB6mWpmxUe4xC6wS40G1J54IIOCeCOv5HtXbaPrLI8x97HIcSkD8XcHAz/wB/GjvZYACyJ8wFT8Rb4OPUhx0AOfH4Hj/Q0Vh3ZSwhUQp88HBynK0q7gj/AE6VUYsNTD7cdhmS8hZ2tpUSpWemCCclPPB/L2rXtE6GiWYJu9waaVPUMJAAw2Ov5n9qkW2DJWJFviTPqyXrs20h8+oNtghI9lEHv8O1dKbCFEpOCTlR/wC+9EZq0+YfUD8aFSHOQEAkk4AqSVy4YHCsE7AQB3OOgqbBSHHEnnjoPYUKHUJByPcdzRi3I8tPGT3NSNkE8lqiPJbYSkDPzNKmIw+6BKMk0qZcW0ecmJqlK2IGMjvRuEkBKXFjJJwKVKhWEHLIcistOhJUnPt8Kcn6dtdxYLUyGxIQRkpebCxj5EUqVOSTWRDbTwUO8+EmjVumS1akQ3eQHIa1MqHy28UMj+Et9Dx/oz4gXCM64lOW5yfrLRAzgdQR1NKlWOpTipYVjVCpJrLNZ0RohVghsuXh5mVdNoDrzQOwHvszyM/p0+dyJKE+QngkZz7D2FKlTUrIS3dg+UnaCOuKHKj7UqWhQSpw5JxnPalSq0WR/vGSVuBKkj/CcGj9uebcZbWhJAUM4NKlVdxq4LFHKVNA4xSpUqNCGf/Z->"; -text = "<|system|>\n" + text + " <|end|>\n<|assistant|>\n"; -text += "{\n 'glossary': {\n 'title': 'example glossary',\n 'GlossDiv': {\n 'title': 'S',\n 'GlossList': {\n 'GlossEntry': {\n 'ID': 'SGML',\n 'SortAs': 'SGML',\n 'GlossTerm': 'Standard Generalized Markup Language',\n 'Acronym': 'SGML',\n 'Abbrev': 'ISO 8879:1986',\n 'GlossDef': {\n 'para': 'A meta-markup language, used to create markup languages such as DocBook.',\n 'GlossSeeAlso': ['GML', 'XML']\n },\n 'GlossSee': 'markup'\n }\n }\n }\n }\n}"; -// text += " <|end|>\n" -// text += "<|user|>\n" -// text += "A language model is a probabilistic model of a natural language.[1]\nIn 1980, the first significant statistical language model was proposed, and during the decade IBM performed Shannon-style experiments, in which potential sources for language modeling improvement were identified by observing and analyzing the performance of human subjects in predicting or correcting text.[2] Language models are useful for a variety of tasks, including speech recognition[3] (helping prevent predictions of low-probability (e.g. nonsense) sequences), machine translation,[4] natural language generation (generating more human-like text), optical character recognition, handwriting recognition,[5] grammar induction,[6] and information retrieval.[7][8] Large language models, currently their most advanced form, are a combination of larger datasets (frequently using words scraped from the public internet), feedforward neural networks, and transformers. They have superseded recurrent neural network-based models, which had previously superseded the pure statistical models, such as word n-gram language model."; -// text += " <|end|>\n <|endoftext|>" - -export let mockTokens = textToNodeAttrs(text.match(/([\S]+|[\s]+)/g) || []); \ No newline at end of file + ]; \ No newline at end of file diff --git a/client/graphpaper-inline/src/stitch.ts b/client/graphpaper-inline/src/stitch.ts index 787db62ac..7cca1e488 100644 --- a/client/graphpaper-inline/src/stitch.ts +++ b/client/graphpaper-inline/src/stitch.ts @@ -1,5 +1,19 @@ import {writable} from 'svelte/store'; +export interface BaseToken { + token: number, + prob: number, + text: string, +} + +export interface GenToken extends BaseToken { + latency_ms: number, + is_generated: boolean, + is_force_forwarded: boolean, + is_input: boolean, + top_k: Array, +} + export interface NodeAttr { class_name: string } @@ -7,7 +21,9 @@ export interface NodeAttr { export interface TextOutput extends NodeAttr { class_name: 'TextOutput', value: string, + is_input: boolean, is_generated: boolean, + is_force_forwarded: boolean, token_count: number, prob: number, } @@ -40,14 +56,16 @@ export interface ResetDisplayMessage extends GuidanceMessage { class_name: 'ResetDisplayMessage' } -export interface TokenBatchMessage extends GuidanceMessage { - class_name: 'TokenBatchMessage', - tokens: Array +export interface ExecutionCompletedMessage extends GuidanceMessage { + class_name: 'ExecutionCompletedMessage', + last_trace_id?: number, } -export interface JupyterCellExecutionCompletedMessage extends GuidanceMessage { - class_name: 'JupyterCellExecutionCompletedMessage', - last_trace_id?: number, +export interface ExecutionCompletedOutputMessage extends GuidanceMessage { + class_name: 'ExecutionCompletedOutputMessage', + trace_id: number, + text: string, + tokens: Array, } export interface ClientReadyMessage extends GuidanceMessage { @@ -57,7 +75,8 @@ export interface ClientReadyMessage extends GuidanceMessage { export interface MetricMessage extends GuidanceMessage { class_name: 'MetricMessage', name: string, - value: number | string + value: number | string | Array | Array, + scalar: boolean, } export interface StitchMessage { @@ -85,6 +104,26 @@ export function isTextOutput(o: NodeAttr | undefined | null): o is TextOutput { return o.class_name === "TextOutput"; } +export function isResetDisplayMessage(o: NodeAttr | undefined | null): o is ResetDisplayMessage { + if (o === undefined || o === null) return false; + return o.class_name === "ResetDisplayMessage"; +} + +export function isMetricMessage(o: NodeAttr | undefined | null): o is MetricMessage { + if (o === undefined || o === null) return false; + return o.class_name === "MetricMessage"; +} + +export function isExecutionCompletedMessage(o: NodeAttr | undefined | null): o is ExecutionCompletedMessage { + if (o === undefined || o === null) return false; + return o.class_name === "ExecutionCompletedMessage"; +} + +export function isExecutionCompletedOutputMessage(o: NodeAttr | undefined | null): o is ExecutionCompletedOutputMessage { + if (o === undefined || o === null) return false; + return o.class_name === "ExecutionCompletedOutputMessage"; +} + export const kernelmsg = writable(undefined); export const clientmsg = writable(undefined); diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 0f7a8d343..ac5708f08 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -13,8 +13,8 @@ from ..trace import NodeAttr, StatelessGuidanceInput, StatefulGuidanceInput, LiteralInput, EmbeddedInput, \ RoleOpenerInput, RoleCloserInput, TextOutput, CaptureOutput, TraceHandler from ..visual import TraceMessage, AutoRenderer, trace_node_to_str, trace_node_to_html, GuidanceMessage, Renderer -from ..visual._message import JupyterCellExecutionCompletedMessage, JupyterCellExecutionCompletedOutputMessage, \ - MetricMessage, TokenBatchMessage +from ..visual._message import ExecutionCompletedMessage, ExecutionCompletedOutputMessage, \ + MetricMessage try: from IPython.display import clear_output, display, HTML @@ -100,9 +100,6 @@ def emit_messages(self): self._renderer.update(MetricMessage(name='avg latency', value=random.uniform(10, 200))) self._renderer.update(MetricMessage(name='consumed', value=random.uniform(0, 100))) self._renderer.update(MetricMessage(name='token reduction', value=random.uniform(0, 100))) - self._renderer.update(TokenBatchMessage(tokens=[ - GenToken(latency_ms=100, token=0, prob=0.5, text="mock", top_k=[]) - ])) class Engine: @@ -132,15 +129,15 @@ def _msg_recv(self, message: GuidanceMessage) -> None: # NOTE(nopdive): This is likely running on a secondary thread. logger.debug(f"ENGINE:{message}") - if isinstance(message, JupyterCellExecutionCompletedMessage): - logger.debug(f"ENGINE:cell executed") - self.post_exec_generator.emit_messages() - self.renderer.update(message) + # if isinstance(message, ExecutionCompletedMessage): + # logger.debug(f"ENGINE:cell executed") + # self.post_exec_generator.emit_messages() + # self.renderer.update(message) # model = self.model_dict.get(message.trace_id) # print(f"ENGINE:{message}", type(message)) - if isinstance(message, JupyterCellExecutionCompletedMessage): + if isinstance(message, ExecutionCompletedMessage): # print("last_state") last_model: "Model" = self.model_dict[message.last_trace_id] paths = [] @@ -253,12 +250,14 @@ def _msg_recv(self, message: GuidanceMessage) -> None: if not failed: final_text = "".join([gen_token.text for gen_token in processed_gen_tokens]) logger.debug(f"ENGINE:final_text:{final_text}") - - self.renderer.update(JupyterCellExecutionCompletedOutputMessage( + self.renderer.update(ExecutionCompletedOutputMessage( trace_id=message.last_trace_id, text=self.tokenizer.decode(tokens).decode("utf-8"), tokens=processed_gen_tokens, )) + self.renderer.update(ExecutionCompletedMessage( + last_trace_id=message.last_trace_id, + )) def get_chat_template(self): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? return self.tokenizer.chat_template() # Instantiate the class before returning to client for now diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index 07d265d69..c12db0b38 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,8 +9,8 @@ diff --git a/guidance/trace/_trace.py b/guidance/trace/_trace.py index 473afb62c..ac9aa31fb 100644 --- a/guidance/trace/_trace.py +++ b/guidance/trace/_trace.py @@ -1,4 +1,5 @@ # TODO(nopdive): Deal with weak referencing for GC. Take care of cyclical dependencies from parent & children fields. +# TODO(nopdive): Consider integrating token operatins into trace nodes. # TODO(nopdive): Benchmark (expected heap fragmentation issue). Likely need memory pooling (via rust/ctypes/Cython). # TODO(nopdive): Integrate images when PR for multimodal is in. # NOTE(nopdive): Should we be explicit on capture variables? Right now they are within guidance grammars. diff --git a/guidance/visual/_message.py b/guidance/visual/_message.py index d6b1753c9..f75d223f4 100644 --- a/guidance/visual/_message.py +++ b/guidance/visual/_message.py @@ -22,19 +22,15 @@ class TraceMessage(GuidanceMessage): class MetricMessage(GuidanceMessage): name: str - value: Union[float, str] + value: Union[float, str, list[float], list[str]] + scalar: bool = True -# TODO(nopdive): Replace with implementation. -class TokenBatchMessage(GuidanceMessage): - tokens: list[GenToken] - - -class JupyterCellExecutionCompletedMessage(GuidanceMessage): +class ExecutionCompletedMessage(GuidanceMessage): last_trace_id: Optional[int] -class JupyterCellExecutionCompletedOutputMessage(GuidanceMessage): +class ExecutionCompletedOutputMessage(GuidanceMessage): trace_id: int text: str tokens: list[GenToken] = [] @@ -50,8 +46,8 @@ class ClientReadyMessage(GuidanceMessage): model_registry: Dict[str, type(GuidanceMessage)] = { 'TraceMessage': TraceMessage, - 'JupyterCellExecutionCompleted': JupyterCellExecutionCompletedMessage, - 'JupyterCellExecutionCompletedOutputMessage': JupyterCellExecutionCompletedOutputMessage, + 'ExecutionCompleted': ExecutionCompletedMessage, + 'ExecutionCompletedOutputMessage': ExecutionCompletedOutputMessage, 'ResetDisplayMessage': ResetDisplayMessage, 'ClientReadyMessage': ClientReadyMessage, 'MetricMessage': MetricMessage, diff --git a/guidance/visual/_renderer.py b/guidance/visual/_renderer.py index e8851a758..ca5cfe72c 100644 --- a/guidance/visual/_renderer.py +++ b/guidance/visual/_renderer.py @@ -3,7 +3,7 @@ from pydantic import BaseModel from asyncio import Queue -from ._message import JupyterCellExecutionCompletedMessage, JupyterCellExecutionCompletedOutputMessage, \ +from ._message import ExecutionCompletedMessage, ExecutionCompletedOutputMessage, \ deserialize_message, serialize_message, MetricMessage from ..trace import TraceHandler from ..visual import GuidanceMessage, TraceMessage, ResetDisplayMessage, ClientReadyMessage @@ -70,9 +70,11 @@ def __init__(self, trace_handler: TraceHandler): def update(self, message: GuidanceMessage) -> RenderUpdate: if isinstance(message, MetricMessage) and not self._completed: return RenderUpdate(messages=[message]) - elif isinstance(message, JupyterCellExecutionCompletedOutputMessage) and not self._completed: + elif isinstance(message, ExecutionCompletedOutputMessage) and not self._completed: + logger.debug("RENDER:execution completed out") return RenderUpdate(messages=[message]) - elif isinstance(message, JupyterCellExecutionCompletedMessage): + elif isinstance(message, ExecutionCompletedMessage): + logger.debug("RENDER:execution completed") self._completed = True return RenderUpdate() elif not isinstance(message, TraceMessage): @@ -227,15 +229,16 @@ def _handle_jupyter_cell_completion(self): def _cell_completion_cb(self): try: - message = JupyterCellExecutionCompletedMessage( + message = ExecutionCompletedMessage( last_trace_id=self._last_trace_id ) logger.debug(f"CELL:executed:{message}") # Message Python observers self.notify(message) + # Message client observers - self._loop.call_soon_threadsafe(self._send_queue.put_nowait, message) + # self._loop.call_soon_threadsafe(self._send_queue.put_nowait, message) finally: get_ipython().events.unregister('post_execute', self._cell_completion_cb) self._is_alive_cell_cb = False @@ -266,12 +269,12 @@ async def _handle_send_messages(self): # Wait until ready # TODO(nopdive): This blocks until cell completion. Not what we want. - # if self._wait_for_client: - # await self._client_ready.wait() + if self._wait_for_client: + await self._client_ready.wait() # What if we only used 1% of our brain? - import asyncio - await asyncio.sleep(0.5) + # import asyncio + # await asyncio.sleep(0.5) logger.debug("SEND:ready") while True: @@ -300,9 +303,9 @@ def update(self, message: GuidanceMessage) -> None: # Handle Jupyter cell completion self._handle_jupyter_cell_completion() - if isinstance(message, TraceMessage) or isinstance(message, JupyterCellExecutionCompletedOutputMessage): + if isinstance(message, TraceMessage) or isinstance(message, ExecutionCompletedOutputMessage): complete_msg = None - if isinstance(message, JupyterCellExecutionCompletedOutputMessage): + if isinstance(message, ExecutionCompletedOutputMessage): complete_msg = message trace_node = self._trace_handler[message.trace_id] @@ -310,7 +313,7 @@ def update(self, message: GuidanceMessage) -> None: if trace_node is not None: clear_output(wait=True) display(HTML(trace_node_to_html(trace_node, prettify_roles=False, complete_msg=complete_msg))) - elif isinstance(message, JupyterCellExecutionCompletedMessage): + elif isinstance(message, ExecutionCompletedMessage): logger.debug("RENDERER:cell executed") else: pass diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index 3e6b5ca5d..e4b934fcb 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -2,7 +2,7 @@ import json from typing import Optional, Dict -from guidance.visual._message import JupyterCellExecutionCompletedOutputMessage +from guidance.visual._message import ExecutionCompletedOutputMessage from ..trace import ( TextOutput, @@ -18,7 +18,7 @@ span_end = "" -def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: JupyterCellExecutionCompletedOutputMessage=None) -> str: +def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: ExecutionCompletedOutputMessage=None) -> str: """Represents trace path as html string. Args: From ddd1ba4b5f65d296317da0b09f25e7ea52e5305f Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Fri, 11 Oct 2024 00:52:07 -0700 Subject: [PATCH 064/133] Text strikethrough on tooltip. Yes, the future is now. Doesn't look as nice as container wide strike. --- client/graphpaper-inline/src/App.svelte | 2 ++ client/graphpaper-inline/src/TokenGrid.svelte | 7 ++++--- client/graphpaper-inline/src/stitch.ts | 1 + guidance/resources/graphpaper-inline.html | 4 ++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 9487492c5..dc300f834 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -63,6 +63,8 @@ completedExecution = true; } else if (isExecutionCompletedOutputMessage(msg)) { tokenDetails = msg.tokens; + console.log(textComponents); + console.log(msg.tokens); } textComponents = textComponents; } diff --git a/client/graphpaper-inline/src/TokenGrid.svelte b/client/graphpaper-inline/src/TokenGrid.svelte index 68faa2456..05dba47fc 100644 --- a/client/graphpaper-inline/src/TokenGrid.svelte +++ b/client/graphpaper-inline/src/TokenGrid.svelte @@ -247,8 +247,9 @@ {#each tooltipToken.extra.top_k as candidate} - {@html DOMPurify.sanitize(escapeWhitespaceCharacters(candidate.text))} - {candidate.prob.toFixed(3)} + + {@html DOMPurify.sanitize(escapeWhitespaceCharacters(candidate.text))} + {candidate.prob.toFixed(3)} {/each} @@ -259,8 +260,8 @@
+
-
{#each tokens as token, i} diff --git a/client/graphpaper-inline/src/stitch.ts b/client/graphpaper-inline/src/stitch.ts index 7cca1e488..6c1c12471 100644 --- a/client/graphpaper-inline/src/stitch.ts +++ b/client/graphpaper-inline/src/stitch.ts @@ -4,6 +4,7 @@ export interface BaseToken { token: number, prob: number, text: string, + is_masked: boolean, } export interface GenToken extends BaseToken { diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index c12db0b38..f576300b3 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,8 +9,8 @@ From fa511895d60ca932edf84f5b3e509e4d7832eeef Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Sun, 13 Oct 2024 22:37:00 -0700 Subject: [PATCH 065/133] Add consumed tokens / token reduction / avg latency metrics --- guidance/_parser.py | 89 ++++----- guidance/_schema.py | 12 +- guidance/models/_model.py | 388 ++++++++++++++++++++++++++------------ 3 files changed, 318 insertions(+), 171 deletions(-) diff --git a/guidance/_parser.py b/guidance/_parser.py index c66b69f71..70f7bb2cb 100644 --- a/guidance/_parser.py +++ b/guidance/_parser.py @@ -44,9 +44,7 @@ def __init__( serialized_grammar = grammar self.tokenizer = tokenizer - self.ll_tokenizer = llguidance.LLTokenizer( - llguidance.TokenizerWrapper(tokenizer) - ) + self.ll_tokenizer = llguidance.LLTokenizer(llguidance.TokenizerWrapper(tokenizer)) self.ll_interpreter = llguidance.LLInterpreter( self.ll_tokenizer, serialized_grammar, @@ -72,9 +70,7 @@ def advance( def _process_prompt(self, prompt: bytes, ensure_bos_token: bool) -> Tuple[list[int], int]: _prompt_tokens = self.tokenizer.encode(prompt) - prompt_tokens = self.ll_interpreter.process_prompt( - _prompt_tokens - ) + prompt_tokens = self.ll_interpreter.process_prompt(_prompt_tokens) if ( ensure_bos_token and self.tokenizer.bos_token is not None @@ -86,12 +82,13 @@ def _process_prompt(self, prompt: bytes, ensure_bos_token: bool) -> Tuple[list[i prompt_tokens = self.tokenizer.recode(prompt_tokens) return prompt_tokens, max(0, len(_prompt_tokens) - len(prompt_tokens)) - def _parse( self, prompt: bytes, ensure_bos_token: bool, - ) -> Generator[Tuple[Optional[GenData], EngineCallResponse], Optional[EngineOutput], EngineCallResponse]: + ) -> Generator[ + Tuple[Optional[GenData], EngineCallResponse], Optional[EngineOutput], EngineCallResponse + ]: tokens, backtrack = self._process_prompt(prompt=prompt, ensure_bos_token=ensure_bos_token) backtrack = 0 @@ -111,7 +108,7 @@ def _parse( # if engine_output.issued_token.token == ff_tokens[0]: # # this is generated # response.generated_bytes = self.tokenizer.decode([ff_tokens[0]]) - + # if len(ff_tokens[1:]): # response.force_forwarded_bytes = self.tokenizer.decode(ff_tokens[1:]) @@ -129,33 +126,41 @@ def _parse( response.generated_tokens.append(engine_output.issued_token) else: # check if the first byte contains the generated token - generated = self.tokenizer.decode([engine_output.issued_token.token]).decode("utf-8") + generated = self.tokenizer.decode([engine_output.issued_token.token]).decode( + "utf-8" + ) force_forwarded = self.tokenizer.decode([_tokens[0]]).decode("utf-8") if force_forwarded.startswith(generated): # this is marked as generated # Example: engine generates token "pl" and parser decides to backtrack and generate a new token "plate" response.generated_bytes = self.tokenizer.decode([_tokens[0]]) - response.generated_tokens.append(GenToken( - token=_tokens[0], - prob=1.0, - text=response.generated_bytes.decode("utf-8"), - latency_ms=engine_output.issued_token.latency_ms, - is_generated=True, - )) + response.generated_tokens.append( + GenToken( + token=_tokens[0], + prob=1.0, + text=response.generated_bytes.decode("utf-8"), + latency_ms=engine_output.issued_token.latency_ms, + is_generated=True, + ) + ) else: ff_token_start_idx = 0 - + if len(_tokens[ff_token_start_idx:]): - response.force_forwarded_bytes = self.tokenizer.decode(_tokens[ff_token_start_idx:]) + response.force_forwarded_bytes = self.tokenizer.decode( + _tokens[ff_token_start_idx:] + ) for _token in _tokens[ff_token_start_idx:]: - response.force_forwarded_tokens.append(GenToken( - token=_token, - prob=1.0, - text=self.tokenizer.decode([_token]).decode("utf-8"), - latency_ms=0, - is_force_forwarded=True, - )) + response.force_forwarded_tokens.append( + GenToken( + token=_token, + prob=1.0, + text=self.tokenizer.decode([_token]).decode("utf-8"), + latency_ms=0, + is_force_forwarded=True, + ) + ) if r.stop: break @@ -174,18 +179,24 @@ def _parse( if not mask[engine_output.issued_token.token]: # Note: we could punt this probem to ll_interpreter.post_process, # but it's a bit clearer to handle it here - raise InvalidTokenException(engine_output.issued_token.token, gen_data.valid_next_tokens, tokens) + raise InvalidTokenException( + engine_output.issued_token.token, gen_data.valid_next_tokens, tokens + ) else: gen_data = None engine_output = yield (gen_data, response) if engine_output is not None: - raise TokenParserException(f"Expected None, got token {engine_output.issued_token.token}") + raise TokenParserException( + f"Expected None, got token {engine_output.issued_token.token}" + ) - backtrack, ff_tokens = self.ll_interpreter.post_process(engine_output.issued_token.token) + backtrack, ff_tokens = self.ll_interpreter.post_process( + engine_output.issued_token.token + ) if backtrack: tokens = tokens[:-backtrack] tokens = tokens + ff_tokens - backtrack = 0 + # backtrack = 0 stop_reason = self.ll_interpreter.stop_reason() if stop_reason not in {"NoExtension", "EndOfSentence"}: @@ -230,9 +241,7 @@ def valid_next_bytes(self) -> set[bytes]: if self.gen_data is None: return set() return { - bytes([t]) - for t in self.gen_data.valid_next_tokens - if t != self.tokenizer.eos_token_id + bytes([t]) for t in self.gen_data.valid_next_tokens if t != self.tokenizer.eos_token_id } def next_byte_mask(self) -> NDArray[np.uint8]: @@ -323,23 +332,15 @@ def _update_capture(self, response: EngineCallResponse): # convert to a string if possible # TODO: will need to not just always do this once we support images etc. try: - inner_v = ( - inner_v.decode("utf8") - if isinstance(inner_v, bytes) - else inner_v - ) + inner_v = inner_v.decode("utf8") if isinstance(inner_v, bytes) else inner_v except UnicodeDecodeError: pass - if k not in self._variables or not isinstance( - self._variables[k], list - ): + if k not in self._variables or not isinstance(self._variables[k], list): self._variables[k] = [] self._variables_log_probs[k] = [] self._variables[k].append(inner_v) - self._variables_log_probs[k].append( - response.capture_group_log_probs[k][i] - ) + self._variables_log_probs[k].append(response.capture_group_log_probs[k][i]) # ...or standard assignment mode else: diff --git a/guidance/_schema.py b/guidance/_schema.py index 70dd6a9b8..c59aedfbb 100644 --- a/guidance/_schema.py +++ b/guidance/_schema.py @@ -8,6 +8,7 @@ class GuidanceEngineMetrics(BaseModel): engine_input_tokens: NonNegativeInt = 0 engine_output_tokens: NonNegativeInt = 0 + engine_backtrack_tokens: NonNegativeInt = 0 class EngineCallResponse(BaseModel): @@ -23,7 +24,10 @@ class EngineCallResponse(BaseModel): generated_bytes: bytes = b"" # bytes generated by the engine generated_tokens: list["GenToken"] = [] # tokens associated with the generated bytes force_forwarded_bytes: bytes = b"" # bytes that were forced forwards by the parser - force_forwarded_tokens: list["GenToken"] = [] # tokens associated with the forced forwarded bytes + force_forwarded_tokens: list["GenToken"] = ( + [] + ) # tokens associated with the forced forwarded bytes + class BaseGenToken(BaseModel): token: int @@ -32,6 +36,7 @@ class BaseGenToken(BaseModel): text: str = "" is_masked: bool = False + class GenToken(BaseGenToken): latency_ms: float is_generated: bool = False @@ -60,6 +65,7 @@ class VisBytesChunk(BaseModel): backtrack: NonNegativeInt = 0 engine_outputs: list[EngineOutput] = [] + class GenData(BaseModel): tokens: list[int] mask: bytes @@ -125,9 +131,7 @@ def to_engine_call_response(self) -> EngineCallResponse: cname = j.name data = bytes.fromhex(j.hex) if j.list_append: - if cname not in capture_groups or not isinstance( - capture_groups[cname], list - ): + if cname not in capture_groups or not isinstance(capture_groups[cname], list): capture_groups[cname] = [] capture_group_log_probs[cname] = [] capture_groups[cname].append(data) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index e22f294f2..0918eed52 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -13,11 +13,32 @@ import numpy as np -from ..trace import NodeAttr, StatelessGuidanceInput, StatefulGuidanceInput, LiteralInput, EmbeddedInput, \ - RoleOpenerInput, RoleCloserInput, TextOutput, CaptureOutput, TraceHandler -from ..visual import TraceMessage, AutoRenderer, trace_node_to_str, trace_node_to_html, GuidanceMessage, Renderer -from ..visual._message import JupyterCellExecutionCompletedMessage, JupyterCellExecutionCompletedOutputMessage, \ - MetricMessage, TokenBatchMessage +from ..trace import ( + NodeAttr, + StatelessGuidanceInput, + StatefulGuidanceInput, + LiteralInput, + EmbeddedInput, + RoleOpenerInput, + RoleCloserInput, + TextOutput, + CaptureOutput, + TraceHandler, +) +from ..visual import ( + TraceMessage, + AutoRenderer, + trace_node_to_str, + trace_node_to_html, + GuidanceMessage, + Renderer, +) +from ..visual._message import ( + JupyterCellExecutionCompletedMessage, + JupyterCellExecutionCompletedOutputMessage, + MetricMessage, + TokenBatchMessage, +) try: from IPython.display import clear_output, display, HTML @@ -28,7 +49,14 @@ logger = logging.getLogger(__name__) -from .._schema import BaseGenToken, EngineCallResponse, EngineOutput, GenToken, GuidanceEngineMetrics, VisBytesChunk +from .._schema import ( + BaseGenToken, + EngineCallResponse, + EngineOutput, + GenToken, + GuidanceEngineMetrics, + VisBytesChunk, +) from .._utils import softmax, CaptureEvents from .._parser import TokenParser from .._grammar import ( @@ -58,7 +86,7 @@ # TODO(nopdive): Remove on implementation. class MockMetricsGenerator: - def __init__(self, renderer: Renderer, monitor: "Monitor", sleep_sec = 0.5): + def __init__(self, renderer: Renderer, monitor: "Monitor", sleep_sec=0.5): from ..visual._async import run_async_task self._renderer = renderer @@ -102,41 +130,56 @@ async def _emit(self): time_end = time.time() time_elapsed = time_end - time_start - self._renderer.update( - MetricMessage(name='wall time', value=time_elapsed) - ) + self._renderer.update(MetricMessage(name="wall time", value=time_elapsed)) self._renderer.update( - MetricMessage(name='cpu', value=self._monitor.get_metric(MonitoringMetric.CPU_USAGE)) + MetricMessage( + name="cpu", value=self._monitor.get_metric(MonitoringMetric.CPU_USAGE) + ) ) self._renderer.update( - MetricMessage(name='ram', value=self._monitor.get_metric(MonitoringMetric.MEM_USAGE)) + MetricMessage( + name="ram", value=self._monitor.get_metric(MonitoringMetric.MEM_USAGE) + ) ) - self._renderer.update( - MetricMessage(name='gpu', value=gpu_percent) - ) + self._renderer.update(MetricMessage(name="gpu", value=gpu_percent)) - self._renderer.update( - MetricMessage(name='vram', value=gpu_used_vram) - ) + self._renderer.update(MetricMessage(name="vram", value=gpu_used_vram)) # # TODO(nopdive): Remove on implementation. class MockPostExecGenerator: - def __init__(self, renderer: Renderer): + def __init__(self, renderer: Renderer, monitor: "Monitor"): self._renderer = renderer + self._monitor = monitor - def emit_messages(self): + def emit_messages(self, lm: "Model"): import random - self._renderer.update(MetricMessage(name='avg latency', value=random.uniform(10, 200))) - self._renderer.update(MetricMessage(name='consumed', value=random.uniform(0, 100))) - self._renderer.update(MetricMessage(name='token reduction', value=random.uniform(0, 100))) - self._renderer.update(TokenBatchMessage(tokens=[ - GenToken(latency_ms=100, token=0, prob=0.5, text="mock", top_k=[]) - ])) + # self._renderer.update(MetricMessage(name="avg latency", value=random.uniform(10, 200))) + # self._renderer.update(MetricMessage(name="consumed", value=random.uniform(0, 100))) + # self._renderer.update(MetricMessage(name="token reduction", value=random.uniform(0, 100))) + # self._renderer.update( + # TokenBatchMessage( + # tokens=[GenToken(latency_ms=100, token=0, prob=0.5, text="mock", top_k=[])] + # ) + # ) + + token_reduction = self._monitor.get_metric(MonitoringMetric.TOKEN_REDUCTION, lm) + self._renderer.update( + MetricMessage( + name="token reduction", + value=token_reduction * 100, + ) + ) + + output_tokens = self._monitor.get_metric(MonitoringMetric.OUTPUT_TOKENS, lm) + self._renderer.update(MetricMessage(name="consumed", value=output_tokens)) + + avg_latency = self._monitor.get_metric(MonitoringMetric.AVG_LATENCY, lm) + self._renderer.update(MetricMessage(name="avg latency", value=avg_latency)) class Engine: @@ -154,7 +197,9 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False, **kwargs): self.metrics = GuidanceEngineMetrics() self.trace_handler = TraceHandler() - self.renderer = AutoRenderer(self.trace_handler, use_legacy_renderer=kwargs.get("use_legacy_renderer", False)) + self.renderer = AutoRenderer( + self.trace_handler, use_legacy_renderer=kwargs.get("use_legacy_renderer", False) + ) self.renderer.subscribe(self._msg_recv) self.model_dict: dict[int, Model] = {} @@ -163,23 +208,20 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False, **kwargs): # TODO(nopdive): Remove on implementation. self.metrics_generator = MockMetricsGenerator(self.renderer, self.monitor) - self.post_exec_generator = MockPostExecGenerator(self.renderer) + self.post_exec_generator = MockPostExecGenerator(self.renderer, self.monitor) def _msg_recv(self, message: GuidanceMessage) -> None: # NOTE(nopdive): This is likely running on a secondary thread. logger.debug(f"ENGINE:{message}") - if isinstance(message, JupyterCellExecutionCompletedMessage): - logger.debug(f"ENGINE:cell executed") - self.post_exec_generator.emit_messages() - self.renderer.update(message) - - # model = self.model_dict.get(message.trace_id) - # print(f"ENGINE:{message}", type(message)) - if isinstance(message, JupyterCellExecutionCompletedMessage): # print("last_state") last_model: "Model" = self.model_dict[message.last_trace_id] + + # send stats to the renderer + self.post_exec_generator.emit_messages(last_model) + self.renderer.update(message) + paths = [] model = last_model while model is not None: @@ -191,12 +233,20 @@ def _msg_recv(self, message: GuidanceMessage) -> None: paths.reverse() - vis_chunks: list[VisBytesChunk] = [path.vis_chunk for path in paths if path.vis_chunk is not None] + vis_chunks: list[VisBytesChunk] = [ + path.vis_chunk for path in paths if path.vis_chunk is not None + ] gen_tokens_lats = [] gen_tokens_indices = [] for vis_chunk in vis_chunks: for engine_output in vis_chunk.engine_outputs: - gen_tokens_lats.append((engine_output.issued_token.token, engine_output.issued_token.latency_ms, engine_output.masked_top_k)) + gen_tokens_lats.append( + ( + engine_output.issued_token.token, + engine_output.issued_token.latency_ms, + engine_output.masked_top_k, + ) + ) gen_tokens_indices.append(len(gen_tokens_lats) - 1) gen_tokens_lats_idx = 0 @@ -228,22 +278,22 @@ def _msg_recv(self, message: GuidanceMessage) -> None: continue end_idx = start_idx - _chunk = "".join(tokens_texts[start_idx:end_idx+1]) + _chunk = "".join(tokens_texts[start_idx : end_idx + 1]) while vis_text not in _chunk and end_idx < len(tokens_texts): # expand the chunk end_idx += 1 - _chunk = "".join(tokens_texts[start_idx:end_idx+1]) + _chunk = "".join(tokens_texts[start_idx : end_idx + 1]) if vis_text not in _chunk and end_idx >= len(tokens_texts): failed = True break - + if vis_text == _chunk: # perfect match pass else: start_pos = _chunk.index(vis_text) - remainder = _chunk[start_pos + len(vis_text):] + remainder = _chunk[start_pos + len(vis_text) :] if remainder: # we have a current chunk that is larger than the vis_text @@ -251,8 +301,8 @@ def _msg_recv(self, message: GuidanceMessage) -> None: # we should not issue that token for now end_idx -= 1 - real_chunk_tokens = tokens[start_idx:end_idx+1] - real_chunk_probs = probs[start_idx:end_idx+1] + real_chunk_tokens = tokens[start_idx : end_idx + 1] + real_chunk_probs = probs[start_idx : end_idx + 1] is_input = len(vis_chunk.input_tokens) > 0 is_force_forwarded = len(vis_chunk.force_forwarded_tokens) > 0 @@ -266,14 +316,14 @@ def _msg_recv(self, message: GuidanceMessage) -> None: break _gen_token = GenToken( - token=token, - prob=prob, - text=self.tokenizer.decode([token]).decode("utf-8"), - latency_ms=0, - is_input=is_input, - is_generated=False, - is_force_forwarded=False - ) + token=token, + prob=prob, + text=self.tokenizer.decode([token]).decode("utf-8"), + latency_ms=0, + is_input=is_input, + is_generated=False, + is_force_forwarded=False, + ) _gen_token.top_k = top_k_prob _gen_tokens.append(_gen_token) @@ -309,9 +359,18 @@ def _msg_recv(self, message: GuidanceMessage) -> None: if not found_perfect_match: # only search within this chunk max_idx = gen_tokens_indices[vis_chunk_idx] - prev_max_idx = -1 if vis_chunk_idx == 0 else gen_tokens_indices[vis_chunk_idx - 1] - 1 + prev_max_idx = ( + -1 + if vis_chunk_idx == 0 + else gen_tokens_indices[vis_chunk_idx - 1] - 1 + ) for idx in range(max_idx, prev_max_idx, -1): - if self.tokenizer.decode([gen_tokens_lats[idx][0]]).decode("utf-8") in _gen_token.text: + if ( + self.tokenizer.decode([gen_tokens_lats[idx][0]]).decode( + "utf-8" + ) + in _gen_token.text + ): _gen_token.latency_ms = gen_tokens_lats[idx][1] _masked_top_k = gen_tokens_lats[idx][2] if _masked_top_k is None: @@ -321,7 +380,10 @@ def _msg_recv(self, message: GuidanceMessage) -> None: else: _masked_tokens = [token.token for token in _masked_top_k] for _token in _gen_token.top_k: - if _token.token not in _masked_tokens and _token.token != _gen_token.token: + if ( + _token.token not in _masked_tokens + and _token.token != _gen_token.token + ): _token.is_masked = True else: _token.is_masked = False @@ -343,15 +405,21 @@ def _msg_recv(self, message: GuidanceMessage) -> None: final_text = "".join([gen_token.text for gen_token in processed_gen_tokens]) logger.debug(f"ENGINE:final_text:{final_text}") - self.renderer.update(JupyterCellExecutionCompletedOutputMessage( - trace_id=message.last_trace_id, - text=self.tokenizer.decode(tokens).decode("utf-8"), - tokens=processed_gen_tokens, - )) + self.renderer.update( + JupyterCellExecutionCompletedOutputMessage( + trace_id=message.last_trace_id, + text=self.tokenizer.decode(tokens).decode("utf-8"), + tokens=processed_gen_tokens, + ) + ) + + def get_chat_template( + self, + ): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? + return ( + self.tokenizer.chat_template() + ) # Instantiate the class before returning to client for now - def get_chat_template(self): # TODO [HN]: Add more logic here...should we instantiate class here? do we even need to? - return self.tokenizer.chat_template() # Instantiate the class before returning to client for now - def reset_metrics(self): self.metrics = GuidanceEngineMetrics() @@ -394,7 +462,7 @@ def start(self, prompt, grammar, ensure_bos_token=True) -> TokenParser: grammar=grammar, tokenizer=self.tokenizer, prompt=prompt, - ensure_bos_token=ensure_bos_token + ensure_bos_token=ensure_bos_token, ) def __call__(self, prompt, grammar, ensure_bos_token=True) -> Iterator[EngineCallResponse]: @@ -539,16 +607,20 @@ def get_top_k(_probs: np.ndarray, _k: int = 5) -> list[GenToken]: is_generated=False, ) - engine_list.append(EngineOutput( - issued_token=issued_token, - top_k=top_k, - masked_top_k=None if not masked_top_k else masked_top_k, - is_backtracked=False, - )) + engine_list.append( + EngineOutput( + issued_token=issued_token, + top_k=top_k, + masked_top_k=None if not masked_top_k else masked_top_k, + is_backtracked=False, + ) + ) return engine_list - def get_next_token(self, token_ids: list[int], mask: Optional[bytes], temperature: float) -> int: + def get_next_token( + self, token_ids: list[int], mask: Optional[bytes], temperature: float + ) -> int: """Base implementation for getting the next token from the model which calls get_logits and sample_with_temperature. Subclasses may override this method, e.g. if they use external APIs that do not support getting logits directly. """ @@ -558,17 +630,19 @@ def get_next_token(self, token_ids: list[int], mask: Optional[bytes], temperatur def get_logits(self, token_ids: list[int]) -> np.ndarray: raise NotImplementedError - + def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[BaseGenToken]]: raise NotImplementedError - def sample_with_temperature(self, logits: np.ndarray, mask: Optional[bytes], temperature: float) -> int: + def sample_with_temperature( + self, logits: np.ndarray, mask: Optional[bytes], temperature: float + ) -> int: if mask is not None: logits += np.frombuffer(mask, dtype=np.uint8) if temperature < 0.0001: return int(np.argmax(logits)) # Get probabilities from softmax - probabilities = softmax(logits/temperature) + probabilities = softmax(logits / temperature) # Sample an index based on the probabilities sampled_index = np.random.choice(len(logits), p=probabilities) return sampled_index @@ -582,6 +656,8 @@ def _report_failed_match(self, prompt): _id_counter = 0 # Counter for identifiers, this has to be outside the model to handle child classes properly. + + class Model: """The base guidance model object, which represents a model in a given state. @@ -593,7 +669,9 @@ class Model: .. automethod:: __add__ """ - global_active_blocks: list["ContextBlock"] = [] # track what context blocks are globally active + global_active_blocks: list["ContextBlock"] = ( + [] + ) # track what context blocks are globally active _grammar_only = 0 # a flag that tracks when we are forced to be executing only compiled grammars (like when we are inside a select) @@ -621,11 +699,15 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): # tokenizer = Tokenizer(tokenizer) self.engine = engine - self.chat_template = engine.get_chat_template() # TODO [HN]: Should this be a method or attr? + self.chat_template = ( + engine.get_chat_template() + ) # TODO [HN]: Should this be a method or attr? # NOTE(nopdive): `echo` seems to be better on the engine, when is there an opportunity to turn echo off midway? self.echo = echo self.token_count = 0 # tracks how many tokens our byte state represents - self.max_display_rate = 0.2 # this controls how frequently we are allowed to redraw the display (in seconds) + self.max_display_rate = ( + 0.2 # this controls how frequently we are allowed to redraw the display (in seconds) + ) self.opened_blocks = {} # what context blocks have been opened but not closed # self.compute_log_probs = compute_log_probs @@ -639,10 +721,14 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self._renderer = engine.renderer # renderer for display else: self._renderer = None # no renderer if echo is false - self._event_queue = None # TODO: these are for streaming results in code, but that needs implemented + self._event_queue = ( + None # TODO: these are for streaming results in code, but that needs implemented + ) self._event_parent = None self._last_display = 0 # used to track the last display call to enable throttling - self._last_event_stream = 0 # used to track the last event streaming call to enable throttling + self._last_event_stream = ( + 0 # used to track the last event streaming call to enable throttling + ) self._id = self.__class__.gen_id() # model id needed for tracking state self._parent_id = parent_id @@ -651,6 +737,7 @@ def __init__(self, engine, echo=True, parent_id=None, **kwargs): self.vis_chunk: VisBytesChunk = None self.engine.model_dict[self._id] = self + self.metrics = GuidanceEngineMetrics() @classmethod def gen_id(cls): @@ -682,8 +769,7 @@ def _html(self): """Generate HTML that displays the model object.""" return trace_node_to_html( - self._trace_handler.id_node_map[self._id], - hasattr(self, "indent_roles") + self._trace_handler.id_node_map[self._id], hasattr(self, "indent_roles") ) def _send_to_event_queue(self, value): @@ -710,7 +796,9 @@ def copy(self): new_lm.opened_blocks = self.opened_blocks.copy() # create a new clean event queue - new_lm._event_queue = None # we start with no event queue because nobody is listening to us yet + new_lm._event_queue = ( + None # we start with no event queue because nobody is listening to us yet + ) if self._event_queue is not None: # if the current lm has an event queue, we make it our parent @@ -726,6 +814,7 @@ def copy(self): self.engine.model_dict[new_lm._id] = new_lm new_lm.vis_chunk = None new_lm._parent = self + new_lm.metrics = self.metrics.model_copy(deep=True) return new_lm @@ -750,7 +839,6 @@ def _inplace_append(self, value, force_silent=False): # this is for programmatic streaming among other things self._send_to_event_queue(self) - def reset(self, clear_variables=True): """This resets the state of the model object. @@ -767,7 +855,6 @@ def reset(self, clear_variables=True): self._variables_log_probs = {} return self - def role_opener(self, role_name, **kwargs): # TODO [HN]: Temporary change while I instrument chat_template in transformers only. # Eventually have all models use chat_template. @@ -780,7 +867,6 @@ def role_opener(self, role_name, **kwargs): f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" ) - def role_closer(self, role_name, **kwargs): # TODO [HN]: Temporary change while I instrument chat_template in transformers only. # Eventually have all models use chat_template. @@ -793,7 +879,6 @@ def role_closer(self, role_name, **kwargs): f"You need to use a chat model in order the use role blocks like `with {role_name}():`! Perhaps you meant to use the {type(lm).__name__}Chat class?" ) - def _repr_html_(self): if ipython_is_imported: clear_output(wait=True) @@ -803,7 +888,9 @@ def _current_prompt(self): """The current prompt in bytes (which is the state without the context close tags).""" return trace_node_to_str(self._trace_handler.id_node_map[self._id]) - def _update_trace_node(self, identifier: int, parent_id: Optional[int], node_attr: Optional[NodeAttr]): + def _update_trace_node( + self, identifier: int, parent_id: Optional[int], node_attr: Optional[NodeAttr] + ): """Updates trace node that corresponds to this model.""" self._trace_handler.update_node(identifier, parent_id, node_attr) @@ -816,14 +903,12 @@ def _update_trace_node(self, identifier: int, parent_id: Optional[int], node_att ) ) - def __str__(self): """A string representation of the current model object (that includes context closers).""" # TODO(nopdive): Ensure context closers or no? return trace_node_to_str(self._trace_handler.id_node_map[self._id]) - def __add__(self, value): """Adding is the primary mechanism for extending model state. @@ -837,6 +922,9 @@ def __add__(self, value): # (we need to do this since Model objects are immutable) lm = self.copy() + # map model's metrics to engine + lm.engine.metrics = lm.metrics + # find blocks that are now active, but haven't been opened by lm yet enter_blocks = [] for context in Model.global_active_blocks: @@ -860,12 +948,16 @@ def __add__(self, value): # TODO(nopdive): Replace with trace traversal. v = format_pattern.sub("", lm._state[pos:]) lm._variables[context.name] = v - self._update_trace_node(lm._id, lm._parent_id, CaptureOutput(name=context.name, value=v)) + self._update_trace_node( + lm._id, lm._parent_id, CaptureOutput(name=context.name, value=v) + ) # add closer # TODO(nopdive): Consider removing context closer/opener on confirmation. closer_text = self.role_closer(context.name) - self._update_trace_node(lm._id, lm._parent_id, RoleCloserInput(name=context.name, text=closer_text)) + self._update_trace_node( + lm._id, lm._parent_id, RoleCloserInput(name=context.name, text=closer_text) + ) lm += context.closer lm = lm.copy() @@ -874,7 +966,11 @@ def __add__(self, value): # add opener opener_text = self.role_opener(context.name) closer_text = self.role_closer(context.name) - self._update_trace_node(lm._id, lm._parent_id, RoleOpenerInput(name=context.name, text=opener_text, closer_text=closer_text)) + self._update_trace_node( + lm._id, + lm._parent_id, + RoleOpenerInput(name=context.name, text=opener_text, closer_text=closer_text), + ) lm += context.opener lm = lm.copy() @@ -925,11 +1021,16 @@ def __add__(self, value): is_generated=False, is_force_forwarded=False, is_input=True, - ) for _token in _tokens - ] + ) + for _token in _tokens + ], ) - self._update_trace_node(out._id, out._parent_id, TextOutput(value=value, is_input=True, tokens=out.vis_chunk.input_tokens)) + self._update_trace_node( + out._id, + out._parent_id, + TextOutput(value=value, is_input=True, tokens=out.vis_chunk.input_tokens), + ) # if we have embedded objects we have to convert the string to a grammar tree else: @@ -976,6 +1077,9 @@ def __add__(self, value): f"A guidance function did not return a model object! Did you try to add a function to a model without calling the function? For example `model + guidance_function()` is correct, while `model + guidance_function` will cause this error." ) + # copy model metrics back to engine + out.metrics = self.engine.metrics.model_copy(deep=True) + return out # def endswith(self, s): @@ -1002,9 +1106,7 @@ def __getitem__(self, key): else: for context in list(reversed(self.opened_blocks)): if context.name == key: - return format_pattern.sub( - "", self._state[self.opened_blocks[context][0] :] - ) + return format_pattern.sub("", self._state[self.opened_blocks[context][0] :]) raise KeyError(f"Model does not contain the variable '{key}'") @@ -1183,6 +1285,9 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): continue delayed_bytes = b"" + if chunk.backtrack: + lm.engine.metrics.engine_backtrack_tokens += chunk.backtrack + # while chunk.backtrack > 0: # parent = lm._parent # while parent is not None: @@ -1219,7 +1324,7 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): prob=0.0, tokens=chunk.generated_tokens, ) - + if chunk.force_forwarded_bytes: lm += TextOutput( value=chunk.force_forwarded_bytes.decode("utf8"), @@ -1228,7 +1333,7 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): prob=0.0, tokens=chunk.force_forwarded_tokens, ) - + new_lm_created = True else: new_lm_created = False @@ -1274,7 +1379,9 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): if k not in lm or not isinstance(lm._variables[k], list): lm._variables[k] = [] lm += CaptureOutput(name=k) - if k not in lm._variables_log_probs or not isinstance(lm._variables_log_probs[k], list): + if k not in lm._variables_log_probs or not isinstance( + lm._variables_log_probs[k], list + ): lm._variables_log_probs[k] = [] lm._variables[k].append(inner_v) @@ -1396,10 +1503,7 @@ def get_role_start(self, role_name, **kwargs): This kwargs are added to the role start as arguments. """ return ( - "<|im_start|>" - + role_name - + "".join([f' {k}="{v}"' for k, v in kwargs.items()]) - + "\n" + "<|im_start|>" + role_name + "".join([f' {k}="{v}"' for k, v in kwargs.items()]) + "\n" ) def get_role_end(self, role_name=None): @@ -1416,6 +1520,7 @@ def get_role_end(self, role_name=None): """ return "<|im_end|>" + class Instruct(Model): """The base class for all instruction-tuned models.""" @@ -1445,6 +1550,7 @@ def __init__(self, *args, **kwargs): self.data = kwargs.pop("data", None) super().__init__(*args, **kwargs) + class MonitoringMetric(str, Enum): CPU_USAGE = "cpu_usage" MEM_USAGE = "mem_usage" @@ -1456,6 +1562,8 @@ class MonitoringMetric(str, Enum): BACKTRACK_TOKENS = "backtrack_tokens" TOKEN_COUNT = "token_count" TOKEN_REDUCTION = "token_reduction" + AVG_LATENCY = "avg_latency" + ALL_METRICS = [ MonitoringMetric.CPU_USAGE, @@ -1467,15 +1575,23 @@ class MonitoringMetric(str, Enum): MonitoringMetric.OUTPUT_TOKENS, MonitoringMetric.BACKTRACK_TOKENS, MonitoringMetric.TOKEN_COUNT, - MonitoringMetric.TOKEN_REDUCTION + MonitoringMetric.TOKEN_REDUCTION, + MonitoringMetric.AVG_LATENCY, ] -def _monitor_fn(stop_flag, metrics_dict: dict[MonitoringMetric, list], max_size: int = 100, interval_ms: float = 1000): + +def _monitor_fn( + stop_flag, + metrics_dict: dict[MonitoringMetric, list], + max_size: int = 100, + interval_ms: float = 1000, +): print("Monitoring started") to_collect_gpu_stats = False try: import gpustat + gpu_stats = gpustat.GPUStatCollection.new_query() if len(gpu_stats) > 0: # only collect GPU stats if there is at least one GPU @@ -1487,7 +1603,7 @@ def _monitor_fn(stop_flag, metrics_dict: dict[MonitoringMetric, list], max_size: while not stop_flag.value: t0 = time.time() - #cpu_percent = psutil.cpu_percent(interval=1) + # cpu_percent = psutil.cpu_percent(interval=1) cpu_percent = psutil.cpu_percent() memory_usage = psutil.virtual_memory() @@ -1508,7 +1624,7 @@ def _monitor_fn(stop_flag, metrics_dict: dict[MonitoringMetric, list], max_size: metrics_dict[MonitoringMetric.GPU_TOTAL_MEM].append(mem_total) t2 = time.time() - + for metrics in metrics_dict.values(): if len(metrics) > max_size: metrics.pop(0) @@ -1530,32 +1646,34 @@ def _monitor_fn(stop_flag, metrics_dict: dict[MonitoringMetric, list], max_size: print("Monitoring stopped") + class Monitor: - """Monitoring service to collect neccessary metrics for visualizatoin - """ - + """Monitoring service to collect neccessary metrics for visualizatoin""" + def __init__(self, engine: Engine, **kwargs): self.engine = engine self.mp_manager = Manager() # use list instead of queue for easily accessing each item, e.g., last item self.max_size = kwargs.get("max_size", 100) - + self.metrics_dict = { MonitoringMetric.CPU_USAGE: self.mp_manager.list(), MonitoringMetric.MEM_USAGE: self.mp_manager.list(), MonitoringMetric.GPU_USAGE: self.mp_manager.list(), MonitoringMetric.GPU_USED_MEM: self.mp_manager.list(), - MonitoringMetric.GPU_TOTAL_MEM: self.mp_manager.list() + MonitoringMetric.GPU_TOTAL_MEM: self.mp_manager.list(), } self.stop_flag = self.mp_manager.Value("b", False) self.process = None - self.per_token_metrics = [] # store metrics per token in token list + self.per_token_metrics = [] # store metrics per token in token list def start(self): - self.process = Process(target=_monitor_fn, args=(self.stop_flag, self.metrics_dict, self.max_size)) + self.process = Process( + target=_monitor_fn, args=(self.stop_flag, self.metrics_dict, self.max_size) + ) self.process.start() def stop(self): @@ -1574,7 +1692,9 @@ def reset(self): self.start() - def get_metrics(self, metrics: list[MonitoringMetric] = ALL_METRICS, lm: Union[Model, None] = None) -> dict[MonitoringMetric, Any]: + def get_metrics( + self, metrics: list[MonitoringMetric] = ALL_METRICS, lm: Union[Model, None] = None + ) -> dict[MonitoringMetric, Any]: result = {} for metric in metrics: @@ -1583,9 +1703,11 @@ def get_metrics(self, metrics: list[MonitoringMetric] = ALL_METRICS, lm: Union[M MonitoringMetric.MEM_USAGE, MonitoringMetric.GPU_USAGE, MonitoringMetric.GPU_USED_MEM, - MonitoringMetric.GPU_TOTAL_MEM + MonitoringMetric.GPU_TOTAL_MEM, ]: - result[metric] = self.metrics_dict[metric][-1] if len(self.metrics_dict[metric]) > 0 else None + result[metric] = ( + self.metrics_dict[metric][-1] if len(self.metrics_dict[metric]) > 0 else None + ) elif metric == MonitoringMetric.INPUT_TOKENS: result[metric] = self.engine.metrics.engine_input_tokens elif metric == MonitoringMetric.OUTPUT_TOKENS: @@ -1596,11 +1718,31 @@ def get_metrics(self, metrics: list[MonitoringMetric] = ALL_METRICS, lm: Union[M result[metric] = lm.token_count if lm is not None else None elif metric == MonitoringMetric.TOKEN_REDUCTION: if lm is not None and lm.token_count > 0: - result[metric] = 1 - (self.engine.metrics.engine_output_tokens / lm.token_count) + result[metric] = 1 - ( + self.engine.metrics.engine_output_tokens / lm.token_count + ) else: result[metric] = None - + elif metric == MonitoringMetric.AVG_LATENCY: + if lm is None: + result[metric] = None + else: + lats = [] + model = lm + while model._parent is not None: + if model.vis_chunk: + for token in model.vis_chunk.generated_tokens: + lats.append(token.latency_ms) + for token in model.vis_chunk.force_forwarded_tokens: + lats.append(token.latency_ms) + model = model._parent + + if len(lats) == 0: + result[metric] = None + else: + result[metric] = np.mean(lats) + return result - + def get_metric(self, metric: MonitoringMetric, lm: Union[Model, None] = None) -> Any: - return self.get_metrics([metric], lm)[metric] \ No newline at end of file + return self.get_metrics([metric], lm)[metric] From f0142b7553bf6ecd877dce81cb681baee064e71b Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Sun, 13 Oct 2024 23:23:57 -0700 Subject: [PATCH 066/133] Update token reduction --- guidance/models/_model.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 0918eed52..bda342195 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -168,18 +168,21 @@ def emit_messages(self, lm: "Model"): # ) token_reduction = self._monitor.get_metric(MonitoringMetric.TOKEN_REDUCTION, lm) - self._renderer.update( - MetricMessage( - name="token reduction", - value=token_reduction * 100, + if token_reduction is not None: + self._renderer.update( + MetricMessage( + name="token reduction", + value=token_reduction * 100, + ) ) - ) output_tokens = self._monitor.get_metric(MonitoringMetric.OUTPUT_TOKENS, lm) - self._renderer.update(MetricMessage(name="consumed", value=output_tokens)) + if output_tokens is not None: + self._renderer.update(MetricMessage(name="consumed", value=output_tokens)) avg_latency = self._monitor.get_metric(MonitoringMetric.AVG_LATENCY, lm) - self._renderer.update(MetricMessage(name="avg latency", value=avg_latency)) + if avg_latency is not None: + self._renderer.update(MetricMessage(name="avg latency", value=avg_latency)) class Engine: @@ -922,9 +925,6 @@ def __add__(self, value): # (we need to do this since Model objects are immutable) lm = self.copy() - # map model's metrics to engine - lm.engine.metrics = lm.metrics - # find blocks that are now active, but haven't been opened by lm yet enter_blocks = [] for context in Model.global_active_blocks: @@ -1077,9 +1077,6 @@ def __add__(self, value): f"A guidance function did not return a model object! Did you try to add a function to a model without calling the function? For example `model + guidance_function()` is correct, while `model + guidance_function` will cause this error." ) - # copy model metrics back to engine - out.metrics = self.engine.metrics.model_copy(deep=True) - return out # def endswith(self, s): @@ -1260,6 +1257,8 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): # we will return a new extended version of ourselves, which we track as `lm` lm = self + lm.engine.metrics = lm.metrics.model_copy(deep=True) + # single generation if n == 1: generated_value = "" @@ -1421,6 +1420,8 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): logger.debug("finish Model._run_stateless") + lm.metrics = lm.engine.metrics.model_copy(deep=True) + return lm @@ -1718,9 +1719,7 @@ def get_metrics( result[metric] = lm.token_count if lm is not None else None elif metric == MonitoringMetric.TOKEN_REDUCTION: if lm is not None and lm.token_count > 0: - result[metric] = 1 - ( - self.engine.metrics.engine_output_tokens / lm.token_count - ) + result[metric] = 1 - min(1, (lm.metrics.engine_output_tokens / lm.token_count)) else: result[metric] = None elif metric == MonitoringMetric.AVG_LATENCY: From b2af267b6aad7265469d35d78c718c1e1ad7575b Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Mon, 14 Oct 2024 10:18:01 -0700 Subject: [PATCH 067/133] rename metrics generator --- guidance/models/_model.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index bda342195..513de6805 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -84,8 +84,7 @@ image_pattern = re.compile(r"<\|_image:(.*?)\|>") -# TODO(nopdive): Remove on implementation. -class MockMetricsGenerator: +class MetricsGenerator: def __init__(self, renderer: Renderer, monitor: "Monitor", sleep_sec=0.5): from ..visual._async import run_async_task @@ -97,7 +96,6 @@ def __init__(self, renderer: Renderer, monitor: "Monitor", sleep_sec=0.5): async def _emit(self): import asyncio import time - import random time_start = time.time() while True: @@ -124,10 +122,6 @@ async def _emit(self): if not mem_percent: mem_percent = 0 - # print(f"CPU: {cpu_percent}, RAM: {mem_percent}") - # print("gpu_percent", gpu_percent) - # print("gpu_used_vram",gpu_used_vram) - time_end = time.time() time_elapsed = time_end - time_start self._renderer.update(MetricMessage(name="wall time", value=time_elapsed)) @@ -149,15 +143,13 @@ async def _emit(self): self._renderer.update(MetricMessage(name="vram", value=gpu_used_vram)) -# # TODO(nopdive): Remove on implementation. -class MockPostExecGenerator: +class PostExecGenerator: def __init__(self, renderer: Renderer, monitor: "Monitor"): self._renderer = renderer self._monitor = monitor def emit_messages(self, lm: "Model"): - import random - + # import random # self._renderer.update(MetricMessage(name="avg latency", value=random.uniform(10, 200))) # self._renderer.update(MetricMessage(name="consumed", value=random.uniform(0, 100))) # self._renderer.update(MetricMessage(name="token reduction", value=random.uniform(0, 100))) @@ -210,8 +202,8 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False, **kwargs): self.monitor.start() # TODO(nopdive): Remove on implementation. - self.metrics_generator = MockMetricsGenerator(self.renderer, self.monitor) - self.post_exec_generator = MockPostExecGenerator(self.renderer, self.monitor) + self.metrics_generator = MetricsGenerator(self.renderer, self.monitor) + self.post_exec_generator = PostExecGenerator(self.renderer, self.monitor) def _msg_recv(self, message: GuidanceMessage) -> None: # NOTE(nopdive): This is likely running on a secondary thread. From a3bd85ac42bb6316f87280647e07156fa1cf587e Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Mon, 14 Oct 2024 15:37:57 -0700 Subject: [PATCH 068/133] Add get_token_probs into llama_cpp --- guidance/models/llama_cpp/_llama_cpp.py | 107 ++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/guidance/models/llama_cpp/_llama_cpp.py b/guidance/models/llama_cpp/_llama_cpp.py index ee000d14a..e33dda982 100644 --- a/guidance/models/llama_cpp/_llama_cpp.py +++ b/guidance/models/llama_cpp/_llama_cpp.py @@ -11,6 +11,8 @@ import numpy as np +from guidance._schema import BaseGenToken + from .._model import Engine, Model, Chat from .._remote import RemoteEngine from .._tokenizer import Tokenizer @@ -216,6 +218,111 @@ def get_logits(self, token_ids): self._cached_logits = logits return logits + + def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[BaseGenToken]]: + if len(token_ids) == 0: + return [] + + # clear kv-cache + llama_cpp.llama_kv_cache_seq_rm(self.model_obj.ctx, -1, 0, -1) + + # create new context + context = self._context + n_batch = self.model_obj.n_batch + batch = context.batch + + logits_batch = [] + for i in range(0, len(token_ids), n_batch): + n_tokens = min(i + n_batch, len(token_ids)) - i + batch.n_tokens = n_tokens + + for j in range(n_tokens): + batch.token[j] = token_ids[i + j] + batch.pos[j] = i + j + batch.seq_id[j][0] = 0 + batch.n_seq_id[j] = 1 + batch.logits[j] = True + + ret = llama_cpp.llama_decode(self.model_obj.ctx, batch) + if ret != 0: + raise Exception(f"Call to llama_cpp.llama_decode returned {ret}.") + + # get all the logits + if llama_cpp.__version__ < "0.2.58": + logits = llama_cpp.llama_get_logits(self.model_obj.ctx) + logits = logits.reshape((-1, self._n_vocab)) + logits_batch.extend(logits) + else: + for j in range(n_tokens): + logits = llama_cpp.llama_get_logits_ith(self.model_obj.ctx, j) + logits = np.ctypeslib.as_array(logits, shape=(self._n_vocab,)).copy() + logits_batch.append(logits) + + # process each token's logits + text_sequence = [] + + # add 1st token + _bytes = self.tokenizer.decode([token_ids[0]]) + try: + _text = _bytes.decode('utf-8') + except Exception as e: + _text = str(_bytes) + print(f"Failed to decode token: {token_ids[0]}, error: {e}, _bytes: {str(_bytes)}") + text_sequence.append( + [BaseGenToken( + token=token_ids[0], + prob=1.0, + text=_text + )] + ) + + for token_idx, logits in zip(token_ids[1:], logits_batch[:-1]): + _probs = self._softmax(logits) + + # get the top k indices + top_k_indices, top_k_probs = self._top_k(_probs.copy(), top_k, ascending=False) + if token_idx not in top_k_indices: + top_k_indices = np.append(top_k_indices, token_idx) + top_k_probs = np.append(top_k_probs, _probs[token_idx]) + + top_k_list = [] + for _token_idx, _prob in zip(top_k_indices, top_k_probs): + _text = "" + try: + _text = self.tokenizer.decode([_token_idx]).decode('utf-8') + except Exception as e: + _bytes = self.tokenizer.decode([_token_idx]) + _text = str(_bytes) + print(f"Failed to decode token: {_token_idx}, error: {e}, _bytes: {str(_bytes)}") + top_k_list.append( + BaseGenToken( + token=_token_idx, + prob=_prob, + text=_text + ) + ) + + text_sequence.append(top_k_list) + + return text_sequence + + def _softmax(self, x) -> np.ndarray: + return(np.exp(x - np.max(x)) / np.exp(x - np.max(x)).sum()) + + def _top_k(self, input, k, axis=None, ascending=True): + if not ascending: + input *= -1 + ind = np.argpartition(input, k, axis=axis) + ind = np.take(ind, np.arange(k), axis=axis) # k non-sorted indices + input = np.take_along_axis(input, ind, axis=axis) # k non-sorted values + + # sort within k elements + ind_part = np.argsort(input, axis=axis) + ind = np.take_along_axis(ind, ind_part, axis=axis) + if not ascending: + input *= -1 + val = np.take_along_axis(input, ind_part, axis=axis) + return ind, val class LlamaCpp(Model): From 252b97c63debf209e33ea7287211650330d33ba4 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Mon, 14 Oct 2024 16:27:18 -0700 Subject: [PATCH 069/133] add workaround for engines that don't support get_token_probs --- guidance/models/_model.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index e4e705130..979124b15 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -253,7 +253,14 @@ def _msg_recv(self, message: GuidanceMessage) -> None: # gen_tokens.extend(vis_chunk.force_forwarded_tokens) tokens = self.tokenizer.encode(text.encode("utf-8")) - probs = self.get_token_probs(tokens) + + # NOTE (loc): Not all engines support the get_token_probs method + try: + probs = self.get_token_probs(tokens) + except Exception as e: + # FIXME (loc): assume prob 1.0 for all tokens + probs = [1.0] * len(tokens) + tokens_texts: list[str] = [] for idx in range(len(tokens)): tokens_texts.append(self.tokenizer.decode([tokens[idx]]).decode("utf-8")) From 734df5a35901ca830a8415d9ca04a03099e43e15 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Tue, 15 Oct 2024 11:49:41 -0700 Subject: [PATCH 070/133] Refactor get token stats out of _msg_recv func --- guidance/models/_model.py | 372 +++++++++++++++++++------------------- 1 file changed, 187 insertions(+), 185 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 979124b15..91bd1c8bb 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -192,7 +192,7 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False, **kwargs): self.trace_handler = TraceHandler() self.renderer = AutoRenderer( - self.trace_handler, use_legacy_renderer=kwargs.get("use_legacy_renderer", False) + self.trace_handler, use_legacy_renderer=kwargs.get("use_legacy_renderer", True) ) self.renderer.subscribe(self._msg_recv) self.model_dict: dict[int, Model] = {} @@ -200,7 +200,6 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False, **kwargs): self.monitor = Monitor(self) self.monitor.start() - # TODO(nopdive): Remove on implementation. self.metrics_generator = MetricsGenerator(self.renderer, self.monitor) self.post_exec_generator = PostExecGenerator(self.renderer, self.monitor) @@ -216,195 +215,18 @@ def _msg_recv(self, message: GuidanceMessage) -> None: self.post_exec_generator.emit_messages(last_model) self.renderer.update(message) - paths = [] - model = last_model - while model is not None: - paths.append(model) - if model._parent_id is None: - break - - model: "Model" = self.model_dict[model._parent_id] - - paths.reverse() - - vis_chunks: list[VisBytesChunk] = [ - path.vis_chunk for path in paths if path.vis_chunk is not None - ] - gen_tokens_lats = [] - gen_tokens_indices = [] - for vis_chunk in vis_chunks: - for engine_output in vis_chunk.engine_outputs: - gen_tokens_lats.append( - ( - engine_output.issued_token.token, - engine_output.issued_token.latency_ms, - engine_output.masked_top_k, - ) - ) - gen_tokens_indices.append(len(gen_tokens_lats) - 1) - gen_tokens_lats_idx = 0 - - text = last_model._state - # gen_tokens: list[GenToken] = [] - # for vis_chunk in vis_chunks: - # text += vis_chunk.bytes.decode("utf-8") - # gen_tokens.extend(vis_chunk.input_tokens) - # gen_tokens.extend(vis_chunk.generated_tokens) - # gen_tokens.extend(vis_chunk.force_forwarded_tokens) - - tokens = self.tokenizer.encode(text.encode("utf-8")) - - # NOTE (loc): Not all engines support the get_token_probs method + failed = False try: - probs = self.get_token_probs(tokens) + processed_gen_tokens = last_model.get_per_token_stats() except Exception as e: - # FIXME (loc): assume prob 1.0 for all tokens - probs = [1.0] * len(tokens) - - tokens_texts: list[str] = [] - for idx in range(len(tokens)): - tokens_texts.append(self.tokenizer.decode([tokens[idx]]).decode("utf-8")) - - start_idx = 0 - end_idx = 1 - start_pos = 0 - remainder = "" - failed = False - - processed_gen_tokens = [] - for vis_chunk_idx, vis_chunk in enumerate(vis_chunks): - vis_text = vis_chunk.bytes.decode("utf-8") - - if not vis_text: - continue - - end_idx = start_idx - _chunk = "".join(tokens_texts[start_idx : end_idx + 1]) - while vis_text not in _chunk and end_idx < len(tokens_texts): - # expand the chunk - end_idx += 1 - _chunk = "".join(tokens_texts[start_idx : end_idx + 1]) - - if vis_text not in _chunk and end_idx >= len(tokens_texts): - failed = True - break - - if vis_text == _chunk: - # perfect match - pass - else: - start_pos = _chunk.index(vis_text) - remainder = _chunk[start_pos + len(vis_text) :] - - if remainder: - # we have a current chunk that is larger than the vis_text - # probably the last token is a partial token - # we should not issue that token for now - end_idx -= 1 - - real_chunk_tokens = tokens[start_idx : end_idx + 1] - real_chunk_probs = probs[start_idx : end_idx + 1] - - is_input = len(vis_chunk.input_tokens) > 0 - is_force_forwarded = len(vis_chunk.force_forwarded_tokens) > 0 - - _gen_tokens: list[GenToken] = [] - for token, top_k_prob in zip(real_chunk_tokens, real_chunk_probs): - prob = -1 - for _token in top_k_prob: - if _token.token == token: - prob = _token.prob - break - - _gen_token = GenToken( - token=token, - prob=prob, - text=self.tokenizer.decode([token]).decode("utf-8"), - latency_ms=0, - is_input=is_input, - is_generated=False, - is_force_forwarded=False, - ) - _gen_token.top_k = top_k_prob - _gen_tokens.append(_gen_token) - - for i, _gen_token in enumerate(_gen_tokens): - if not is_input: - if i < len(vis_chunk.generated_tokens): - _gen_token.is_generated = True - else: - if is_force_forwarded: - _gen_token.is_force_forwarded = True - - found_perfect_match = False - max_idx = gen_tokens_indices[vis_chunk_idx] - for idx in range(max_idx, -1, -1): - if _gen_token.token == gen_tokens_lats[idx][0]: - _gen_token.latency_ms = gen_tokens_lats[idx][1] - _masked_top_k = gen_tokens_lats[idx][2] - if _masked_top_k is None: - # in free accepting state, no masking - for _token in _gen_token.top_k: - _token.is_masked = False - else: - _masked_tokens = [token.token for token in _masked_top_k] - for _token in _gen_token.top_k: - if _token.token not in _masked_tokens: - _token.is_masked = True - else: - _token.is_masked = False - - found_perfect_match = True - break - - if not found_perfect_match: - # only search within this chunk - max_idx = gen_tokens_indices[vis_chunk_idx] - prev_max_idx = ( - -1 - if vis_chunk_idx == 0 - else gen_tokens_indices[vis_chunk_idx - 1] - 1 - ) - for idx in range(max_idx, prev_max_idx, -1): - if ( - self.tokenizer.decode([gen_tokens_lats[idx][0]]).decode( - "utf-8" - ) - in _gen_token.text - ): - _gen_token.latency_ms = gen_tokens_lats[idx][1] - _masked_top_k = gen_tokens_lats[idx][2] - if _masked_top_k is None: - # in free accepting state, no masking - for _token in _gen_token.top_k: - _token.is_masked = False - else: - _masked_tokens = [token.token for token in _masked_top_k] - for _token in _gen_token.top_k: - if ( - _token.token not in _masked_tokens - and _token.token != _gen_token.token - ): - _token.is_masked = True - else: - _token.is_masked = False - - break - else: - # input tokens are not masked - for _token in _gen_token.top_k: - _token.is_masked = False - - processed_gen_tokens.extend(_gen_tokens) - - start_idx = end_idx + 1 - - start_pos = 0 - remainder = "" + logger.error(f"Failed to get per token stats: {e}") + failed = True if not failed: final_text = "".join([gen_token.text for gen_token in processed_gen_tokens]) logger.debug(f"ENGINE:final_text:{final_text}") + + tokens = [gen_token.token for gen_token in processed_gen_tokens] self.renderer.update( ExecutionCompletedOutputMessage( trace_id=message.last_trace_id, @@ -1426,6 +1248,186 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): return lm + def get_per_token_stats(self) -> list[GenToken]: + paths = [] + model = self + while model is not None: + paths.append(model) + if model._parent_id is None: + break + + model: "Model" = self.engine.model_dict[model._parent_id] + + paths.reverse() + + vis_chunks: list[VisBytesChunk] = [ + path.vis_chunk for path in paths if path.vis_chunk is not None + ] + + gen_tokens_lats = [] + gen_tokens_indices = [] + for vis_chunk in vis_chunks: + for engine_output in vis_chunk.engine_outputs: + gen_tokens_lats.append( + ( + engine_output.issued_token.token, + engine_output.issued_token.latency_ms, + engine_output.masked_top_k, + ) + ) + gen_tokens_indices.append(len(gen_tokens_lats) - 1) + + text = self._state + tokens = self.engine.tokenizer.encode(text.encode("utf-8")) + + # NOTE (loc): Not all engines support the get_token_probs method + try: + probs = self.engine.get_token_probs(tokens) + except Exception as e: + # FIXME (loc): assume prob 1.0 for all tokens + probs = [1.0] * len(tokens) + + tokens_texts: list[str] = [] + for idx in range(len(tokens)): + tokens_texts.append(self.engine.tokenizer.decode([tokens[idx]]).decode("utf-8")) + + start_idx = 0 + end_idx = 1 + start_pos = 0 + remainder = "" + + processed_gen_tokens = [] + for vis_chunk_idx, vis_chunk in enumerate(vis_chunks): + vis_text = vis_chunk.bytes.decode("utf-8") + + if not vis_text: + continue + + end_idx = start_idx + _chunk = "".join(tokens_texts[start_idx : end_idx + 1]) + while vis_text not in _chunk and end_idx < len(tokens_texts): + # expand the chunk + end_idx += 1 + _chunk = "".join(tokens_texts[start_idx : end_idx + 1]) + + if vis_text not in _chunk and end_idx >= len(tokens_texts): + # failed = True + # break + raise Exception(f"Failed to find the {vis_text} in the tokens chunk {_chunk}") + + if vis_text == _chunk: + # perfect match + pass + else: + start_pos = _chunk.index(vis_text) + remainder = _chunk[start_pos + len(vis_text) :] + + if remainder: + # we have a current chunk that is larger than the vis_text + # probably the last token is a partial token + # we should not issue that token for now + end_idx -= 1 + + real_chunk_tokens = tokens[start_idx : end_idx + 1] + real_chunk_probs = probs[start_idx : end_idx + 1] + + is_input = len(vis_chunk.input_tokens) > 0 + is_force_forwarded = len(vis_chunk.force_forwarded_tokens) > 0 + + _gen_tokens: list[GenToken] = [] + for token, top_k_prob in zip(real_chunk_tokens, real_chunk_probs): + prob = -1 + for _token in top_k_prob: + if _token.token == token: + prob = _token.prob + break + + _gen_token = GenToken( + token=token, + prob=prob, + text=self.engine.tokenizer.decode([token]).decode("utf-8"), + latency_ms=0, + is_input=is_input, + is_generated=False, + is_force_forwarded=False, + ) + _gen_token.top_k = top_k_prob + _gen_tokens.append(_gen_token) + + for i, _gen_token in enumerate(_gen_tokens): + if not is_input: + if i < len(vis_chunk.generated_tokens): + _gen_token.is_generated = True + else: + if is_force_forwarded: + _gen_token.is_force_forwarded = True + + found_perfect_match = False + max_idx = gen_tokens_indices[vis_chunk_idx] + for idx in range(max_idx, -1, -1): + if _gen_token.token == gen_tokens_lats[idx][0]: + _gen_token.latency_ms = gen_tokens_lats[idx][1] + _masked_top_k = gen_tokens_lats[idx][2] + if _masked_top_k is None: + # in free accepting state, no masking + for _token in _gen_token.top_k: + _token.is_masked = False + else: + _masked_tokens = [token.token for token in _masked_top_k] + for _token in _gen_token.top_k: + if _token.token not in _masked_tokens: + _token.is_masked = True + else: + _token.is_masked = False + + found_perfect_match = True + break + + if not found_perfect_match: + # only search within this chunk + max_idx = gen_tokens_indices[vis_chunk_idx] + prev_max_idx = ( + -1 if vis_chunk_idx == 0 else gen_tokens_indices[vis_chunk_idx - 1] - 1 + ) + for idx in range(max_idx, prev_max_idx, -1): + if ( + self.engine.tokenizer.decode([gen_tokens_lats[idx][0]]).decode( + "utf-8" + ) + in _gen_token.text + ): + _gen_token.latency_ms = gen_tokens_lats[idx][1] + _masked_top_k = gen_tokens_lats[idx][2] + if _masked_top_k is None: + # in free accepting state, no masking + for _token in _gen_token.top_k: + _token.is_masked = False + else: + _masked_tokens = [token.token for token in _masked_top_k] + for _token in _gen_token.top_k: + if ( + _token.token not in _masked_tokens + and _token.token != _gen_token.token + ): + _token.is_masked = True + else: + _token.is_masked = False + + break + else: + # input tokens are not masked + for _token in _gen_token.top_k: + _token.is_masked = False + + processed_gen_tokens.extend(_gen_tokens) + + start_idx = end_idx + 1 + + start_pos = 0 + remainder = "" + + return processed_gen_tokens + class ModelStream: def __init__(self, model, grammar=None, timeout=5): From 6c8ec65a85608aebfe7bfb6fbf96698b2e6b1e3c Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Tue, 15 Oct 2024 13:08:31 -0700 Subject: [PATCH 071/133] set new ui as default --- guidance/models/_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 91bd1c8bb..eebb6948b 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -192,7 +192,7 @@ def __init__(self, tokenizer: Tokenizer, compute_log_probs=False, **kwargs): self.trace_handler = TraceHandler() self.renderer = AutoRenderer( - self.trace_handler, use_legacy_renderer=kwargs.get("use_legacy_renderer", True) + self.trace_handler, use_legacy_renderer=kwargs.get("use_legacy_renderer", False) ) self.renderer.subscribe(self._msg_recv) self.model_dict: dict[int, Model] = {} From c29accca692ecafa54f8469676884a9889db3c8e Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 15 Oct 2024 13:12:19 -0700 Subject: [PATCH 072/133] Client-side clean-ups. --- client/graphpaper-inline/package.json | 1 + client/graphpaper-inline/pnpm-lock.yaml | 3 + client/graphpaper-inline/src/App.svelte | 31 +- .../graphpaper-inline/src/MetricCard.svelte | 35 +- client/graphpaper-inline/src/Minibar.svelte | 9 +- client/graphpaper-inline/src/TokenGrid.svelte | 39 +- .../src/TokenGridItem.svelte | 42 +- client/graphpaper-inline/src/interfaces.ts | 20 + client/graphpaper-inline/src/mocks.ts | 4315 +++++++++-------- 9 files changed, 2445 insertions(+), 2050 deletions(-) create mode 100644 client/graphpaper-inline/src/interfaces.ts diff --git a/client/graphpaper-inline/package.json b/client/graphpaper-inline/package.json index 3dc659ded..e889ffc3c 100644 --- a/client/graphpaper-inline/package.json +++ b/client/graphpaper-inline/package.json @@ -32,6 +32,7 @@ "typescript": "^5.5.4" }, "dependencies": { + "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-scale-chromatic": "^3.1.0", "dompurify": "^3.1.7" diff --git a/client/graphpaper-inline/pnpm-lock.yaml b/client/graphpaper-inline/pnpm-lock.yaml index 065b74962..ecafc68c6 100644 --- a/client/graphpaper-inline/pnpm-lock.yaml +++ b/client/graphpaper-inline/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + d3-interpolate: + specifier: ^3.0.1 + version: 3.0.1 d3-scale: specifier: ^4.0.2 version: 4.0.2 diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index dc300f834..5313cc5eb 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -19,15 +19,18 @@ } from './stitch'; import StitchHandler from './StitchHandler.svelte'; import {onMount} from "svelte"; - import MetricCard, {type MetricDef, type MetricVal} from "./MetricCard.svelte"; - // import {mockGenTokens, mockNodeAttrs} from "./mocks"; + import {type MetricDef, type MetricVal} from "./interfaces"; + import MetricCard from "./MetricCard.svelte"; + import {mockGenTokens, mockNodeAttrs} from "./mocks"; let msg: any; let textComponents: Array = []; let tokenDetails: Array = []; - // textComponents = mockNodeAttrs; - // tokenDetails = mockGenTokens; let completedExecution: boolean = false; + let mode: string; + + textComponents = mockNodeAttrs; + tokenDetails = mockGenTokens; $: if ($kernelmsg !== undefined) { if ($kernelmsg.content !== '') { @@ -135,7 +138,8 @@ isScalar: true, precision: 0, } - } + }; + let selectedMetricDef: MetricDef = metricDefs['consumed']; const metrics: Record = { 'status': '✓', @@ -147,7 +151,11 @@ 'avg latency': 0, 'consumed': 0, 'token reduction': 0, - } + }; + + let metricModes = new Set(); + metricModes.add('avg latency'); + metricModes.add('consumed'); onMount(() => { const msg: StitchMessage = { @@ -155,7 +163,12 @@ content: JSON.stringify({ 'class_name': 'ClientReadyMessage' }) } clientmsg.set(msg); - }) + }); + + const onNavClick = (event: CustomEvent) => { + mode = event.detail; + selectedMetricDef = metricDefs[mode]; + }; @@ -170,12 +183,12 @@
- +
\ No newline at end of file diff --git a/client/graphpaper-inline/src/MetricCard.svelte b/client/graphpaper-inline/src/MetricCard.svelte index 07f82a9fa..7f5f50eaf 100644 --- a/client/graphpaper-inline/src/MetricCard.svelte +++ b/client/graphpaper-inline/src/MetricCard.svelte @@ -1,38 +1,39 @@ + -
-
{metricDef.name}
+
+
{metricDef.name}
{#if value.constructor === Array} - + {:else} {#if typeof value === "number"} -
{value.toFixed(metricDef.precision)}{metricDef.units}
+
{value.toFixed(metricDef.precision)}{metricDef.units}
{:else} -
{value}{metricDef.units}
+
{value}{metricDef.units}
{/if} {/if}
\ No newline at end of file diff --git a/client/graphpaper-inline/src/Minibar.svelte b/client/graphpaper-inline/src/Minibar.svelte index 52f871eb2..0b54777f2 100644 --- a/client/graphpaper-inline/src/Minibar.svelte +++ b/client/graphpaper-inline/src/Minibar.svelte @@ -3,7 +3,7 @@
- {#each values as val, i} + {#each typedValues as val, i} {/each} diff --git a/client/graphpaper-inline/src/TokenGrid.svelte b/client/graphpaper-inline/src/TokenGrid.svelte index 05dba47fc..815f56074 100644 --- a/client/graphpaper-inline/src/TokenGrid.svelte +++ b/client/graphpaper-inline/src/TokenGrid.svelte @@ -2,13 +2,29 @@ @@ -230,7 +248,7 @@ Token
- {@html DOMPurify.sanitize(escapeWhitespaceCharacters(tooltipToken.text))} + {@html renderText(tooltipToken.text)}
{#if tooltipToken.extra !== undefined} @@ -248,8 +266,14 @@ {#each tooltipToken.extra.top_k as candidate} - {@html DOMPurify.sanitize(escapeWhitespaceCharacters(candidate.text))} - {candidate.prob.toFixed(3)} + + + {@html renderText(candidate.text)} + + + + {candidate.prob.toFixed(3)} + {/each} @@ -279,8 +303,7 @@ {/if} {/if} - - + {/each} {#if isCompleted === false} diff --git a/client/graphpaper-inline/src/TokenGridItem.svelte b/client/graphpaper-inline/src/TokenGridItem.svelte index 385cede43..29343d984 100644 --- a/client/graphpaper-inline/src/TokenGridItem.svelte +++ b/client/graphpaper-inline/src/TokenGridItem.svelte @@ -1,43 +1,43 @@ - - {#each token.text as ch, i} {#if ch === ' '} - +   {:else if ch === '\t'} - + \t   {:else if ch === '\n'} - + \n
{:else} - + {#if i === 0} {token.role} diff --git a/client/graphpaper-inline/src/interfaces.ts b/client/graphpaper-inline/src/interfaces.ts new file mode 100644 index 000000000..247e65f6c --- /dev/null +++ b/client/graphpaper-inline/src/interfaces.ts @@ -0,0 +1,20 @@ +import type {GenToken} from "./stitch"; + +export interface MetricDef { + name: string, + units: string, + description: string, + isScalar: boolean, + precision: number, +} + +export type MetricVal = string | number | Array; + +export interface Token { + text: string, + prob: number, + role: string, + special: boolean, + extra?: GenToken, +} +export declare type TokenCallback = (token: Token) => number; diff --git a/client/graphpaper-inline/src/mocks.ts b/client/graphpaper-inline/src/mocks.ts index 67fb88c02..869d13cbc 100644 --- a/client/graphpaper-inline/src/mocks.ts +++ b/client/graphpaper-inline/src/mocks.ts @@ -117,1994 +117,2327 @@ export const mockNodeAttrs: Array = - [ - { - "token": 27, - "prob": 1, - "text": "<", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 27, - "prob": 1, - "text": "<" - } - ] - }, - { - "token": 91, - "prob": 0.0008722934871912003, - "text": "|", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 198, - "prob": 0.029958423227071762, - "text": "\n" - }, - { - "token": 13, - "prob": 0.013489649631083012, - "text": "." - }, - { - "token": 16, - "prob": 0.011806909926235676, - "text": "1" - }, - { - "token": 12, - "prob": 0.010169479995965958, - "text": "-" - }, - { - "token": 15, - "prob": 0.009271609596908092, - "text": "0" - }, - { - "token": 91, - "prob": 0.0008722934871912003, - "text": "|" - } - ] - }, - { - "token": 320, - "prob": 0.000027396810764912516, - "text": "im", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 930, - "prob": 0.12004928290843964, - "text": " |" - }, - { - "token": 29, - "prob": 0.06939840316772461, - "text": ">" - }, - { - "token": 27, - "prob": 0.03129403665661812, - "text": "<" - }, - { - "token": 198, - "prob": 0.028110388666391373, - "text": "\n" - }, - { - "token": 60, - "prob": 0.02136152982711792, - "text": "]" - }, - { - "token": 320, - "prob": 0.000027396810764912516, - "text": "im" - } - ] - }, - { - "token": 62, - "prob": 0.01482831034809351, - "text": "_", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 91, - "prob": 0.42150357365608215, - "text": "|" - }, - { - "token": 7629, - "prob": 0.023308370262384415, - "text": "perial" - }, - { - "token": 60, - "prob": 0.020157789811491966, - "text": "]" - }, - { - "token": 14, - "prob": 0.018618104979395866, - "text": "/" - }, - { - "token": 92, - "prob": 0.015273063443601131, - "text": "}" - }, - { - "token": 62, - "prob": 0.01482831034809351, - "text": "_" - } - ] - }, - { - "token": 9688, - "prob": 0.0003535318828653544, - "text": "start", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 91, - "prob": 0.017649956047534943, - "text": "|" - }, - { - "token": 79, - "prob": 0.011138186790049076, - "text": "p" - }, - { - "token": 16366, - "prob": 0.011045439168810844, - "text": "client" - }, - { - "token": 82, - "prob": 0.008266090415418148, - "text": "s" - }, - { - "token": 15908, - "prob": 0.00811094231903553, - "text": "dir" - }, - { - "token": 9688, - "prob": 0.0003535318828653544, - "text": "start" - } - ] - }, - { - "token": 91, - "prob": 0.12612135708332062, - "text": "|", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 62, - "prob": 0.3673606216907501, - "text": "_" - }, - { - "token": 91, - "prob": 0.12612135708332062, - "text": "|" - }, - { - "token": 929, - "prob": 0.041732169687747955, - "text": "up" - }, - { - "token": 92, - "prob": 0.032134898006916046, - "text": "}" - }, - { - "token": 28, - "prob": 0.024743985384702682, - "text": "=" - } - ] - }, - { - "token": 29, - "prob": 0.012729871086776257, - "text": ">", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 259, - "prob": 0.028011340647935867, - "text": "in" - }, - { - "token": 4023, - "prob": 0.01824311725795269, - "text": "http" - }, - { - "token": 27, - "prob": 0.015950094908475876, - "text": "<" - }, - { - "token": 929, - "prob": 0.01563503034412861, - "text": "up" - }, - { - "token": 29, - "prob": 0.012729871086776257, - "text": ">" - } - ] - }, - { - "token": 10057, - "prob": 0.00004459881893126294, - "text": "system", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 91, - "prob": 0.2632869482040405, - "text": "|" - }, - { - "token": 198, - "prob": 0.05016319826245308, - "text": "\n" - }, - { - "token": 1279, - "prob": 0.04930492863059044, - "text": " <" - }, - { - "token": 930, - "prob": 0.045030541718006134, - "text": " |" - }, - { - "token": 28, - "prob": 0.023192651569843292, - "text": "=" - }, - { - "token": 10057, - "prob": 0.00004459881893126294, - "text": "system" - } - ] - }, - { - "token": 198, - "prob": 0.01464146375656128, - "text": "\n", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 91, - "prob": 0.20154249668121338, - "text": "|" - }, - { - "token": 3556, - "prob": 0.11300163716077805, - "text": "" - }, - { - "token": 361, - "prob": 0.02362215332686901, - "text": "if" - }, - { - "token": 3546, - "prob": 0.019490960985422134, - "text": "Im" - }, - { - "token": 930, - "prob": 0.016572270542383194, - "text": " |" - } - ] - }, - { - "token": 62, - "prob": 0.9976491332054138, - "text": "_", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 62, - "prob": 0.9976491332054138, - "text": "_" - }, - { - "token": 91, - "prob": 0.000336194148985669, - "text": "|" - }, - { - "token": 41052, - "prob": 0.00012316853099036962, - "text": "_(" - }, - { - "token": 29, - "prob": 0.000117526447866112, - "text": ">" - }, - { - "token": 59, - "prob": 0.00009838600090006366, - "text": "\\" - } - ] - }, - { - "token": 437, - "prob": 0.4462008774280548, - "text": "end", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 437, - "prob": 0.4462008774280548, - "text": "end" - }, - { - "token": 9688, - "prob": 0.09380462765693665, - "text": "start" - }, - { - "token": 12957, - "prob": 0.017503555864095688, - "text": "last" - }, - { - "token": 11338, - "prob": 0.016530489549040794, - "text": "stop" - }, - { - "token": 27471, - "prob": 0.012605799362063408, - "text": "begin" - } - ] - }, - { - "token": 91, - "prob": 0.9823351502418518, - "text": "|", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 91, - "prob": 0.9823351502418518, - "text": "|" - }, - { - "token": 29, - "prob": 0.002384455408900976, - "text": ">" - }, - { - "token": 60, - "prob": 0.0023481370881199837, - "text": "]" - }, - { - "token": 15886, - "prob": 0.002319696359336376, - "text": "||" - }, - { - "token": 930, - "prob": 0.0013476606691256166, - "text": " |" - } - ] - }, - { - "token": 29, - "prob": 0.9560039639472961, - "text": ">", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 29, - "prob": 0.9560039639472961, - "text": ">" - }, - { - "token": 6927, - "prob": 0.005681615322828293, - "text": "><" - }, - { - "token": 60, - "prob": 0.0032080409582704306, - "text": "]" - }, - { - "token": 27, - "prob": 0.002467683283612132, - "text": "<" - }, - { - "token": 4211, - "prob": 0.0021098603028804064, - "text": ">>" - } - ] - }, - { - "token": 198, - "prob": 0.02139684557914734, - "text": "\n", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 10057, - "prob": 0.35756662487983704, - "text": "system" - }, - { - "token": 198, - "prob": 0.02139684557914734, - "text": "\n" - }, - { - "token": 11964, - "prob": 0.01934202015399933, - "text": "System" - }, - { - "token": 1662, - "prob": 0.010047300718724728, - "text": "not" - }, - { - "token": 1169, - "prob": 0.006138301454484463, - "text": "the" - } - ] - }, - { - "token": 27, - "prob": 0.039419274777173996, - "text": "<", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 1639, - "prob": 0.1665498912334442, - "text": "You" - }, - { - "token": 464, - "prob": 0.06005862355232239, - "text": "The" - }, - { - "token": 27, - "prob": 0.039419274777173996, - "text": "<" - }, - { - "token": 1212, - "prob": 0.027387971058487892, - "text": "This" - }, - { - "token": 1532, - "prob": 0.022758493199944496, - "text": "If" - } - ] - }, - { - "token": 91, - "prob": 0.7559300065040588, - "text": "|", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 91, - "prob": 0.7559300065040588, - "text": "|" - }, - { - "token": 320, - "prob": 0.006860977970063686, - "text": "im" - }, - { - "token": 15886, - "prob": 0.0064566307701170444, - "text": "||" - }, - { - "token": 1671, - "prob": 0.004361273255199194, - "text": "br" - }, - { - "token": 930, - "prob": 0.004342366941273212, - "text": " |" - } - ] - }, - { - "token": 320, - "prob": 0.8291174173355103, - "text": "im", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 320, - "prob": 0.8291174173355103, - "text": "im" - }, - { - "token": 3546, - "prob": 0.012388699688017368, - "text": "Im" - }, - { - "token": 361, - "prob": 0.007399916183203459, - "text": "if" - }, - { - "token": 72, - "prob": 0.004467112943530083, - "text": "i" - }, - { - "token": 29, - "prob": 0.0026658582501113415, - "text": ">" - } - ] - }, - { - "token": 62, - "prob": 0.9993433356285095, - "text": "_", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 62, - "prob": 0.9993433356285095, - "text": "_" - }, - { - "token": 7, - "prob": 0.0000683960533933714, - "text": "(" - }, - { - "token": 59, - "prob": 0.00006206566467881203, - "text": "\\" - }, - { - "token": 13, - "prob": 0.00004414364229887724, - "text": "." - }, - { - "token": 29, - "prob": 0.00002257493724755477, - "text": ">" - } - ] - }, - { - "token": 9688, - "prob": 0.6440587043762207, - "text": "start", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 9688, - "prob": 0.6440587043762207, - "text": "start" - }, - { - "token": 437, - "prob": 0.05475924164056778, - "text": "end" - }, - { - "token": 27471, - "prob": 0.043713200837373734, - "text": "begin" - }, - { - "token": 11338, - "prob": 0.003659052774310112, - "text": "stop" - }, - { - "token": 38690, - "prob": 0.003096950938925147, - "text": "starting" - } - ] - }, - { - "token": 91, - "prob": 0.9499432444572449, - "text": "|", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 91, - "prob": 0.9499432444572449, - "text": "|" - }, - { - "token": 62, - "prob": 0.00848131813108921, - "text": "_" - }, - { - "token": 15886, - "prob": 0.005286256782710552, - "text": "||" - }, - { - "token": 930, - "prob": 0.003634629538282752, - "text": " |" - }, - { - "token": 29, - "prob": 0.0032877251505851746, - "text": ">" - } - ] - }, - { - "token": 29, - "prob": 0.9690060615539551, - "text": ">", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 29, - "prob": 0.9690060615539551, - "text": ">" - }, - { - "token": 6927, - "prob": 0.004052347969263792, - "text": "><" - }, - { - "token": 24618, - "prob": 0.0019232694758102298, - "text": ">\"" - }, - { - "token": 27, - "prob": 0.0012727173743769526, - "text": "<" - }, - { - "token": 4211, - "prob": 0.0011409870348870754, - "text": ">>" - } - ] - }, - { - "token": 7220, - "prob": 0.003625249955803156, - "text": "user", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 10057, - "prob": 0.43270590901374817, - "text": "system" - }, - { - "token": 11964, - "prob": 0.012400631792843342, - "text": "System" - }, - { - "token": 9688, - "prob": 0.008726297877728939, - "text": "start" - }, - { - "token": 847, - "prob": 0.007208186201751232, - "text": "other" - }, - { - "token": 198, - "prob": 0.006247976794838905, - "text": "\n" - }, - { - "token": 7220, - "prob": 0.003625249955803156, - "text": "user" - } - ] - }, - { - "token": 198, - "prob": 0.5544214248657227, - "text": "\n", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 198, - "prob": 0.5544214248657227, - "text": "\n" - }, - { - "token": 62, - "prob": 0.04264130815863609, - "text": "_" - }, - { - "token": 12, - "prob": 0.029624110087752342, - "text": "-" - }, - { - "token": 29, - "prob": 0.014048474840819836, - "text": ">" - }, - { - "token": 14, - "prob": 0.011965525336563587, - "text": "/" - } - ] - }, - { - "token": 49, - "prob": 0.00022193520271684974, - "text": "R", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 1639, - "prob": 0.39992958307266235, - "text": "You" - }, - { - "token": 27, - "prob": 0.11402493715286255, - "text": "<" - }, - { - "token": 464, - "prob": 0.05199533700942993, - "text": "The" - }, - { - "token": 1212, - "prob": 0.01731906458735466, - "text": "This" - }, - { - "token": 3556, - "prob": 0.016215169802308083, - "text": "" - }, - { - "token": 361, - "prob": 0.0009765964932739735, - "text": "if" - } - ] - }, - { - "token": 62, - "prob": 0.9997590184211731, - "text": "_", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 62, - "prob": 0.9997590184211731, - "text": "_" - }, - { - "token": 13, - "prob": 0.000022090805941843428, - "text": "." - }, - { - "token": 59, - "prob": 0.000015420928320963867, - "text": "\\" - }, - { - "token": 834, - "prob": 0.000013038138604315463, - "text": "__" - }, - { - "token": 12, - "prob": 0.000011890577297890559, - "text": "-" - } - ] - }, - { - "token": 437, - "prob": 0.7618218064308167, - "text": "end", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 437, - "prob": 0.7618218064308167, - "text": "end" - }, - { - "token": 9688, - "prob": 0.17939522862434387, - "text": "start" - }, - { - "token": 27471, - "prob": 0.00941860768944025, - "text": "begin" - }, - { - "token": 11338, - "prob": 0.005442698486149311, - "text": "stop" - }, - { - "token": 1571, - "prob": 0.0011666559148579836, - "text": "ending" - } - ] - }, - { - "token": 91, - "prob": 0.9977994561195374, - "text": "|", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 91, - "prob": 0.9977994561195374, - "text": "|" - }, - { - "token": 62, - "prob": 0.00038299127481877804, - "text": "_" - }, - { - "token": 15886, - "prob": 0.00029917186475358903, - "text": "||" - }, - { - "token": 29, - "prob": 0.0001353792322333902, - "text": ">" - }, - { - "token": 10, - "prob": 0.00012695405166596174, - "text": "+" - } - ] - }, - { - "token": 29, - "prob": 0.9984844326972961, - "text": ">", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 29, - "prob": 0.9984844326972961, - "text": ">" - }, - { - "token": 60, - "prob": 0.00033915083622559905, - "text": "]" - }, - { - "token": 6927, - "prob": 0.00010037984611699358, - "text": "><" - }, - { - "token": 28, - "prob": 0.00008626521594123915, - "text": "=" - }, - { - "token": 24618, - "prob": 0.00007595126226078719, - "text": ">\"" - } - ] - }, - { - "token": 198, - "prob": 0.5057048797607422, - "text": "\n", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 198, - "prob": 0.5057048797607422, - "text": "\n" - }, - { - "token": 1640, - "prob": 0.21033842861652374, - "text": "for" - }, - { - "token": 10057, - "prob": 0.032438330352306366, - "text": "system" - }, - { - "token": 7220, - "prob": 0.028024563565850258, - "text": "user" - }, - { - "token": 329, - "prob": 0.010914873331785202, - "text": " for" - } - ] - }, - { - "token": 31175, - "prob": 0.0000045710116864938755, - "text": ">:", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 27, - "prob": 0.3989731967449188, - "text": "<" - }, - { - "token": 1639, - "prob": 0.1570923775434494, - "text": "You" - }, - { - "token": 49, - "prob": 0.03772936016321182, - "text": "R" - }, - { - "token": 464, - "prob": 0.027823705226182938, - "text": "The" - }, - { - "token": 3556, - "prob": 0.01715909130871296, - "text": ":" - } - ] - }, - { - "token": 7, - "prob": 0.0029301203321665525, - "text": "(", - "latency_ms": 0, - "is_generated": false, - "is_force_forwarded": false, - "is_input": true, - "top_k": [ - { - "token": 16, - "prob": 0.0514117032289505, - "text": "1" - }, - { - "token": 27, - "prob": 0.03453383222222328, - "text": "<" - }, - { - "token": 15, - "prob": 0.03179513290524483, - "text": "0" - }, - { - "token": 352, - "prob": 0.01785029098391533, - "text": " 1" - }, - { - "token": 198, - "prob": 0.0139352697879076, - "text": "\n" - }, - { - "token": 7, - "prob": 0.0029301203321665525, - "text": "(" - } - ] - } - ]; \ No newline at end of file +export const mockGenTokens: Array = [ + { + "token": 27, + "prob": 1, + "text": "<", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 27, + "prob": 1, + "text": "<", + "is_masked": false + } + ] + }, + { + "token": 91, + "prob": 0.0008722934871912003, + "text": "|", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 198, + "prob": 0.029958423227071762, + "text": "\n", + "is_masked": false + }, + { + "token": 13, + "prob": 0.013489649631083012, + "text": ".", + "is_masked": false + }, + { + "token": 16, + "prob": 0.011806909926235676, + "text": "1", + "is_masked": false + }, + { + "token": 12, + "prob": 0.010169479995965958, + "text": "-", + "is_masked": false + }, + { + "token": 15, + "prob": 0.009271609596908092, + "text": "0", + "is_masked": false + }, + { + "token": 91, + "prob": 0.0008722934871912003, + "text": "|", + "is_masked": false + } + ] + }, + { + "token": 320, + "prob": 0.000027396810764912516, + "text": "im", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 930, + "prob": 0.12004928290843964, + "text": " |", + "is_masked": false + }, + { + "token": 29, + "prob": 0.06939840316772461, + "text": ">", + "is_masked": false + }, + { + "token": 27, + "prob": 0.03129403665661812, + "text": "<", + "is_masked": false + }, + { + "token": 198, + "prob": 0.028110388666391373, + "text": "\n", + "is_masked": false + }, + { + "token": 60, + "prob": 0.02136152982711792, + "text": "]", + "is_masked": false + }, + { + "token": 320, + "prob": 0.000027396810764912516, + "text": "im", + "is_masked": false + } + ] + }, + { + "token": 62, + "prob": 0.01482831034809351, + "text": "_", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.42150357365608215, + "text": "|", + "is_masked": false + }, + { + "token": 7629, + "prob": 0.023308370262384415, + "text": "perial", + "is_masked": false + }, + { + "token": 60, + "prob": 0.020157789811491966, + "text": "]", + "is_masked": false + }, + { + "token": 14, + "prob": 0.018618104979395866, + "text": "/", + "is_masked": false + }, + { + "token": 92, + "prob": 0.015273063443601131, + "text": "}", + "is_masked": false + }, + { + "token": 62, + "prob": 0.01482831034809351, + "text": "_", + "is_masked": false + } + ] + }, + { + "token": 9688, + "prob": 0.0003535318828653544, + "text": "start", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.017649956047534943, + "text": "|", + "is_masked": false + }, + { + "token": 79, + "prob": 0.011138186790049076, + "text": "p", + "is_masked": false + }, + { + "token": 16366, + "prob": 0.011045439168810844, + "text": "client", + "is_masked": false + }, + { + "token": 82, + "prob": 0.008266090415418148, + "text": "s", + "is_masked": false + }, + { + "token": 15908, + "prob": 0.00811094231903553, + "text": "dir", + "is_masked": false + }, + { + "token": 9688, + "prob": 0.0003535318828653544, + "text": "start", + "is_masked": false + } + ] + }, + { + "token": 91, + "prob": 0.12612135708332062, + "text": "|", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 62, + "prob": 0.3673606216907501, + "text": "_", + "is_masked": false + }, + { + "token": 91, + "prob": 0.12612135708332062, + "text": "|", + "is_masked": false + }, + { + "token": 929, + "prob": 0.041732169687747955, + "text": "up", + "is_masked": false + }, + { + "token": 92, + "prob": 0.032134898006916046, + "text": "}", + "is_masked": false + }, + { + "token": 28, + "prob": 0.024743985384702682, + "text": "=", + "is_masked": false + } + ] + }, + { + "token": 29, + "prob": 0.012729871086776257, + "text": ">", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 259, + "prob": 0.028011340647935867, + "text": "in", + "is_masked": false + }, + { + "token": 4023, + "prob": 0.01824311725795269, + "text": "http", + "is_masked": false + }, + { + "token": 27, + "prob": 0.015950094908475876, + "text": "<", + "is_masked": false + }, + { + "token": 929, + "prob": 0.01563503034412861, + "text": "up", + "is_masked": false + }, + { + "token": 29, + "prob": 0.012729871086776257, + "text": ">", + "is_masked": false + } + ] + }, + { + "token": 10057, + "prob": 0.00004459881893126294, + "text": "system", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.2632869482040405, + "text": "|", + "is_masked": false + }, + { + "token": 198, + "prob": 0.05016319826245308, + "text": "\n", + "is_masked": false + }, + { + "token": 1279, + "prob": 0.04930492863059044, + "text": " <", + "is_masked": false + }, + { + "token": 930, + "prob": 0.045030541718006134, + "text": " |", + "is_masked": false + }, + { + "token": 28, + "prob": 0.023192651569843292, + "text": "=", + "is_masked": false + }, + { + "token": 10057, + "prob": 0.00004459881893126294, + "text": "system", + "is_masked": false + } + ] + }, + { + "token": 198, + "prob": 0.01464146375656128, + "text": "\n", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.20154249668121338, + "text": "|", + "is_masked": false + }, + { + "token": 3556, + "prob": 0.11300163716077805, + "text": "", + "is_masked": false + }, + { + "token": 361, + "prob": 0.02362215332686901, + "text": "if", + "is_masked": false + }, + { + "token": 3546, + "prob": 0.019490960985422134, + "text": "Im", + "is_masked": false + }, + { + "token": 930, + "prob": 0.016572270542383194, + "text": " |", + "is_masked": false + } + ] + }, + { + "token": 62, + "prob": 0.9976491332054138, + "text": "_", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 62, + "prob": 0.9976491332054138, + "text": "_", + "is_masked": false + }, + { + "token": 91, + "prob": 0.000336194148985669, + "text": "|", + "is_masked": false + }, + { + "token": 41052, + "prob": 0.00012316853099036962, + "text": "_(", + "is_masked": false + }, + { + "token": 29, + "prob": 0.000117526447866112, + "text": ">", + "is_masked": false + }, + { + "token": 59, + "prob": 0.00009838600090006366, + "text": "\\", + "is_masked": false + } + ] + }, + { + "token": 437, + "prob": 0.4462008774280548, + "text": "end", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 437, + "prob": 0.4462008774280548, + "text": "end", + "is_masked": false + }, + { + "token": 9688, + "prob": 0.09380462765693665, + "text": "start", + "is_masked": false + }, + { + "token": 12957, + "prob": 0.017503555864095688, + "text": "last", + "is_masked": false + }, + { + "token": 11338, + "prob": 0.016530489549040794, + "text": "stop", + "is_masked": false + }, + { + "token": 27471, + "prob": 0.012605799362063408, + "text": "begin", + "is_masked": false + } + ] + }, + { + "token": 91, + "prob": 0.9823351502418518, + "text": "|", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.9823351502418518, + "text": "|", + "is_masked": false + }, + { + "token": 29, + "prob": 0.002384455408900976, + "text": ">", + "is_masked": false + }, + { + "token": 60, + "prob": 0.0023481370881199837, + "text": "]", + "is_masked": false + }, + { + "token": 15886, + "prob": 0.002319696359336376, + "text": "||", + "is_masked": false + }, + { + "token": 930, + "prob": 0.0013476606691256166, + "text": " |", + "is_masked": false + } + ] + }, + { + "token": 29, + "prob": 0.9560039639472961, + "text": ">", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 29, + "prob": 0.9560039639472961, + "text": ">", + "is_masked": false + }, + { + "token": 6927, + "prob": 0.005681615322828293, + "text": "><", + "is_masked": false + }, + { + "token": 60, + "prob": 0.0032080409582704306, + "text": "]", + "is_masked": false + }, + { + "token": 27, + "prob": 0.002467683283612132, + "text": "<", + "is_masked": false + }, + { + "token": 4211, + "prob": 0.0021098603028804064, + "text": ">>", + "is_masked": false + } + ] + }, + { + "token": 198, + "prob": 0.02139684557914734, + "text": "\n", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 10057, + "prob": 0.35756662487983704, + "text": "system", + "is_masked": false + }, + { + "token": 198, + "prob": 0.02139684557914734, + "text": "\n", + "is_masked": false + }, + { + "token": 11964, + "prob": 0.01934202015399933, + "text": "System", + "is_masked": false + }, + { + "token": 1662, + "prob": 0.010047300718724728, + "text": "not", + "is_masked": false + }, + { + "token": 1169, + "prob": 0.006138301454484463, + "text": "the", + "is_masked": false + } + ] + }, + { + "token": 27, + "prob": 0.039419274777173996, + "text": "<", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 1639, + "prob": 0.1665498912334442, + "text": "You", + "is_masked": false + }, + { + "token": 464, + "prob": 0.06005862355232239, + "text": "The", + "is_masked": false + }, + { + "token": 27, + "prob": 0.039419274777173996, + "text": "<", + "is_masked": false + }, + { + "token": 1212, + "prob": 0.027387971058487892, + "text": "This", + "is_masked": false + }, + { + "token": 1532, + "prob": 0.022758493199944496, + "text": "If", + "is_masked": false + } + ] + }, + { + "token": 91, + "prob": 0.7559300065040588, + "text": "|", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.7559300065040588, + "text": "|", + "is_masked": false + }, + { + "token": 320, + "prob": 0.006860977970063686, + "text": "im", + "is_masked": false + }, + { + "token": 15886, + "prob": 0.0064566307701170444, + "text": "||", + "is_masked": false + }, + { + "token": 1671, + "prob": 0.004361273255199194, + "text": "br", + "is_masked": false + }, + { + "token": 930, + "prob": 0.004342366941273212, + "text": " |", + "is_masked": false + } + ] + }, + { + "token": 320, + "prob": 0.8291174173355103, + "text": "im", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 320, + "prob": 0.8291174173355103, + "text": "im", + "is_masked": false + }, + { + "token": 3546, + "prob": 0.012388699688017368, + "text": "Im", + "is_masked": false + }, + { + "token": 361, + "prob": 0.007399916183203459, + "text": "if", + "is_masked": false + }, + { + "token": 72, + "prob": 0.004467112943530083, + "text": "i", + "is_masked": false + }, + { + "token": 29, + "prob": 0.0026658582501113415, + "text": ">", + "is_masked": false + } + ] + }, + { + "token": 62, + "prob": 0.9993433356285095, + "text": "_", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 62, + "prob": 0.9993433356285095, + "text": "_", + "is_masked": false + }, + { + "token": 7, + "prob": 0.0000683960533933714, + "text": "(", + "is_masked": false + }, + { + "token": 59, + "prob": 0.00006206566467881203, + "text": "\\", + "is_masked": false + }, + { + "token": 13, + "prob": 0.00004414364229887724, + "text": ".", + "is_masked": false + }, + { + "token": 29, + "prob": 0.00002257493724755477, + "text": ">", + "is_masked": false + } + ] + }, + { + "token": 9688, + "prob": 0.6440587043762207, + "text": "start", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 9688, + "prob": 0.6440587043762207, + "text": "start", + "is_masked": false + }, + { + "token": 437, + "prob": 0.05475924164056778, + "text": "end", + "is_masked": false + }, + { + "token": 27471, + "prob": 0.043713200837373734, + "text": "begin", + "is_masked": false + }, + { + "token": 11338, + "prob": 0.003659052774310112, + "text": "stop", + "is_masked": false + }, + { + "token": 38690, + "prob": 0.003096950938925147, + "text": "starting", + "is_masked": false + } + ] + }, + { + "token": 91, + "prob": 0.9499432444572449, + "text": "|", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.9499432444572449, + "text": "|", + "is_masked": false + }, + { + "token": 62, + "prob": 0.00848131813108921, + "text": "_", + "is_masked": false + }, + { + "token": 15886, + "prob": 0.005286256782710552, + "text": "||", + "is_masked": false + }, + { + "token": 930, + "prob": 0.003634629538282752, + "text": " |", + "is_masked": false + }, + { + "token": 29, + "prob": 0.0032877251505851746, + "text": ">", + "is_masked": false + } + ] + }, + { + "token": 29, + "prob": 0.9690060615539551, + "text": ">", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 29, + "prob": 0.9690060615539551, + "text": ">", + "is_masked": false + }, + { + "token": 6927, + "prob": 0.004052347969263792, + "text": "><", + "is_masked": false + }, + { + "token": 24618, + "prob": 0.0019232694758102298, + "text": ">\"", + "is_masked": false + }, + { + "token": 27, + "prob": 0.0012727173743769526, + "text": "<", + "is_masked": false + }, + { + "token": 4211, + "prob": 0.0011409870348870754, + "text": ">>", + "is_masked": false + } + ] + }, + { + "token": 7220, + "prob": 0.003625249955803156, + "text": "user", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 10057, + "prob": 0.43270590901374817, + "text": "system", + "is_masked": false + }, + { + "token": 11964, + "prob": 0.012400631792843342, + "text": "System", + "is_masked": false + }, + { + "token": 9688, + "prob": 0.008726297877728939, + "text": "start", + "is_masked": false + }, + { + "token": 847, + "prob": 0.007208186201751232, + "text": "other", + "is_masked": false + }, + { + "token": 198, + "prob": 0.006247976794838905, + "text": "\n", + "is_masked": false + }, + { + "token": 7220, + "prob": 0.003625249955803156, + "text": "user", + "is_masked": false + } + ] + }, + { + "token": 198, + "prob": 0.5544214248657227, + "text": "\n", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 198, + "prob": 0.5544214248657227, + "text": "\n", + "is_masked": false + }, + { + "token": 62, + "prob": 0.04264130815863609, + "text": "_", + "is_masked": false + }, + { + "token": 12, + "prob": 0.029624110087752342, + "text": "-", + "is_masked": false + }, + { + "token": 29, + "prob": 0.014048474840819836, + "text": ">", + "is_masked": false + }, + { + "token": 14, + "prob": 0.011965525336563587, + "text": "/", + "is_masked": false + } + ] + }, + { + "token": 49, + "prob": 0.00022193520271684974, + "text": "R", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 1639, + "prob": 0.39992958307266235, + "text": "You", + "is_masked": false + }, + { + "token": 27, + "prob": 0.11402493715286255, + "text": "<", + "is_masked": false + }, + { + "token": 464, + "prob": 0.05199533700942993, + "text": "The", + "is_masked": false + }, + { + "token": 1212, + "prob": 0.01731906458735466, + "text": "This", + "is_masked": false + }, + { + "token": 3556, + "prob": 0.016215169802308083, + "text": "", + "is_masked": false + }, + { + "token": 361, + "prob": 0.0009765964932739735, + "text": "if", + "is_masked": false + } + ] + }, + { + "token": 62, + "prob": 0.9997590184211731, + "text": "_", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 62, + "prob": 0.9997590184211731, + "text": "_", + "is_masked": false + }, + { + "token": 13, + "prob": 0.000022090805941843428, + "text": ".", + "is_masked": false + }, + { + "token": 59, + "prob": 0.000015420928320963867, + "text": "\\", + "is_masked": false + }, + { + "token": 834, + "prob": 0.000013038138604315463, + "text": "__", + "is_masked": false + }, + { + "token": 12, + "prob": 0.000011890577297890559, + "text": "-", + "is_masked": false + } + ] + }, + { + "token": 437, + "prob": 0.7618218064308167, + "text": "end", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 437, + "prob": 0.7618218064308167, + "text": "end", + "is_masked": false + }, + { + "token": 9688, + "prob": 0.17939522862434387, + "text": "start", + "is_masked": false + }, + { + "token": 27471, + "prob": 0.00941860768944025, + "text": "begin", + "is_masked": false + }, + { + "token": 11338, + "prob": 0.005442698486149311, + "text": "stop", + "is_masked": false + }, + { + "token": 1571, + "prob": 0.0011666559148579836, + "text": "ending", + "is_masked": false + } + ] + }, + { + "token": 91, + "prob": 0.9977994561195374, + "text": "|", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 91, + "prob": 0.9977994561195374, + "text": "|", + "is_masked": false + }, + { + "token": 62, + "prob": 0.00038299127481877804, + "text": "_", + "is_masked": false + }, + { + "token": 15886, + "prob": 0.00029917186475358903, + "text": "||", + "is_masked": false + }, + { + "token": 29, + "prob": 0.0001353792322333902, + "text": ">", + "is_masked": false + }, + { + "token": 10, + "prob": 0.00012695405166596174, + "text": "+", + "is_masked": false + } + ] + }, + { + "token": 29, + "prob": 0.9984844326972961, + "text": ">", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 29, + "prob": 0.9984844326972961, + "text": ">", + "is_masked": false + }, + { + "token": 60, + "prob": 0.00033915083622559905, + "text": "]", + "is_masked": false + }, + { + "token": 6927, + "prob": 0.00010037984611699358, + "text": "><", + "is_masked": false + }, + { + "token": 28, + "prob": 0.00008626521594123915, + "text": "=", + "is_masked": false + }, + { + "token": 24618, + "prob": 0.00007595126226078719, + "text": ">\"", + "is_masked": false + } + ] + }, + { + "token": 198, + "prob": 0.5057048797607422, + "text": "\n", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 198, + "prob": 0.5057048797607422, + "text": "\n", + "is_masked": false + }, + { + "token": 1640, + "prob": 0.21033842861652374, + "text": "for", + "is_masked": false + }, + { + "token": 10057, + "prob": 0.032438330352306366, + "text": "system", + "is_masked": false + }, + { + "token": 7220, + "prob": 0.028024563565850258, + "text": "user", + "is_masked": false + }, + { + "token": 329, + "prob": 0.010914873331785202, + "text": " for", + "is_masked": false + } + ] + }, + { + "token": 31175, + "prob": 0.0000045710116864938755, + "text": ">:", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 27, + "prob": 0.3989731967449188, + "text": "<", + "is_masked": false + }, + { + "token": 1639, + "prob": 0.1570923775434494, + "text": "You", + "is_masked": false + }, + { + "token": 49, + "prob": 0.03772936016321182, + "text": "R", + "is_masked": false + }, + { + "token": 464, + "prob": 0.027823705226182938, + "text": "The", + "is_masked": false + }, + { + "token": 3556, + "prob": 0.01715909130871296, + "text": ":", + "is_masked": false + } + ] + }, + { + "token": 7, + "prob": 0.0029301203321665525, + "text": "(", + "is_masked": false, + "latency_ms": 0, + "is_generated": false, + "is_force_forwarded": false, + "is_input": true, + "top_k": [ + { + "token": 16, + "prob": 0.0514117032289505, + "text": "1", + "is_masked": false + }, + { + "token": 27, + "prob": 0.03453383222222328, + "text": "<", + "is_masked": false + }, + { + "token": 15, + "prob": 0.03179513290524483, + "text": "0", + "is_masked": false + }, + { + "token": 352, + "prob": 0.01785029098391533, + "text": " 1", + "is_masked": false + }, + { + "token": 198, + "prob": 0.0139352697879076, + "text": "\n", + "is_masked": false + }, + { + "token": 7, + "prob": 0.0029301203321665525, + "text": "(", + "is_masked": false + } + ] + } +]; \ No newline at end of file From bd88ede867ef5333c6dc49de9de44368d746d7cf Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Tue, 15 Oct 2024 13:35:23 -0700 Subject: [PATCH 073/133] refactor get_per_token_stats function --- guidance/models/_model.py | 41 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index eebb6948b..f8e9a5390 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -1278,18 +1278,19 @@ def get_per_token_stats(self) -> list[GenToken]: gen_tokens_indices.append(len(gen_tokens_lats) - 1) text = self._state - tokens = self.engine.tokenizer.encode(text.encode("utf-8")) + token_ids = self.engine.tokenizer.encode(text.encode("utf-8")) + token_texts: list[str] = [] + for idx in range(len(token_ids)): + token_texts.append(self.engine.tokenizer.decode([token_ids[idx]]).decode("utf-8")) # NOTE (loc): Not all engines support the get_token_probs method try: - probs = self.engine.get_token_probs(tokens) + probs = self.engine.get_token_probs(token_ids) except Exception as e: # FIXME (loc): assume prob 1.0 for all tokens - probs = [1.0] * len(tokens) - - tokens_texts: list[str] = [] - for idx in range(len(tokens)): - tokens_texts.append(self.engine.tokenizer.decode([tokens[idx]]).decode("utf-8")) + probs = [] + for token_id, token_text in zip(token_ids, token_texts): + probs.append([BaseGenToken(token=token_id, prob=1.0, text=token_text)]) start_idx = 0 end_idx = 1 @@ -1303,14 +1304,15 @@ def get_per_token_stats(self) -> list[GenToken]: if not vis_text: continue + # Find the chunk starting at start_idx that contains the vis_text end_idx = start_idx - _chunk = "".join(tokens_texts[start_idx : end_idx + 1]) - while vis_text not in _chunk and end_idx < len(tokens_texts): + _chunk = "".join(token_texts[start_idx : end_idx + 1]) + while vis_text not in _chunk and end_idx < len(token_texts): # expand the chunk end_idx += 1 - _chunk = "".join(tokens_texts[start_idx : end_idx + 1]) + _chunk = "".join(token_texts[start_idx : end_idx + 1]) - if vis_text not in _chunk and end_idx >= len(tokens_texts): + if vis_text not in _chunk and end_idx >= len(token_texts): # failed = True # break raise Exception(f"Failed to find the {vis_text} in the tokens chunk {_chunk}") @@ -1328,24 +1330,24 @@ def get_per_token_stats(self) -> list[GenToken]: # we should not issue that token for now end_idx -= 1 - real_chunk_tokens = tokens[start_idx : end_idx + 1] - real_chunk_probs = probs[start_idx : end_idx + 1] + _chunk_token_ids = token_ids[start_idx : end_idx + 1] + _chunk_probs = probs[start_idx : end_idx + 1] is_input = len(vis_chunk.input_tokens) > 0 is_force_forwarded = len(vis_chunk.force_forwarded_tokens) > 0 _gen_tokens: list[GenToken] = [] - for token, top_k_prob in zip(real_chunk_tokens, real_chunk_probs): + for token_id, top_k_prob in zip(_chunk_token_ids, _chunk_probs): prob = -1 for _token in top_k_prob: - if _token.token == token: + if _token.token == token_id: prob = _token.prob break _gen_token = GenToken( - token=token, + token=token_id, prob=prob, - text=self.engine.tokenizer.decode([token]).decode("utf-8"), + text=self.engine.tokenizer.decode([token_id]).decode("utf-8"), latency_ms=0, is_input=is_input, is_generated=False, @@ -1362,6 +1364,8 @@ def get_per_token_stats(self) -> list[GenToken]: if is_force_forwarded: _gen_token.is_force_forwarded = True + # Start from the end of current chunk + # go backwards to find the match between token and associated text string found_perfect_match = False max_idx = gen_tokens_indices[vis_chunk_idx] for idx in range(max_idx, -1, -1): @@ -1383,6 +1387,9 @@ def get_per_token_stats(self) -> list[GenToken]: found_perfect_match = True break + # NOTE (loc): There are cases that the generated token and issued token are not matched + # for example, the engine may issue token "pl" but the parser decides to generate token "plate" due to the constraints + # To mitigate the issue, we narrow down the search space to find the text that may contain the generated token if not found_perfect_match: # only search within this chunk max_idx = gen_tokens_indices[vis_chunk_idx] From 153846ed26f1f78e35d74da67776b29f629e2f6e Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 15 Oct 2024 15:14:01 -0700 Subject: [PATCH 074/133] Fix for client hang. --- client/graphpaper-inline/src/App.svelte | 2 +- client/graphpaper-inline/src/TokenGrid.svelte | 29 ++++++++++++------- guidance/models/_model.py | 1 + guidance/resources/graphpaper-inline.html | 4 +-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 5313cc5eb..3843ce092 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -65,9 +65,9 @@ } else if (isExecutionCompletedMessage(msg)) { completedExecution = true; } else if (isExecutionCompletedOutputMessage(msg)) { - tokenDetails = msg.tokens; console.log(textComponents); console.log(msg.tokens); + tokenDetails = msg.tokens; } textComponents = textComponents; } diff --git a/client/graphpaper-inline/src/TokenGrid.svelte b/client/graphpaper-inline/src/TokenGrid.svelte index 815f56074..faea41284 100644 --- a/client/graphpaper-inline/src/TokenGrid.svelte +++ b/client/graphpaper-inline/src/TokenGrid.svelte @@ -43,15 +43,25 @@ } let tokens: Array = []; + let activeOpenerRoles: Array = []; + let activeCloserRoleText: Array = []; + let specialSet: Set = new Set(); + let namedRoleSet: Record = {}; + let currentTokenIndex: number = 0; $: { - let activeOpenerRoles: Array = []; - let activeCloserRoleText: Array = []; + if (textComponents.length === 0) { + // Reset + tokens = []; + activeOpenerRoles = []; + activeCloserRoleText = []; + specialSet.clear(); + namedRoleSet = {}; + currentTokenIndex = 0; + } - let specialSet: Set = new Set(); - let namedRoleSet: Record = {}; + for (; currentTokenIndex < textComponents.length; currentTokenIndex += 1) { + const nodeAttr = textComponents[currentTokenIndex]; - tokens = []; - for (let nodeAttr of textComponents) { if (isRoleOpenerInput(nodeAttr)) { activeOpenerRoles.push(nodeAttr); activeCloserRoleText.push(nodeAttr.closer_text || ""); @@ -87,7 +97,7 @@ // console.log("Opener and closer role texts did not balance.") } - // Process tokens to have detail if we have it + // Process tokens to have detail if we have it (should only happen once at the end). const isDetailed = (tokenDetails.length > 0); if (isDetailed) { // Preprocess for special words @@ -112,6 +122,8 @@ let value = specialMatchStack.shift(); if (value !== undefined) { [matchStart, matchEnd, match] = value; + } else { + break; } } @@ -141,9 +153,6 @@ } } - // const role = Object.keys(namedRoleSet).includes(tokenDetail.text) ? namedRoleSet[tokenDetail.text] : ""; - // const special = specialSet.has(tokenDetail.text); - const token = { text: tokenDetail.text, prob: tokenDetail.prob, diff --git a/guidance/models/_model.py b/guidance/models/_model.py index eebb6948b..cf97d9c8f 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -216,6 +216,7 @@ def _msg_recv(self, message: GuidanceMessage) -> None: self.renderer.update(message) failed = False + processed_gen_tokens: list[GenToken] = [] # suppress IDE warnings by definition try: processed_gen_tokens = last_model.get_per_token_stats() except Exception as e: diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index f576300b3..d6dabfa2e 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,8 +9,8 @@ From a24c73e0cb1e6da532caf35fd2e2ea8cae4ffebf Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 15 Oct 2024 15:42:49 -0700 Subject: [PATCH 075/133] Client should be able to take array metric messages. --- client/graphpaper-inline/src/App.svelte | 9 ++++++--- guidance/resources/graphpaper-inline.html | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index 3843ce092..a27ccb8ba 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -46,7 +46,6 @@ } else if (isResetDisplayMessage(msg)) { textComponents = []; } else if (isMetricMessage(msg)) { - // TODO(nopdive): Move aggregation to server-side. const name = msg.name; const value = msg.value; @@ -54,8 +53,12 @@ let currVal = metrics[name]; const metricDef = metricDefs[name]; if (metricDef.isScalar === false) { - currVal = currVal as Array; - metrics[name] = [...currVal.slice(1), value as string | number]; + if (value.constructor === Array) { + metrics[name] = value; + } else { + currVal = currVal as Array; + metrics[name] = [...currVal.slice(1), value as string | number]; + } } else if (metricDef.isScalar === true) { metrics[name] = value; } else { diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index d6dabfa2e..926becca8 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -10,7 +10,7 @@ From 2205eca2dbe81c42e30d74a31ad78e5f75f7d4ea Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Tue, 15 Oct 2024 15:55:23 -0700 Subject: [PATCH 076/133] Removed mock inputs. --- client/graphpaper-inline/src/App.svelte | 5 ++--- guidance/resources/graphpaper-inline.html | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index a27ccb8ba..a3b2eeeb8 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -29,8 +29,8 @@ let completedExecution: boolean = false; let mode: string; - textComponents = mockNodeAttrs; - tokenDetails = mockGenTokens; + // textComponents = mockNodeAttrs; + // tokenDetails = mockGenTokens; $: if ($kernelmsg !== undefined) { if ($kernelmsg.content !== '') { @@ -76,7 +76,6 @@ } } - // TODO(nopdive): Restrict metrics while updating style. const metricDefs: Record = { 'status': { name: 'status', diff --git a/guidance/resources/graphpaper-inline.html b/guidance/resources/graphpaper-inline.html index 926becca8..84c1da72f 100644 --- a/guidance/resources/graphpaper-inline.html +++ b/guidance/resources/graphpaper-inline.html @@ -9,8 +9,8 @@ From 11f42625ded908a7ec089abe78b6bae35c036d61 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Tue, 15 Oct 2024 16:34:37 -0700 Subject: [PATCH 077/133] Improve visualization for generated tokens --- guidance/models/_model.py | 10 ++++++++++ guidance/visual/_trace.py | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index f8e9a5390..bfed6fb32 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -1372,6 +1372,11 @@ def get_per_token_stats(self) -> list[GenToken]: if _gen_token.token == gen_tokens_lats[idx][0]: _gen_token.latency_ms = gen_tokens_lats[idx][1] _masked_top_k = gen_tokens_lats[idx][2] + + # if we find a match, then this token should be marked as generated + _gen_token.is_generated = True + _gen_token.is_force_forwarded = False + if _masked_top_k is None: # in free accepting state, no masking for _token in _gen_token.top_k: @@ -1405,6 +1410,11 @@ def get_per_token_stats(self) -> list[GenToken]: ): _gen_token.latency_ms = gen_tokens_lats[idx][1] _masked_top_k = gen_tokens_lats[idx][2] + + # if we find a match, then this token should be marked as generated + _gen_token.is_generated = True + _gen_token.is_force_forwarded = False + if _masked_top_k is None: # in free accepting state, no masking for _token in _gen_token.top_k: diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index af1a077eb..3a0513621 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -90,9 +90,9 @@ def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: Exec latency = f"{complete_msg.tokens[prob_idx].latency_ms:.2f}" - if attr.is_generated: + if complete_msg.tokens[prob_idx].is_generated: fmt += f"{html.escape(token_str)}" - elif attr.is_force_forwarded: + elif complete_msg.tokens[prob_idx].is_force_forwarded: fmt += f"{html.escape(token_str)}" else: fmt += f"{html.escape(token_str)}" From f5f22a6b96036a7e02c24695719b9fc5cacb08f1 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Tue, 15 Oct 2024 16:44:21 -0700 Subject: [PATCH 078/133] Add warning if gpustat is not installed --- guidance/models/_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 1ccf6a369..f3160e50b 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -1620,7 +1620,7 @@ def _monitor_fn( # only collect GPU stats if there is at least one GPU to_collect_gpu_stats = True except: - pass + logger.warning("gpustat is not installed, run `pip install gpustat` to collect GPU stats.") try: while not stop_flag.value: From d8f431b7a04c29815b94915bc8d2d47d47fe6759 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 16 Oct 2024 12:15:55 -0700 Subject: [PATCH 079/133] Remove unused fields in VisBytesChunk --- guidance/_schema.py | 4 ---- guidance/models/_model.py | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/guidance/_schema.py b/guidance/_schema.py index c59aedfbb..c0d8c3cfc 100644 --- a/guidance/_schema.py +++ b/guidance/_schema.py @@ -32,7 +32,6 @@ class EngineCallResponse(BaseModel): class BaseGenToken(BaseModel): token: int prob: float - # bytes: bytes text: str = "" is_masked: bool = False @@ -56,11 +55,8 @@ class EngineOutput(BaseModel): class VisBytesChunk(BaseModel): bytes: bytes is_input: bool = False - input_bytes: bytes = b"" input_tokens: list[GenToken] = [] - generated_bytes: bytes = b"" generated_tokens: list[GenToken] = [] - force_forwarded_bytes: bytes = b"" force_forwarded_tokens: list["GenToken"] = [] backtrack: NonNegativeInt = 0 engine_outputs: list[EngineOutput] = [] diff --git a/guidance/models/_model.py b/guidance/models/_model.py index f3160e50b..611250a46 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -836,7 +836,6 @@ def __add__(self, value): out.vis_chunk = VisBytesChunk( bytes=_bytes, is_input=True, - input_bytes=_bytes, input_tokens=[ GenToken( token=_token, @@ -1166,9 +1165,8 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): lm.vis_chunk = VisBytesChunk( bytes=chunk.new_bytes, is_input=False, - generated_bytes=chunk.generated_bytes, + # generated_bytes=chunk.generated_bytes, generated_tokens=chunk.generated_tokens, - force_forwarded_bytes=chunk.force_forwarded_bytes, force_forwarded_tokens=chunk.force_forwarded_tokens, backtrack=chunk.backtrack, engine_outputs=chunk.engine_outputs, @@ -1176,8 +1174,6 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): else: # append to existing VisBytesChunk lm.vis_chunk.bytes += chunk.new_bytes - lm.vis_chunk.generated_bytes += chunk.generated_bytes - lm.vis_chunk.force_forwarded_bytes += chunk.force_forwarded_bytes lm.vis_chunk.backtrack += chunk.backtrack lm.vis_chunk.engine_outputs += chunk.engine_outputs From a71aa3e24e5ca8a8b4ca105ac997bc27424372b4 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 16 Oct 2024 13:11:42 -0700 Subject: [PATCH 080/133] 1) rename get_top_k_probs into get_per_token_topk_probs 2) support non-zero temperature in get_next_top_k_tokens --- guidance/models/_model.py | 26 +++++++-- guidance/models/llama_cpp/_llama_cpp.py | 48 +++++++--------- guidance/models/transformers/_transformers.py | 57 +++++++++++-------- 3 files changed, 75 insertions(+), 56 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 611250a46..cabf12324 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -387,7 +387,6 @@ def get_top_k(_probs: np.ndarray, _k: int = 5) -> list[GenToken]: engine_list = [] unseen_tokens = token_ids[-len(probs) :][1:] - # for _probs, _logits in zip(probs, logits): # we're missing the very first token if len(token_ids) == len(probs): @@ -424,7 +423,23 @@ def get_top_k(_probs: np.ndarray, _k: int = 5) -> list[GenToken]: ) masked_top_k = get_top_k(masked_probs, k) - issued_token = masked_top_k[0] if len(masked_top_k) > 0 else top_k[0] + if temperature < 0.0001: + issued_token = masked_top_k[0] if len(masked_top_k) > 0 else top_k[0] + else: + # we need to sample from the probabilities + if mask is None: + sampled_index = np.random.choice(len(_probs), p=_probs) + else: + sampled_index = np.random.choice(len(masked_probs), p=masked_probs) + + issued_token = GenToken( + token=sampled_index, + prob=_probs[sampled_index], + text=self.tokenizer.decode([sampled_index]).decode("utf-8"), + latency_ms=lat_ms, + is_generated=True, + ) + if i < len(unseen_tokens): token = unseen_tokens[i] issued_token = GenToken( @@ -459,7 +474,10 @@ def get_next_token( def get_logits(self, token_ids: list[int]) -> np.ndarray: raise NotImplementedError - def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[BaseGenToken]]: + def get_per_token_topk_probs( + self, token_ids: list[int], top_k: int = 5 + ) -> list[list[BaseGenToken]]: + """Get the top-k probabilities for each token in the sequence.""" raise NotImplementedError def sample_with_temperature( @@ -1282,7 +1300,7 @@ def get_per_token_stats(self) -> list[GenToken]: # NOTE (loc): Not all engines support the get_token_probs method try: - probs = self.engine.get_token_probs(token_ids) + probs = self.engine.get_per_token_topk_probs(token_ids) except Exception as e: # FIXME (loc): assume prob 1.0 for all tokens probs = [] diff --git a/guidance/models/llama_cpp/_llama_cpp.py b/guidance/models/llama_cpp/_llama_cpp.py index e33dda982..40d81540e 100644 --- a/guidance/models/llama_cpp/_llama_cpp.py +++ b/guidance/models/llama_cpp/_llama_cpp.py @@ -218,11 +218,13 @@ def get_logits(self, token_ids): self._cached_logits = logits return logits - - def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[BaseGenToken]]: + + def get_per_token_topk_probs( + self, token_ids: list[int], top_k: int = 5 + ) -> list[list[BaseGenToken]]: if len(token_ids) == 0: return [] - + # clear kv-cache llama_cpp.llama_kv_cache_seq_rm(self.model_obj.ctx, -1, 0, -1) @@ -246,7 +248,7 @@ def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[Bas ret = llama_cpp.llama_decode(self.model_obj.ctx, batch) if ret != 0: raise Exception(f"Call to llama_cpp.llama_decode returned {ret}.") - + # get all the logits if llama_cpp.__version__ < "0.2.58": logits = llama_cpp.llama_get_logits(self.model_obj.ctx) @@ -264,18 +266,12 @@ def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[Bas # add 1st token _bytes = self.tokenizer.decode([token_ids[0]]) try: - _text = _bytes.decode('utf-8') + _text = _bytes.decode("utf-8") except Exception as e: _text = str(_bytes) print(f"Failed to decode token: {token_ids[0]}, error: {e}, _bytes: {str(_bytes)}") - text_sequence.append( - [BaseGenToken( - token=token_ids[0], - prob=1.0, - text=_text - )] - ) - + text_sequence.append([BaseGenToken(token=token_ids[0], prob=1.0, text=_text)]) + for token_idx, logits in zip(token_ids[1:], logits_batch[:-1]): _probs = self._softmax(logits) @@ -289,39 +285,35 @@ def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[Bas for _token_idx, _prob in zip(top_k_indices, top_k_probs): _text = "" try: - _text = self.tokenizer.decode([_token_idx]).decode('utf-8') + _text = self.tokenizer.decode([_token_idx]).decode("utf-8") except Exception as e: _bytes = self.tokenizer.decode([_token_idx]) _text = str(_bytes) - print(f"Failed to decode token: {_token_idx}, error: {e}, _bytes: {str(_bytes)}") - top_k_list.append( - BaseGenToken( - token=_token_idx, - prob=_prob, - text=_text + print( + f"Failed to decode token: {_token_idx}, error: {e}, _bytes: {str(_bytes)}" ) - ) - + top_k_list.append(BaseGenToken(token=_token_idx, prob=_prob, text=_text)) + text_sequence.append(top_k_list) return text_sequence - + def _softmax(self, x) -> np.ndarray: - return(np.exp(x - np.max(x)) / np.exp(x - np.max(x)).sum()) - + return np.exp(x - np.max(x)) / np.exp(x - np.max(x)).sum() + def _top_k(self, input, k, axis=None, ascending=True): if not ascending: input *= -1 ind = np.argpartition(input, k, axis=axis) - ind = np.take(ind, np.arange(k), axis=axis) # k non-sorted indices - input = np.take_along_axis(input, ind, axis=axis) # k non-sorted values + ind = np.take(ind, np.arange(k), axis=axis) # k non-sorted indices + input = np.take_along_axis(input, ind, axis=axis) # k non-sorted values # sort within k elements ind_part = np.argsort(input, axis=axis) ind = np.take_along_axis(ind, ind_part, axis=axis) if not ascending: input *= -1 - val = np.take_along_axis(input, ind_part, axis=axis) + val = np.take_along_axis(input, ind_part, axis=axis) return ind, val diff --git a/guidance/models/transformers/_transformers.py b/guidance/models/transformers/_transformers.py index 2d398f384..30155105c 100644 --- a/guidance/models/transformers/_transformers.py +++ b/guidance/models/transformers/_transformers.py @@ -37,12 +37,15 @@ "trust_remote_code", ] + class ByteDecoderError(Exception): pass + class ByteTokensError(Exception): pass + class TransformersTokenizer(Tokenizer): def __init__( self, @@ -106,10 +109,14 @@ def _tokenizer(self, model: str, **kwargs) -> tuple[ raise except ByteTokensError as e: # Give a specific warning for ByteTokensError and fall back to fast tokenizer - warnings.warn(f"Falling back to fast tokenizer. Could not build byte tokens for model {model!r} due to exception {e.__class__.__name__}: {e}") + warnings.warn( + f"Falling back to fast tokenizer. Could not build byte tokens for model {model!r} due to exception {e.__class__.__name__}: {e}" + ) except Exception as e: # Fall back for other exceptions - warnings.warn(f"Falling back to fast tokenizer. Could not load tokenizer for model {model!r} due to exception {e.__class__.__name__}: {e}") + warnings.warn( + f"Falling back to fast tokenizer. Could not load tokenizer for model {model!r} due to exception {e.__class__.__name__}: {e}" + ) else: return tokenizer, byte_tokens @@ -141,7 +148,9 @@ def _byte_tokens( ) pass else: - return self._byte_tokens_from_byte_decoder(transformers_tokenizer.byte_decoder, transformers_tokenizer) + return self._byte_tokens_from_byte_decoder( + transformers_tokenizer.byte_decoder, transformers_tokenizer + ) if hasattr(transformers_tokenizer, "sp_model"): return self._byte_tokens_from_sp_model(transformers_tokenizer) @@ -156,9 +165,7 @@ def _byte_tokens( fallback_byte_decoder = self._fallback_byte_decoder() try: - self._check_byte_decoder( - fallback_byte_decoder, transformers_tokenizer - ) + self._check_byte_decoder(fallback_byte_decoder, transformers_tokenizer) except ByteDecoderError as e: # Should be the only exception that is raised in _byte_tokens raise ByteTokensError( @@ -232,7 +239,9 @@ def _byte_tokens_by_encoding_token_strings( token_str = transformers_tokenizer.convert_tokens_to_string([token]) encoded_str = transformers_tokenizer.encode(token_str) if len(encoded_str) != 1: - raise ValueError(f"Round-trip encoding of tokens [{token}] failed! Got {encoded_str}") + raise ValueError( + f"Round-trip encoding of tokens [{token}] failed! Got {encoded_str}" + ) roundtrip_id = encoded_str[0] if roundtrip_id == i: byte_coded = token_str.encode() @@ -248,7 +257,7 @@ def _byte_tokens_by_encoding_token_strings( def _fallback_byte_decoder(self) -> dict[str, int]: byte_decoder = transformers_package.AutoTokenizer.from_pretrained( "gpt2", use_fast=False - ).byte_decoder # fall back to gpt2 mapping + ).byte_decoder # fall back to gpt2 mapping # some special tokens may not have their whitespace encoded... byte_decoder[" "] = 32 @@ -295,8 +304,10 @@ def check_byte_decoder_complex_round_trip() -> None: # if it's at the start of the reconstructed bytes # Some tokenizers add this automatically as part of the call function, so # we need to remove it to compare - if hasattr(transformers_tokenizer, "bos_token") and transformers_tokenizer.bos_token and reconstructed.startswith( - transformers_tokenizer.bos_token.encode() + if ( + hasattr(transformers_tokenizer, "bos_token") + and transformers_tokenizer.bos_token + and reconstructed.startswith(transformers_tokenizer.bos_token.encode()) ): reconstructed = reconstructed[len(transformers_tokenizer.bos_token) :] # TODO: can we narrow this exception? @@ -516,8 +527,10 @@ def get_logits(self, token_ids): self.metrics.engine_output_tokens += 1 return self._cached_logits - - def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[BaseGenToken]]: + + def get_per_token_topk_probs( + self, token_ids: list[int], top_k: int = 5 + ) -> list[list[BaseGenToken]]: tokenizer = self.tokenizer._orig_tokenizer # NOTE (loc) - assume batch size of 1 @@ -541,11 +554,13 @@ def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[Bas if len(text_sequence) == 0: text_sequence.append( - [BaseGenToken( - token=_token_id.item(), - prob=1.0, - text=tokenizer.decode([_token_id]) - )] + [ + BaseGenToken( + token=_token_id.item(), + prob=1.0, + text=tokenizer.decode([_token_id]), + ) + ] ) continue @@ -557,13 +572,7 @@ def get_token_probs(self, token_ids: list[int], top_k: int = 5) -> list[list[Bas top_k_probs = [_probs[i].item() for i in top_k_indices] top_k_list = [] for t, p in zip(top_k_indices, top_k_probs): - top_k_list.append( - BaseGenToken( - token=t, - prob=p, - text=tokenizer.decode([t]) - ) - ) + top_k_list.append(BaseGenToken(token=t, prob=p, text=tokenizer.decode([t]))) text_sequence.append(top_k_list) batch.append(text_sequence) From aa2d0e4e01f809f095d82d50825fa66f0f90d115 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 16 Oct 2024 13:41:11 -0700 Subject: [PATCH 081/133] refactor get_next_token_with_top_k in Engine class to generate only last EngineOutput result --- guidance/_parser.py | 12 +--- guidance/models/_model.py | 123 +++++++++++++------------------------- 2 files changed, 46 insertions(+), 89 deletions(-) diff --git a/guidance/_parser.py b/guidance/_parser.py index 70f7bb2cb..772962c70 100644 --- a/guidance/_parser.py +++ b/guidance/_parser.py @@ -104,17 +104,11 @@ def _parse( if engine_output: response.engine_outputs.append(engine_output) - # if ff_tokens: - # if engine_output.issued_token.token == ff_tokens[0]: - # # this is generated - # response.generated_bytes = self.tokenizer.decode([ff_tokens[0]]) - - # if len(ff_tokens[1:]): - # response.force_forwarded_bytes = self.tokenizer.decode(ff_tokens[1:]) - + # NOTE (loc): Temporary solution to quickly check which segments are generated and which are force-forwarded to animate visualizations on the UI + # These tokens in chunk will not be used for final visualization + # TODO: This should be handled by the interpreter if response.new_bytes: _tokens = self.tokenizer.encode(response.new_bytes) - # _tokens = ff_tokens ff_token_start_idx = 1 if engine_output is None: diff --git a/guidance/models/_model.py b/guidance/models/_model.py index cabf12324..00e206bbc 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -330,11 +330,11 @@ def __call__(self, prompt, grammar, ensure_bos_token=True) -> Iterator[EngineCal else: mask = gen_data.mask - engine_output = self.get_next_top_k_tokens( + engine_output = self.get_next_token_with_top_k( token_ids=gen_data.tokens, mask=mask, temperature=gen_data.temperature, - )[0] + ) if is_in_accepting_state and not gen_data.mask[engine_output.issued_token.token]: engine_output.issued_token.token = self.tokenizer.eos_token_id @@ -348,18 +348,15 @@ def __call__(self, prompt, grammar, ensure_bos_token=True) -> Iterator[EngineCal yield response - def get_next_top_k_tokens( + def get_next_token_with_top_k( self, token_ids: list[int], mask: Optional[bytes], temperature: float, k: int = 5, - ) -> list[EngineOutput]: + ) -> EngineOutput: t0 = time.time() - new_tokens_logits = [self.get_logits(token_ids)] - if new_tokens_logits is None: - return [] - + logits = self.get_logits(token_ids) lat_ms = (time.time() - t0) * 1000 def get_top_k(_probs: np.ndarray, _k: int = 5) -> list[GenToken]: @@ -380,86 +377,52 @@ def get_top_k(_probs: np.ndarray, _k: int = 5) -> list[GenToken]: # compute top-k without masking probs = ( - softmax(np.array(new_tokens_logits)) + softmax(np.array(logits)) if temperature < 0.0001 - else softmax(np.array(new_tokens_logits) / temperature) + else softmax(np.array(logits) / temperature) ) - engine_list = [] - unseen_tokens = token_ids[-len(probs) :][1:] - - # we're missing the very first token - if len(token_ids) == len(probs): - first_token = token_ids[0] - engine_list.insert( - 0, - EngineOutput( - issued_token=GenToken( - token=first_token, - prob=1.0, - text=self.tokenizer.decode([first_token]).decode("utf-8"), - latency_ms=0, - is_generated=False, - ), - top_k=[], - masked_top_k=[], - is_backtracked=False, - ), - ) + top_k: list[GenToken] = get_top_k(probs, k) - for i, _probs in enumerate(probs): - top_k: list[GenToken] = get_top_k(_probs, k) - _logits = new_tokens_logits[i] - - # compute top-k with masking - masked_top_k: list[GenToken] = [] - if mask is not None: - # shift logits to [0 - max] range first and apply mask - masked_logits = (_logits - np.min(_logits)) * np.frombuffer(mask, dtype=np.uint8) - masked_probs = ( - softmax(masked_logits) - if temperature < 0.0001 - else softmax(masked_logits / temperature) - ) - masked_top_k = get_top_k(masked_probs, k) + # compute top-k with masking + masked_top_k: list[GenToken] = [] + if mask is not None: + # shift logits to [0 - max] range first and apply mask + masked_logits = (logits - np.min(logits)) * np.frombuffer(mask, dtype=np.uint8) + masked_probs = ( + softmax(masked_logits) + if temperature < 0.0001 + else softmax(masked_logits / temperature) + ) + masked_top_k = get_top_k(masked_probs, k) - if temperature < 0.0001: - issued_token = masked_top_k[0] if len(masked_top_k) > 0 else top_k[0] + if temperature < 0.0001: + issued_token = masked_top_k[0] if len(masked_top_k) > 0 else top_k[0] + else: + # we need to sample from the probabilities + if mask is None: + sampled_index = np.random.choice(len(probs), p=probs) + sampled_prob = probs[sampled_index] else: - # we need to sample from the probabilities - if mask is None: - sampled_index = np.random.choice(len(_probs), p=_probs) - else: - sampled_index = np.random.choice(len(masked_probs), p=masked_probs) - - issued_token = GenToken( - token=sampled_index, - prob=_probs[sampled_index], - text=self.tokenizer.decode([sampled_index]).decode("utf-8"), - latency_ms=lat_ms, - is_generated=True, - ) - - if i < len(unseen_tokens): - token = unseen_tokens[i] - issued_token = GenToken( - token=token, - prob=_probs[token], - text=self.tokenizer.decode([token]).decode("utf-8"), - latency_ms=0, - is_generated=False, - ) - - engine_list.append( - EngineOutput( - issued_token=issued_token, - top_k=top_k, - masked_top_k=None if not masked_top_k else masked_top_k, - is_backtracked=False, - ) + sampled_index = np.random.choice(len(masked_probs), p=masked_probs) + sampled_prob = masked_probs[sampled_index] + + issued_token = GenToken( + token=sampled_index, + prob=sampled_prob, + text=self.tokenizer.decode([sampled_index]).decode("utf-8"), + latency_ms=lat_ms, + is_generated=True, ) - return engine_list + output = EngineOutput( + issued_token=issued_token, + top_k=top_k, + masked_top_k=None if not masked_top_k else masked_top_k, + is_backtracked=False, + ) + + return output def get_next_token( self, token_ids: list[int], mask: Optional[bytes], temperature: float From d63879f52efe5968a7aac92ee3e31a42f4668ae6 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 16 Oct 2024 13:52:45 -0700 Subject: [PATCH 082/133] Refactor token in BaseGenToken into token_id --- guidance/_parser.py | 20 ++++++------ guidance/_schema.py | 2 +- guidance/models/_model.py | 31 ++++++++++--------- guidance/models/llama_cpp/_llama_cpp.py | 4 +-- guidance/models/transformers/_transformers.py | 4 +-- guidance/visual/_trace.py | 10 +++--- 6 files changed, 38 insertions(+), 33 deletions(-) diff --git a/guidance/_parser.py b/guidance/_parser.py index 772962c70..556c3fd3a 100644 --- a/guidance/_parser.py +++ b/guidance/_parser.py @@ -113,16 +113,16 @@ def _parse( ff_token_start_idx = 1 if engine_output is None: ff_token_start_idx = 0 - elif engine_output.issued_token.token == _tokens[0]: + elif engine_output.issued_token.token_id == _tokens[0]: # this is generated response.generated_bytes = self.tokenizer.decode([_tokens[0]]) engine_output.issued_token.is_generated = True response.generated_tokens.append(engine_output.issued_token) else: # check if the first byte contains the generated token - generated = self.tokenizer.decode([engine_output.issued_token.token]).decode( - "utf-8" - ) + generated = self.tokenizer.decode( + [engine_output.issued_token.token_id] + ).decode("utf-8") force_forwarded = self.tokenizer.decode([_tokens[0]]).decode("utf-8") if force_forwarded.startswith(generated): @@ -131,7 +131,7 @@ def _parse( response.generated_bytes = self.tokenizer.decode([_tokens[0]]) response.generated_tokens.append( GenToken( - token=_tokens[0], + token_id=_tokens[0], prob=1.0, text=response.generated_bytes.decode("utf-8"), latency_ms=engine_output.issued_token.latency_ms, @@ -148,7 +148,7 @@ def _parse( for _token in _tokens[ff_token_start_idx:]: response.force_forwarded_tokens.append( GenToken( - token=_token, + token_id=_token, prob=1.0, text=self.tokenizer.decode([_token]).decode("utf-8"), latency_ms=0, @@ -170,22 +170,22 @@ def _parse( engine_output = yield (gen_data, response) if engine_output is None: raise TokenParserException("Expected EngineOutput, got None") - if not mask[engine_output.issued_token.token]: + if not mask[engine_output.issued_token.token_id]: # Note: we could punt this probem to ll_interpreter.post_process, # but it's a bit clearer to handle it here raise InvalidTokenException( - engine_output.issued_token.token, gen_data.valid_next_tokens, tokens + engine_output.issued_token.token_id, gen_data.valid_next_tokens, tokens ) else: gen_data = None engine_output = yield (gen_data, response) if engine_output is not None: raise TokenParserException( - f"Expected None, got token {engine_output.issued_token.token}" + f"Expected None, got token {engine_output.issued_token.token_id}" ) backtrack, ff_tokens = self.ll_interpreter.post_process( - engine_output.issued_token.token + engine_output.issued_token.token_id ) if backtrack: tokens = tokens[:-backtrack] diff --git a/guidance/_schema.py b/guidance/_schema.py index c0d8c3cfc..86b1a8340 100644 --- a/guidance/_schema.py +++ b/guidance/_schema.py @@ -30,7 +30,7 @@ class EngineCallResponse(BaseModel): class BaseGenToken(BaseModel): - token: int + token_id: int prob: float text: str = "" is_masked: bool = False diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 00e206bbc..6d1009f3f 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -227,7 +227,7 @@ def _msg_recv(self, message: GuidanceMessage) -> None: final_text = "".join([gen_token.text for gen_token in processed_gen_tokens]) logger.debug(f"ENGINE:final_text:{final_text}") - tokens = [gen_token.token for gen_token in processed_gen_tokens] + tokens = [gen_token.token_id for gen_token in processed_gen_tokens] self.renderer.update( ExecutionCompletedOutputMessage( trace_id=message.last_trace_id, @@ -336,8 +336,11 @@ def __call__(self, prompt, grammar, ensure_bos_token=True) -> Iterator[EngineCal temperature=gen_data.temperature, ) - if is_in_accepting_state and not gen_data.mask[engine_output.issued_token.token]: - engine_output.issued_token.token = self.tokenizer.eos_token_id + if ( + is_in_accepting_state + and not gen_data.mask[engine_output.issued_token.token_id] + ): + engine_output.issued_token.token_id = self.tokenizer.eos_token_id # TODO: Should we set the prob to 1.0 here? engine_output.issued_token.prob = 1.0 else: @@ -365,7 +368,7 @@ def get_top_k(_probs: np.ndarray, _k: int = 5) -> list[GenToken]: return [ GenToken( - token=token, + token_id=token, prob=prob, text=self.tokenizer.decode([token]).decode("utf-8"), latency_ms=lat_ms, @@ -408,7 +411,7 @@ def get_top_k(_probs: np.ndarray, _k: int = 5) -> list[GenToken]: sampled_prob = masked_probs[sampled_index] issued_token = GenToken( - token=sampled_index, + token_id=sampled_index, prob=sampled_prob, text=self.tokenizer.decode([sampled_index]).decode("utf-8"), latency_ms=lat_ms, @@ -819,7 +822,7 @@ def __add__(self, value): is_input=True, input_tokens=[ GenToken( - token=_token, + token_id=_token, prob=1.0, text=out.engine.tokenizer.decode([_token]).decode("utf-8"), latency_ms=0, @@ -1248,7 +1251,7 @@ def get_per_token_stats(self) -> list[GenToken]: for engine_output in vis_chunk.engine_outputs: gen_tokens_lats.append( ( - engine_output.issued_token.token, + engine_output.issued_token.token_id, engine_output.issued_token.latency_ms, engine_output.masked_top_k, ) @@ -1268,7 +1271,7 @@ def get_per_token_stats(self) -> list[GenToken]: # FIXME (loc): assume prob 1.0 for all tokens probs = [] for token_id, token_text in zip(token_ids, token_texts): - probs.append([BaseGenToken(token=token_id, prob=1.0, text=token_text)]) + probs.append([BaseGenToken(token_id=token_id, prob=1.0, text=token_text)]) start_idx = 0 end_idx = 1 @@ -1318,12 +1321,12 @@ def get_per_token_stats(self) -> list[GenToken]: for token_id, top_k_prob in zip(_chunk_token_ids, _chunk_probs): prob = -1 for _token in top_k_prob: - if _token.token == token_id: + if _token.token_id == token_id: prob = _token.prob break _gen_token = GenToken( - token=token_id, + token_id=token_id, prob=prob, text=self.engine.tokenizer.decode([token_id]).decode("utf-8"), latency_ms=0, @@ -1347,7 +1350,7 @@ def get_per_token_stats(self) -> list[GenToken]: found_perfect_match = False max_idx = gen_tokens_indices[vis_chunk_idx] for idx in range(max_idx, -1, -1): - if _gen_token.token == gen_tokens_lats[idx][0]: + if _gen_token.token_id == gen_tokens_lats[idx][0]: _gen_token.latency_ms = gen_tokens_lats[idx][1] _masked_top_k = gen_tokens_lats[idx][2] @@ -1362,7 +1365,7 @@ def get_per_token_stats(self) -> list[GenToken]: else: _masked_tokens = [token.token for token in _masked_top_k] for _token in _gen_token.top_k: - if _token.token not in _masked_tokens: + if _token.token_id not in _masked_tokens: _token.is_masked = True else: _token.is_masked = False @@ -1401,8 +1404,8 @@ def get_per_token_stats(self) -> list[GenToken]: _masked_tokens = [token.token for token in _masked_top_k] for _token in _gen_token.top_k: if ( - _token.token not in _masked_tokens - and _token.token != _gen_token.token + _token.token_id not in _masked_tokens + and _token.token_id != _gen_token.token_id ): _token.is_masked = True else: diff --git a/guidance/models/llama_cpp/_llama_cpp.py b/guidance/models/llama_cpp/_llama_cpp.py index 40d81540e..2718edfc9 100644 --- a/guidance/models/llama_cpp/_llama_cpp.py +++ b/guidance/models/llama_cpp/_llama_cpp.py @@ -270,7 +270,7 @@ def get_per_token_topk_probs( except Exception as e: _text = str(_bytes) print(f"Failed to decode token: {token_ids[0]}, error: {e}, _bytes: {str(_bytes)}") - text_sequence.append([BaseGenToken(token=token_ids[0], prob=1.0, text=_text)]) + text_sequence.append([BaseGenToken(token_id=token_ids[0], prob=1.0, text=_text)]) for token_idx, logits in zip(token_ids[1:], logits_batch[:-1]): _probs = self._softmax(logits) @@ -292,7 +292,7 @@ def get_per_token_topk_probs( print( f"Failed to decode token: {_token_idx}, error: {e}, _bytes: {str(_bytes)}" ) - top_k_list.append(BaseGenToken(token=_token_idx, prob=_prob, text=_text)) + top_k_list.append(BaseGenToken(token_id=_token_idx, prob=_prob, text=_text)) text_sequence.append(top_k_list) diff --git a/guidance/models/transformers/_transformers.py b/guidance/models/transformers/_transformers.py index 30155105c..685231415 100644 --- a/guidance/models/transformers/_transformers.py +++ b/guidance/models/transformers/_transformers.py @@ -556,7 +556,7 @@ def get_per_token_topk_probs( text_sequence.append( [ BaseGenToken( - token=_token_id.item(), + token_id=_token_id.item(), prob=1.0, text=tokenizer.decode([_token_id]), ) @@ -572,7 +572,7 @@ def get_per_token_topk_probs( top_k_probs = [_probs[i].item() for i in top_k_indices] top_k_list = [] for t, p in zip(top_k_indices, top_k_probs): - top_k_list.append(BaseGenToken(token=t, prob=p, text=tokenizer.decode([t]))) + top_k_list.append(BaseGenToken(token_id=t, prob=p, text=tokenizer.decode([t]))) text_sequence.append(top_k_list) batch.append(text_sequence) diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index 3a0513621..0dca4a3f3 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -18,7 +18,9 @@ span_end = "" -def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: ExecutionCompletedOutputMessage=None) -> str: +def trace_node_to_html( + node: TraceNode, prettify_roles=False, complete_msg: ExecutionCompletedOutputMessage = None +) -> str: """Represents trace path as html string. Args: @@ -71,9 +73,9 @@ def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: Exec else: # switch to token-based cell_tokens = attr.tokens - for token in cell_tokens: + for token in cell_tokens: # assert token.token == complete_msg.tokens[prob_idx].token, f"Token mismatch {token.token} != {complete_msg.tokens[prob_idx].token}" - if token.token != complete_msg.tokens[prob_idx].token: + if token.token_id != complete_msg.tokens[prob_idx].token_id: if remaining_text + token.text != complete_msg.tokens[prob_idx].text: remaining_text += token.text continue @@ -97,7 +99,7 @@ def trace_node_to_html(node: TraceNode, prettify_roles=False, complete_msg: Exec else: fmt += f"{html.escape(token_str)}" - full_text = full_text[len(token_str):] + full_text = full_text[len(token_str) :] prob_idx += 1 pass buffer.append(fmt) From 2bf8a407be88928aeb5f6e7073eb940b6854605f Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 16 Oct 2024 14:11:06 -0700 Subject: [PATCH 083/133] Fix token not in GenToken --- guidance/models/_model.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 6d1009f3f..ffd3a681e 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -1261,8 +1261,8 @@ def get_per_token_stats(self) -> list[GenToken]: text = self._state token_ids = self.engine.tokenizer.encode(text.encode("utf-8")) token_texts: list[str] = [] - for idx in range(len(token_ids)): - token_texts.append(self.engine.tokenizer.decode([token_ids[idx]]).decode("utf-8")) + for idx, token_id in enumerate(token_ids): + token_texts.append(self.engine.tokenizer.decode([token_id]).decode("utf-8")) # NOTE (loc): Not all engines support the get_token_probs method try: @@ -1363,7 +1363,7 @@ def get_per_token_stats(self) -> list[GenToken]: for _token in _gen_token.top_k: _token.is_masked = False else: - _masked_tokens = [token.token for token in _masked_top_k] + _masked_tokens = [token.token_id for token in _masked_top_k] for _token in _gen_token.top_k: if _token.token_id not in _masked_tokens: _token.is_masked = True @@ -1401,7 +1401,7 @@ def get_per_token_stats(self) -> list[GenToken]: for _token in _gen_token.top_k: _token.is_masked = False else: - _masked_tokens = [token.token for token in _masked_top_k] + _masked_tokens = [token.token_id for token in _masked_top_k] for _token in _gen_token.top_k: if ( _token.token_id not in _masked_tokens From 9b2cda41c0ab10111b722b621913c790dc781919 Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 16 Oct 2024 14:29:09 -0700 Subject: [PATCH 084/133] refactor get_per_token_stats func --- guidance/models/_model.py | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index ffd3a681e..279f22ca2 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -1095,24 +1095,6 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): if chunk.backtrack: lm.engine.metrics.engine_backtrack_tokens += chunk.backtrack - # while chunk.backtrack > 0: - # parent = lm._parent - # while parent is not None: - # if parent.vis_chunk is not None: - # break - - # parent = parent._parent - - # if parent.vis_chunk.input_tokens: - # parent.vis_chunk.input_tokens.pop() - # chunk.backtrack -= 1 - # elif parent.vis_chunk.generated_tokens: - # parent.vis_chunk.generated_tokens.pop() - # chunk.backtrack -= 1 - # elif parent.vis_chunk.force_forwarded_tokens: - # parent.vis_chunk.force_forwarded_tokens.pop() - # chunk.backtrack -= 1 - if len(chunk.new_bytes) > 0: generated_value += new_text @@ -1123,6 +1105,7 @@ def _run_stateless(self, stateless_function, temperature=0.0, top_p=1.0, n=1): # prob=chunk.new_bytes_prob, # ) + # split chunk into generated and force_forwarded parts for better animated visualization if chunk.generated_bytes: lm += TextOutput( value=chunk.generated_bytes.decode("utf8"), @@ -1245,18 +1228,18 @@ def get_per_token_stats(self) -> list[GenToken]: path.vis_chunk for path in paths if path.vis_chunk is not None ] - gen_tokens_lats = [] - gen_tokens_indices = [] + gen_tokens_infos: list[tuple[int, float, list[GenToken]]] = [] + gen_tokens_indices: list[int] = [] for vis_chunk in vis_chunks: for engine_output in vis_chunk.engine_outputs: - gen_tokens_lats.append( + gen_tokens_infos.append( ( engine_output.issued_token.token_id, engine_output.issued_token.latency_ms, engine_output.masked_top_k, ) ) - gen_tokens_indices.append(len(gen_tokens_lats) - 1) + gen_tokens_indices.append(len(gen_tokens_infos) - 1) text = self._state token_ids = self.engine.tokenizer.encode(text.encode("utf-8")) @@ -1350,9 +1333,9 @@ def get_per_token_stats(self) -> list[GenToken]: found_perfect_match = False max_idx = gen_tokens_indices[vis_chunk_idx] for idx in range(max_idx, -1, -1): - if _gen_token.token_id == gen_tokens_lats[idx][0]: - _gen_token.latency_ms = gen_tokens_lats[idx][1] - _masked_top_k = gen_tokens_lats[idx][2] + if _gen_token.token_id == gen_tokens_infos[idx][0]: + _gen_token.latency_ms = gen_tokens_infos[idx][1] + _masked_top_k = gen_tokens_infos[idx][2] # if we find a match, then this token should be marked as generated _gen_token.is_generated = True @@ -1384,13 +1367,13 @@ def get_per_token_stats(self) -> list[GenToken]: ) for idx in range(max_idx, prev_max_idx, -1): if ( - self.engine.tokenizer.decode([gen_tokens_lats[idx][0]]).decode( + self.engine.tokenizer.decode([gen_tokens_infos[idx][0]]).decode( "utf-8" ) in _gen_token.text ): - _gen_token.latency_ms = gen_tokens_lats[idx][1] - _masked_top_k = gen_tokens_lats[idx][2] + _gen_token.latency_ms = gen_tokens_infos[idx][1] + _masked_top_k = gen_tokens_infos[idx][2] # if we find a match, then this token should be marked as generated _gen_token.is_generated = True From cab45887e183fca2e6cbec2f1ee42576c476819f Mon Sep 17 00:00:00 2001 From: Loc Huynh Date: Wed, 16 Oct 2024 17:37:09 -0700 Subject: [PATCH 085/133] support getting per_token_stats for Phi3 --- guidance/models/_model.py | 36 +++++++++++++++-- guidance/visual/_trace.py | 84 ++++++++++++++++++++++++++++++--------- 2 files changed, 97 insertions(+), 23 deletions(-) diff --git a/guidance/models/_model.py b/guidance/models/_model.py index 279f22ca2..8d5a6d730 100644 --- a/guidance/models/_model.py +++ b/guidance/models/_model.py @@ -1243,9 +1243,34 @@ def get_per_token_stats(self) -> list[GenToken]: text = self._state token_ids = self.engine.tokenizer.encode(text.encode("utf-8")) + + # verify if text == encode(decode(text)) + decoded_text = self.engine.tokenizer.decode(token_ids).decode("utf-8") + token_texts: list[str] = [] - for idx, token_id in enumerate(token_ids): - token_texts.append(self.engine.tokenizer.decode([token_id]).decode("utf-8")) + if text == decoded_text: + for idx, token_id in enumerate(token_ids): + token_texts.append(self.engine.tokenizer.decode([token_id]).decode("utf-8")) + else: + # need to pad missing tokens + ptr_idx = 0 + for token_id in token_ids: + missing_chunk = "" + decoded = self.engine.tokenizer.decode([token_id]).decode("utf-8") + if not text[ptr_idx:].startswith(decoded): + _next_idx = ptr_idx + found = False + while _next_idx < len(text): + if text[_next_idx:].startswith(decoded): + found = True + break + _next_idx += 1 + + assert found, f"Failed to find the token {decoded} in the text {text}" + missing_chunk = text[ptr_idx:_next_idx] + + token_texts.append(missing_chunk + decoded) + ptr_idx += len(missing_chunk + decoded) # NOTE (loc): Not all engines support the get_token_probs method try: @@ -1296,12 +1321,15 @@ def get_per_token_stats(self) -> list[GenToken]: _chunk_token_ids = token_ids[start_idx : end_idx + 1] _chunk_probs = probs[start_idx : end_idx + 1] + _chunk_token_texts = token_texts[start_idx : end_idx + 1] is_input = len(vis_chunk.input_tokens) > 0 is_force_forwarded = len(vis_chunk.force_forwarded_tokens) > 0 _gen_tokens: list[GenToken] = [] - for token_id, top_k_prob in zip(_chunk_token_ids, _chunk_probs): + for token_id, top_k_prob, token_text in zip( + _chunk_token_ids, _chunk_probs, _chunk_token_texts + ): prob = -1 for _token in top_k_prob: if _token.token_id == token_id: @@ -1311,7 +1339,7 @@ def get_per_token_stats(self) -> list[GenToken]: _gen_token = GenToken( token_id=token_id, prob=prob, - text=self.engine.tokenizer.decode([token_id]).decode("utf-8"), + text=token_text, latency_ms=0, is_input=is_input, is_generated=False, diff --git a/guidance/visual/_trace.py b/guidance/visual/_trace.py index 0dca4a3f3..eaa1b846e 100644 --- a/guidance/visual/_trace.py +++ b/guidance/visual/_trace.py @@ -2,6 +2,7 @@ import json from typing import Optional, Dict +from guidance._schema import GenToken from guidance.visual._message import ExecutionCompletedOutputMessage from ..trace import ( @@ -72,36 +73,81 @@ def trace_node_to_html( fmt += f"{html.escape(attr.value)}" else: # switch to token-based - cell_tokens = attr.tokens - for token in cell_tokens: - # assert token.token == complete_msg.tokens[prob_idx].token, f"Token mismatch {token.token} != {complete_msg.tokens[prob_idx].token}" - if token.token_id != complete_msg.tokens[prob_idx].token_id: - if remaining_text + token.text != complete_msg.tokens[prob_idx].text: - remaining_text += token.text - continue - else: - remaining_text = "" - - token_str = complete_msg.tokens[prob_idx].text - prob = complete_msg.tokens[prob_idx].prob + # cell_tokens = attr.tokens + # for token in cell_tokens: + # # assert token.token == complete_msg.tokens[prob_idx].token, f"Token mismatch {token.token} != {complete_msg.tokens[prob_idx].token}" + # if token.token_id != complete_msg.tokens[prob_idx].token_id: + # if remaining_text + token.text != complete_msg.tokens[prob_idx].text: + # remaining_text += token.text + # continue + # else: + # remaining_text = "" + + # token_str = complete_msg.tokens[prob_idx].text + # prob = complete_msg.tokens[prob_idx].prob + # top_k = {} + # # find the correct token + # for _item in complete_msg.tokens[prob_idx].top_k: + # top_k[f"{_item.text}"] = f"{_item.prob} - Masked: {_item.is_masked}" + # top_k = json.dumps(top_k, indent=2) + + # latency = f"{complete_msg.tokens[prob_idx].latency_ms:.2f}" + + # if complete_msg.tokens[prob_idx].is_generated: + # fmt += f"{html.escape(token_str)}" + # elif complete_msg.tokens[prob_idx].is_force_forwarded: + # fmt += f"{html.escape(token_str)}" + # else: + # fmt += f"{html.escape(token_str)}" + + # full_text = full_text[len(token_str) :] + # prob_idx += 1 + + chunk_text = attr.value + # find tokens in complete message that cover this chunk + tokens: list[GenToken] = [] + _idx = prob_idx + tokens_text = "" + while _idx < len(complete_msg.tokens): + _token = complete_msg.tokens[_idx] + tokens_text += _token.text + tokens.append(_token) + if chunk_text in tokens_text: + break + _idx += 1 + + assert ( + chunk_text in tokens_text + ), f"Token mismatch {tokens_text} != {chunk_text}" + + start_idx = tokens_text.index(chunk_text) + remaining_text = tokens_text[start_idx + len(chunk_text) :] + + if remaining_text: + # remove the last tokens + tokens.pop(-1) + + # update prob_idx + prob_idx += len(tokens) + + for token in tokens: + token_str = token.text + prob = token.prob top_k = {} # find the correct token - for _item in complete_msg.tokens[prob_idx].top_k: + for _item in token.top_k: top_k[f"{_item.text}"] = f"{_item.prob} - Masked: {_item.is_masked}" top_k = json.dumps(top_k, indent=2) - latency = f"{complete_msg.tokens[prob_idx].latency_ms:.2f}" + latency = f"{token.latency_ms:.2f}" - if complete_msg.tokens[prob_idx].is_generated: + if token.is_generated: fmt += f"{html.escape(token_str)}" - elif complete_msg.tokens[prob_idx].is_force_forwarded: + elif token.is_force_forwarded: fmt += f"{html.escape(token_str)}" else: fmt += f"{html.escape(token_str)}" - full_text = full_text[len(token_str) :] - prob_idx += 1 - pass buffer.append(fmt) if active_role is not None: From 9a6dd7f6ef0f0181517289e1ff98f386470e9bf3 Mon Sep 17 00:00:00 2001 From: S Jenkins Date: Thu, 17 Oct 2024 12:38:53 -0700 Subject: [PATCH 086/133] WIP updated style. --- client/graphpaper-inline/src/App.svelte | 19 ++- .../graphpaper-inline/src/MetricCard.svelte | 2 +- client/graphpaper-inline/src/TokenGrid.svelte | 110 +++++++++++++----- .../src/TokenGridItem.svelte | 14 +-- client/graphpaper-inline/src/interfaces.ts | 5 +- guidance/resources/graphpaper-inline.html | 4 +- guidance/visual/_renderer.py | 8 +- 7 files changed, 105 insertions(+), 57 deletions(-) diff --git a/client/graphpaper-inline/src/App.svelte b/client/graphpaper-inline/src/App.svelte index a3b2eeeb8..33143f4a6 100644 --- a/client/graphpaper-inline/src/App.svelte +++ b/client/graphpaper-inline/src/App.svelte @@ -29,8 +29,8 @@ let completedExecution: boolean = false; let mode: string; - // textComponents = mockNodeAttrs; - // tokenDetails = mockGenTokens; + textComponents = mockNodeAttrs; + tokenDetails = mockGenTokens; $: if ($kernelmsg !== undefined) { if ($kernelmsg.content !== '') { @@ -45,6 +45,7 @@ } } else if (isResetDisplayMessage(msg)) { textComponents = []; + completedExecution = false; } else if (isMetricMessage(msg)) { const name = msg.name; const value = msg.value; @@ -68,8 +69,6 @@ } else if (isExecutionCompletedMessage(msg)) { completedExecution = true; } else if (isExecutionCompletedOutputMessage(msg)) { - console.log(textComponents); - console.log(msg.tokens); tokenDetails = msg.tokens; } textComponents = textComponents; @@ -100,17 +99,17 @@ }, 'ram': { name: 'ram', - units: 'GB', + units: 'G', description: 'Utilization of RAM.', isScalar: true, - precision: 0, + precision: 1, }, 'vram': { name: 'vram', - units: 'GB', + units: 'G', description: 'Utilization of video RAM.', isScalar: true, - precision: 0, + precision: 1, }, 'wall time': { name: 'wall time', @@ -180,9 +179,9 @@ -
+
-