From 0542347bd7fd78a8961f004d5ea25d06a1a00820 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jul 2024 11:12:49 +0800 Subject: [PATCH 01/85] chore: fix health API chore: fix assets path conflict --- src/openagent/app.py | 15 ++++++++------- src/widget/vite.config.ts | 9 ++++++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/openagent/app.py b/src/openagent/app.py index a24a0e4e..8cbf815b 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -23,6 +23,12 @@ allow_headers=["*"], ) + +@app.get("/health", status_code=status.HTTP_200_OK) +async def health_check(): + return JSONResponse(content={"status": "ok"}) + + app.include_router(onboarding_router) app.include_router(chat_router) app.include_router(session_router) @@ -34,11 +40,6 @@ async def swap_root(): return FileResponse(os.path.join("dist", "index.html")) -app.mount("/assets", StaticFiles(directory="dist/assets"), name="widget") +app.mount("/static", StaticFiles(directory="dist/static"), name="widget") -mount_chainlit(app=app, target="openagent/ui/app.py", path="/ui") - - -@app.get("/health", status_code=status.HTTP_200_OK) -async def health_check(): - return JSONResponse(content={"status": "ok"}) +mount_chainlit(app=app, target="openagent/ui/app.py", path="") diff --git a/src/widget/vite.config.ts b/src/widget/vite.config.ts index f6115b38..f0751fcb 100644 --- a/src/widget/vite.config.ts +++ b/src/widget/vite.config.ts @@ -10,7 +10,14 @@ export default defineConfig({ target: 'esnext', }, build: { - outDir: '../dist' + outDir: '../dist', + rollupOptions: { + output: { + assetFileNames: 'static/[name].[hash].[ext]', + chunkFileNames: 'static/[name].[hash].js', + entryFileNames: 'static/[name].[hash].js', + } + } }, server: { From 14cf351b5877fbf9a25947fbefce2bfdd8b6c81e Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jul 2024 14:53:59 +0800 Subject: [PATCH 02/85] chore: remove useless files --- src/openagent/agent/cache.py | 2 - src/openagent/agent/ctx_var.py | 6 - src/openagent/agent/function_agent.py | 151 ------------ src/openagent/agent/postgres_history.py | 49 ---- src/openagent/agent/session_title.py | 51 ---- src/openagent/agent/stream_callback.py | 269 ---------------------- src/openagent/agent/suggested_question.py | 63 ----- src/openagent/app.py | 9 - src/openagent/conf/env.py | 38 ++- src/openagent/conf/llm_provider.py | 22 ++ src/openagent/db/database.py | 3 - src/openagent/db/models.py | 44 ---- src/openagent/dto/__init__.py | 0 src/openagent/dto/cb_content.py | 19 -- src/openagent/dto/chat_history.py | 108 --------- src/openagent/dto/chat_req.py | 16 -- src/openagent/dto/chat_resp.py | 19 -- src/openagent/dto/error.py | 7 - src/openagent/dto/mutation.py | 22 -- src/openagent/dto/session.py | 113 --------- src/openagent/dto/task.py | 87 ------- src/openagent/index/pgvector_store.py | 2 +- src/openagent/router/__init__.py | 0 src/openagent/router/chat.py | 16 -- src/openagent/router/onboarding.py | 56 ----- src/openagent/router/session.py | 110 --------- src/openagent/service/__init__.py | 0 src/openagent/service/chat.py | 159 ------------- src/openagent/service/history.py | 98 -------- src/openagent/service/session.py | 254 -------------------- 30 files changed, 52 insertions(+), 1741 deletions(-) delete mode 100644 src/openagent/agent/cache.py delete mode 100644 src/openagent/agent/ctx_var.py delete mode 100644 src/openagent/agent/function_agent.py delete mode 100644 src/openagent/agent/postgres_history.py delete mode 100644 src/openagent/agent/session_title.py delete mode 100644 src/openagent/agent/stream_callback.py delete mode 100644 src/openagent/agent/suggested_question.py create mode 100644 src/openagent/conf/llm_provider.py delete mode 100644 src/openagent/dto/__init__.py delete mode 100644 src/openagent/dto/cb_content.py delete mode 100644 src/openagent/dto/chat_history.py delete mode 100644 src/openagent/dto/chat_req.py delete mode 100644 src/openagent/dto/chat_resp.py delete mode 100644 src/openagent/dto/error.py delete mode 100644 src/openagent/dto/mutation.py delete mode 100644 src/openagent/dto/session.py delete mode 100644 src/openagent/dto/task.py delete mode 100644 src/openagent/router/__init__.py delete mode 100644 src/openagent/router/chat.py delete mode 100644 src/openagent/router/onboarding.py delete mode 100644 src/openagent/router/session.py delete mode 100644 src/openagent/service/__init__.py delete mode 100644 src/openagent/service/chat.py delete mode 100644 src/openagent/service/history.py delete mode 100644 src/openagent/service/session.py diff --git a/src/openagent/agent/cache.py b/src/openagent/agent/cache.py deleted file mode 100644 index c7521ec1..00000000 --- a/src/openagent/agent/cache.py +++ /dev/null @@ -1,2 +0,0 @@ -def init_cache() -> None: - pass diff --git a/src/openagent/agent/ctx_var.py b/src/openagent/agent/ctx_var.py deleted file mode 100644 index cffa78b9..00000000 --- a/src/openagent/agent/ctx_var.py +++ /dev/null @@ -1,6 +0,0 @@ -from contextvars import ContextVar - -from openagent.dto.chat_req import ChatReq - -resp_msg_id: ContextVar[str | None] = ContextVar("resp_msg_id", default=None) -chat_req_ctx: ContextVar[ChatReq] = ContextVar("chat_req_ctx") diff --git a/src/openagent/agent/function_agent.py b/src/openagent/agent/function_agent.py deleted file mode 100644 index f4669ff0..00000000 --- a/src/openagent/agent/function_agent.py +++ /dev/null @@ -1,151 +0,0 @@ -import asyncio - -from langchain.agents import ( - AgentExecutor, - AgentType, - create_tool_calling_agent, - initialize_agent, -) -from langchain.prompts import MessagesPlaceholder -from langchain.schema import SystemMessage -from langchain_community.chat_models import ChatOllama -from langchain_core.prompts import ChatPromptTemplate -from langchain_google_vertexai import ChatVertexAI -from langchain_openai import ChatOpenAI -from toolz import memoize - -from openagent.agent.cache import init_cache -from openagent.agent.system_prompt import ( - SYSTEM_PROMPT, - SYSTEM_PROMPT_V2, - custom_agent_kwargs, -) -from openagent.conf.env import settings -from openagent.experts.article_expert import ArticleExpert -from openagent.experts.feed_expert import FeedExpert -from openagent.experts.nft_expert import NFTExpert -from openagent.experts.price_expert import PriceExpert -from openagent.experts.search_expert import SearchExpert -from openagent.experts.swap_expert import SwapExpert -from openagent.experts.transfer_expert import TransferExpert - -# Initialize cache -init_cache() - - -# Function to create a ReAct agent -def create_react_agent(session_id: str): - # Define agent kwargs - agent_kwargs = ( - { - "system_message": SystemMessage(content=SYSTEM_PROMPT), - "extra_prompt_messages": [MessagesPlaceholder(variable_name="memory")], - } - if settings.MODEL_NAME.startswith("gpt") - else custom_agent_kwargs - ) - - # List of experts to be loaded - experts = [ - SearchExpert(), - FeedExpert(), - PriceExpert(), - ArticleExpert(), - NFTExpert(), - SwapExpert(), - TransferExpert(), - ] - - # Initialize interpreter - interpreter = create_interpreter(settings.MODEL_NAME) - - # Initialize and return the agent - return initialize_agent( - experts, - interpreter, - agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, - verbose=True, - agent_kwargs=agent_kwargs, - handle_parsing_errors=True, - ) - - -# Function to create an interpreter based on model name -def create_interpreter(model_name): - if model_name.startswith("gpt"): - return ChatOpenAI( - model=model_name, - temperature=0.3, - streaming=True, - ) - elif model_name.startswith("gemini"): - return ChatVertexAI( - model=settings.MODEL_NAME, - project=settings.PROJECT_ID, - temperature=0.3, - streaming=True, - ) - else: - return ChatOllama( - model=model_name, - base_url=settings.LLM_API_BASE, - ) - - -@memoize -def get_agent(session_id: str) -> AgentExecutor: - if settings.MODEL_NAME.startswith("gemini") or settings.MODEL_NAME.startswith("gpt"): - return create_tool_call_agent(session_id) - return create_react_agent(session_id) - - -# Function to create a tool calling agent -def create_tool_call_agent(session_id: str): - # Initialize language model - interpreter = create_interpreter(settings.MODEL_NAME) - - # Define prompt - prompt = ChatPromptTemplate.from_messages( - [ - ( - "system", - SYSTEM_PROMPT_V2, - ), - ("placeholder", "{chat_history}"), - ("human", "{input}"), - ("placeholder", "{agent_scratchpad}"), - ] - ) - - # List of experts - experts = [ - SearchExpert(), - FeedExpert(), - PriceExpert(), - ArticleExpert(), - NFTExpert(), - SwapExpert(), - TransferExpert(), - ] - - # Construct the Tools agent - agent = create_tool_calling_agent(interpreter, experts, prompt) - - # Create an agent executor by passing in the agent and tools - agent_executor = AgentExecutor(agent=agent, tools=experts, verbose=True) - return agent_executor - - -# Function to get the chat history of a session from Postgres - - -async def main(): - # Create a tool call agent and use it to handle some inputs - agent = get_agent("123") - await agent.ainvoke({"input": "Swap 1 eth to usdt"}) - await agent.ainvoke({"input": "What is the price of ETH?"}) - await agent.ainvoke({"input": "What did vitalik.eth do recently?"}) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/src/openagent/agent/postgres_history.py b/src/openagent/agent/postgres_history.py deleted file mode 100644 index a4f5b2d3..00000000 --- a/src/openagent/agent/postgres_history.py +++ /dev/null @@ -1,49 +0,0 @@ -import json -import logging -from typing import List - -from langchain.schema import ( - BaseChatMessageHistory, -) -from langchain.schema.messages import BaseMessage, messages_from_dict -from toolz.curried import compose_left, filter, map - -from openagent.db.database import DBSession -from openagent.db.models import ChatHistory - -logger = logging.getLogger(__name__) - - -class PostgresChatMessageHistory(BaseChatMessageHistory): - """Chat message history stored in a Postgres database.""" - - def __init__( - self, - session_id: str, - ): - self.session_id = session_id - - @property - def messages(self) -> List[BaseMessage]: # type: ignore - with DBSession() as db_session: - histories = ( - db_session.query(ChatHistory) - .filter(ChatHistory.session_id == self.session_id) - .all() - ) - lst = compose_left( - map(compose_left(lambda x: x.message, json.loads)), - filter(lambda x: x["type"] in ["ai", "human"]), - list, - )(histories) - return messages_from_dict(lst) - - def add_message(self, message: BaseMessage) -> None: - # saved by stream callback - pass - - def clear(self) -> None: - ChatHistory.filter(session_id=self.session_id).delete() - - def __del__(self) -> None: - pass diff --git a/src/openagent/agent/session_title.py b/src/openagent/agent/session_title.py deleted file mode 100644 index 2bfb89c2..00000000 --- a/src/openagent/agent/session_title.py +++ /dev/null @@ -1,51 +0,0 @@ -from dotenv import load_dotenv -from langchain.chains import LLMChain -from langchain.prompts import PromptTemplate -from langchain_community.chat_models import ChatOllama -from langchain_google_vertexai import ChatVertexAI -from langchain_openai import ChatOpenAI -from loguru import logger - -from openagent.conf.env import settings -from openagent.db.database import DBSession -from openagent.db.models import ChatSession - -load_dotenv() - - -async def agen_session_title(user_id: str, session_id: str, history: str) -> list[str]: - prompt = PromptTemplate( - template=""" -Based on the following user chat history, generate a session title. \ -Your response words should less than 10 words and return directly. - -History: -{history} -Session Title: - """, - input_variables=["history"], - ) - if settings.MODEL_NAME.startswith("gpt"): - model = ChatOpenAI( - model=settings.MODEL_NAME, - openai_api_base=settings.LLM_API_BASE, - temperature=0.5, - ) - elif settings.MODEL_NAME.startswith("gemini"): - model = ChatVertexAI(model_name=settings.MODEL_NAME) - else: - model = ChatOllama(model=settings.MODEL_NAME, base_url=settings.LLM_API_BASE) - interpreter = LLMChain(llm=model, prompt=prompt) - logger.info(f"start to generate session title based on history: {history}") - output = await interpreter.arun( - history=history, - metadata={"agentName": "openagent-chainlit", "userId": user_id}, - ) - output = output.strip("'").strip('"') - logger.info(f"session title generated: {output}") - with DBSession() as db_session: - db_session.query(ChatSession).filter( - ChatSession.session_id == session_id - ).update({ChatSession.title: output}) - db_session.commit() - return output diff --git a/src/openagent/agent/stream_callback.py b/src/openagent/agent/stream_callback.py deleted file mode 100644 index 694adaf4..00000000 --- a/src/openagent/agent/stream_callback.py +++ /dev/null @@ -1,269 +0,0 @@ -import asyncio -import json -import uuid -from typing import Any, AsyncIterator, Dict, List, Literal, Optional, Union, cast -from uuid import UUID - -from langchain.callbacks.base import AsyncCallbackHandler -from langchain.schema import AgentFinish, BaseMessage, LLMResult, _message_to_dict - -from openagent.agent.ctx_var import chat_req_ctx, resp_msg_id -from openagent.db.database import DBSession -from openagent.db.models import ChatHistory -from openagent.dto.cb_content import CbContent, CbContentType - - -class StreamCallbackHandler(AsyncCallbackHandler): - queue: asyncio.Queue[CbContent] - - done: asyncio.Event - is_on_chain_start_called: bool = False - - current_llm_block_id: Optional[str] = None - current_tool_block_id: Optional[str] = None - - current_tool_start_content: Optional[dict] = None - - @property - def always_verbose(self) -> bool: - return True - - def __init__(self) -> None: - self.queue = asyncio.Queue() - self.done = asyncio.Event() - - async def on_llm_start( - self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any - ) -> None: - # If two calls are made in a row, this resets the state - self.done.clear() - self.current_llm_block_id = str(uuid.uuid4()) - - async def on_llm_end( - self, - response: LLMResult, - *, - run_id: UUID, - parent_run_id: Optional[UUID] = None, - tags: Optional[List[str]] = None, - **kwargs: Any, - ) -> None: - output_str = response.generations[0][0].text - if output_str is None or output_str == "": - return - - with DBSession() as db_session: - msg_id = resp_msg_id.get() - chat_req = chat_req_ctx.get() - - ai_message = BaseMessage( - content=output_str, - type="ai", - additional_kwargs={"block_id": self.current_llm_block_id}, - ) - db_session.add( - ChatHistory( - user_id=chat_req.user_id, - message_id=msg_id, - session_id=chat_req.session_id, - message=json.dumps(_message_to_dict(ai_message)), - ) - ) - db_session.commit() - - async def on_llm_new_token(self, token: str, **kwargs: Any) -> None: - if token is not None and token != "": - self.queue.put_nowait( - CbContent( - content=token, - type=CbContentType.llm_content, - block_id=self.current_llm_block_id, - ) - ) - - async def on_chain_start( - self, - serialized: Dict[str, Any], - inputs: Dict[str, Any], - *, - run_id: UUID, - parent_run_id: Optional[UUID] = None, - tags: Optional[List[str]] = None, - metadata: Optional[Dict[str, Any]] = None, - **kwargs: Any, - ) -> None: - if self.is_on_chain_start_called: - return - - self.is_on_chain_start_called = True - with DBSession() as db_session: - chat_req = chat_req_ctx.get() - human_message = BaseMessage( - content=inputs["input"], - type="human", - additional_kwargs={"block_id": str(uuid.uuid4())}, - ) - db_session.add( - ChatHistory( - user_id=chat_req.user_id, - message_id=chat_req.message_id, - session_id=chat_req.session_id, - message=json.dumps(_message_to_dict(human_message)), - ) - ) - db_session.commit() - - def show_tool_block(self, tool_name) -> bool: - if tool_name in [ - "token", - "swap", - "transfer", - "collection", - "network", - "feed", - "dapp", - "account", - "executor", - ]: - return True - return False - - async def on_tool_start( - self, - serialized: Dict[str, Any], - input_str: str, - *, - run_id: UUID, - parent_run_id: Optional[UUID] = None, - tags: Optional[List[str]] = None, - metadata: Optional[Dict[str, Any]] = None, - **kwargs: Any, - ) -> None: - tool_name = serialized["name"] - show = self.show_tool_block(tool_name) - if not show: - return - self.current_tool_block_id = str(uuid.uuid4()) - - try: - tool_input = json.loads(input_str.replace("'", '"')) - except Exception: - tool_input = "" - await self.queue.put( - CbContent( - content={ - "tool_name": tool_name, - "input": tool_input, - }, - type=CbContentType.tool_content, - block_id=self.current_tool_block_id, - ) - ) - - self.current_tool_start_content = tool_input - - async def on_tool_end( - self, - output: str, - *, - run_id: UUID, - parent_run_id: Optional[UUID] = None, - tags: Optional[List[str]] = None, - **kwargs: Any, - ) -> None: - tool_name = kwargs["name"] - show = self.show_tool_block(tool_name) - if not show: - return - try: - end_index = output.rfind("}") - output_str = output[: end_index + 1] - output_json = json.loads(output_str) - except Exception: - output_json = json.loads(output) - - await self.queue.put( - CbContent( - content={"tool_name": tool_name, "output": output_json}, - type=CbContentType.tool_content, - block_id=self.current_tool_block_id, - ) - ) - with DBSession() as db_session: - msg_id = resp_msg_id.get() - chat_req = chat_req_ctx.get() - ai_message = BaseMessage( - content=json.dumps( - { - "tool_name": tool_name, - "output": output_json, - "input": self.current_tool_start_content, - } - ), - type="tool", - additional_kwargs={"block_id": self.current_tool_block_id}, - ) - db_session.add( - ChatHistory( - user_id=chat_req.user_id, - message_id=msg_id, - session_id=chat_req.session_id, - message=json.dumps(_message_to_dict(ai_message)), - ) - ) - db_session.commit() - - async def on_agent_finish( - self, - finish: AgentFinish, - *, - run_id: UUID, - parent_run_id: Optional[UUID] = None, - tags: Optional[List[str]] = None, - **kwargs: Any, - ) -> None: - self.done.set() - - async def on_llm_error( - self, - error: BaseException, - *, - run_id: UUID, - parent_run_id: Optional[UUID] = None, - tags: Optional[List[str]] = None, - **kwargs: Any, - ) -> None: - self.done.set() - return await super().on_llm_error( - error, run_id=run_id, parent_run_id=parent_run_id, tags=tags, **kwargs - ) - - # TODO implement the other methods - - async def aiter(self) -> AsyncIterator[CbContent]: - while not self.queue.empty() or not self.done.is_set(): - # Wait for the next token in the queue, - # but stop waiting if the done event is set - done, other = await asyncio.wait( - [ - # NOTE: If you add other tasks here, update the code below, - # which assumes each set has exactly one task each - asyncio.ensure_future(self.queue.get()), - asyncio.ensure_future(self.done.wait()), - ], - return_when=asyncio.FIRST_COMPLETED, - ) - - # Cancel the other task - if other: - other.pop().cancel() - - # Extract the value of the first completed task - token_or_done = cast(Union[CbContent, Literal[True]], done.pop().result()) - - # If the extracted value is the boolean True, the done event was set - if token_or_done is True: - break - - # Otherwise, the extracted value is a token, which we yield - yield token_or_done diff --git a/src/openagent/agent/suggested_question.py b/src/openagent/agent/suggested_question.py deleted file mode 100644 index ab5991e2..00000000 --- a/src/openagent/agent/suggested_question.py +++ /dev/null @@ -1,63 +0,0 @@ -import json - -from dotenv import load_dotenv -from langchain.chains import LLMChain -from langchain.prompts import PromptTemplate -from langchain_community.chat_models import ChatOllama -from langchain_google_vertexai import ChatVertexAI -from langchain_openai import ChatOpenAI -from loguru import logger - -from openagent.conf.env import settings - -load_dotenv() - - -async def agen_suggested_questions(user_id: str, history: str) -> list[str]: - prompt = PromptTemplate( - template=""" -Suggest follow up questions based on the user chat history. - -Return Format: -["question1", "question2", "question3"] - -Example: - -Q: -eth price? -A: -["What is the price of BTC?", "What is ETH?", "Can you list some hot tokens on Ethereum?"] - -Q: -what is the price of BTC? -A: -["What is the price of ETH?", "What is the price of BTC?", "Can you list some hot tokens on Ethereum?"] - ------------------------------------------------------------------ -Q: -{history} -A:""", # noqa - input_variables=["history"], - ) - if settings.MODEL_NAME.startswith("gpt"): - model = ChatOpenAI( - model=settings.MODEL_NAME, - openai_api_base=settings.LLM_API_BASE, - temperature=0.5, - ) - elif settings.MODEL_NAME.startswith("gemini"): - model = ChatVertexAI( - model_name=settings.MODEL_NAME, project=settings.PROJECT_ID, temperature=0.5 - ) - else: - model = ChatOllama(model=settings.MODEL_NAME, base_url=settings.LLM_API_BASE) - interpreter = LLMChain(llm=model, prompt=prompt) - logger.info(f"start to generate suggested questions based on history: {history}") - output = await interpreter.arun( - history=history, - ) - logger.info(f"suggested questions generated: {output}") - # parse output, it's json array str - lst = json.loads(output) - logger.info(f"suggested questions parsed: {lst}") - return lst diff --git a/src/openagent/app.py b/src/openagent/app.py index 8cbf815b..89fd7762 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -8,9 +8,6 @@ from starlette.responses import FileResponse, JSONResponse from starlette.staticfiles import StaticFiles -from openagent.router.chat import chat_router -from openagent.router.onboarding import onboarding_router -from openagent.router.session import session_router load_dotenv() app = FastAPI(title="OpenAgent", description="") @@ -28,12 +25,6 @@ async def health_check(): return JSONResponse(content={"status": "ok"}) - -app.include_router(onboarding_router) -app.include_router(chat_router) -app.include_router(session_router) - - @app.get("/widget/swap") async def swap_root(): print("swap_root") diff --git a/src/openagent/conf/env.py b/src/openagent/conf/env.py index b87cc16c..d3674390 100644 --- a/src/openagent/conf/env.py +++ b/src/openagent/conf/env.py @@ -1,20 +1,40 @@ -from typing import Optional +from typing import Optional, List from dotenv import load_dotenv -from pydantic import Field +from pydantic import Field, field_validator from pydantic_settings import BaseSettings load_dotenv() class Settings(BaseSettings): - MODEL_NAME: str = Field(default="gemini-1.5-pro", env="MODEL_NAME") - LLM_API_BASE: Optional[str] = Field(default=None) - PROJECT_ID: Optional[str] = Field(default=None) - NFTSCAN_API_KEY: str = Field(..., env="NFTSCAN_API_KEY") - DB_CONNECTION: str = Field(..., env="DB_CONNECTION") - RSS3_DATA_API: str = Field(default="https://testnet.rss3.io/data", env="RSS3_DATA_API") - RSS3_SEARCH_API: str = Field(default="https://devnet.rss3.io/search", env="RSS3_SEARCH_API") + # PGVector connection string + DB_CONNECTION: str = Field(..., env="DB_CONNECTION", description="PGVector connection string") + + # Online LLM API KEY + VERTEX_PROJECT_ID: Optional[str] = Field(default=None, + description="Google cloud vertex project id (optional)") + OPENAI_API_KEY: Optional[str] = Field(default=None, env="OPENAI_API_KEY", + description="OpenAI API Key (optional)") + # Local LLM configuration + OLLAMA_MODEL: Optional[List[str]] = Field(default=None, env="OLLAMA_MODEL", + description="OLLAMA Model list (optional)") + OLLAMA_MODEL_URL: Optional[str] = Field(default=None, env="OLLAMA_MODEL_URL", + description="OLLAMA Model URL (optional)") + + # Tool API Keys + NFTSCAN_API_KEY: Optional[str] = Field(..., env="NFTSCAN_API_KEY", description="NFTScan API Key (optional)") + RSS3_DATA_API: Optional[str] = Field(default="https://testnet.rss3.io/data", env="RSS3_DATA_API", + description="RSS3 Data API with a default value") + RSS3_SEARCH_API: Optional[str] = Field(default="https://devnet.rss3.io/search", env="RSS3_SEARCH_API", + description="RSS3 Search API with a default value") + + # Validator to split comma-separated string into a list + @field_validator("OLLAMA_MODEL", mode="before") + def split_string(cls, v): + if isinstance(v, str): + return v.split(',') + return v settings = Settings() diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py new file mode 100644 index 00000000..2af0f9f4 --- /dev/null +++ b/src/openagent/conf/llm_provider.py @@ -0,0 +1,22 @@ +import os + +from langchain_openai import ChatOpenAI +from langchain_google_vertexai import ChatVertexAI +from dotenv import load_dotenv + +from openagent.conf.env import settings + + +def build_providers(): + providers = {} + if settings.OPENAI_API_KEY: + providers['gpt-3.5-turbo'] = ChatOpenAI(model="gpt-3.5-turbo") + providers['gpt-4o'] = ChatOpenAI(model="gpt-4o") + + if settings.VERTEX_PROJECT_ID: + providers['gemini-1.5-pro'] = ChatVertexAI(model="gemini-1.5-pro") + return providers + + +if __name__ == '__main__': + print(build_providers()) diff --git a/src/openagent/db/database.py b/src/openagent/db/database.py index 54673dfe..87e7e1fa 100644 --- a/src/openagent/db/database.py +++ b/src/openagent/db/database.py @@ -15,6 +15,3 @@ DBSession = sessionmaker(bind=engine) -if __name__ == "__main__": - with DBSession() as sess: - print(sess.query(User).all()) diff --git a/src/openagent/db/models.py b/src/openagent/db/models.py index 4ee07ac3..4c76538f 100644 --- a/src/openagent/db/models.py +++ b/src/openagent/db/models.py @@ -9,50 +9,6 @@ Base = declarative_base() # type: ignore - -class ChatHistory(Base): # type: ignore - __tablename__ = "chat_history" - - id = Column(Integer, primary_key=True, autoincrement=True) - user_id = Column(String(255), nullable=False) - session_id = Column(String(255), nullable=False) - message_id = Column(String(255), nullable=False) - message = Column(Text, nullable=False) - send_at = Column(DateTime(timezone=True), server_default=func.now()) - - -class ChatSession(Base): # type: ignore - __tablename__ = "chat_session" - - id = Column(Integer, primary_key=True, autoincrement=True) - user_id = Column(String(255), nullable=False) - session_id = Column(String(255), nullable=False, unique=True) - title = Column(String(255), nullable=True) - created_at = Column(DateTime(timezone=True), server_default=func.now()) - deleted_at = Column(DateTime(timezone=True), nullable=True) - parent_id = Column(String(255), nullable=True, default=None) - order = Column(Integer, nullable=True, default=0) - type = Column(String(255), nullable=True, default="session") - tab = Column(String(255), nullable=True, default="recent") - - -class Task(Base): # type: ignore - __tablename__ = "task" - - id = Column(Integer, primary_key=True, autoincrement=True) - user_id = Column(String(255), nullable=False) - session_id = Column(String(255), nullable=False) - task_id = Column(String(255), nullable=False, unique=True) - type = Column(String(255), nullable=False) - body = Column(Text, nullable=False) - status = Column(String(255), nullable=False, default=TaskStatus.running) - created_at = Column(DateTime(timezone=True), server_default=func.now()) - run_at = Column(DateTime(timezone=True), nullable=True) - done_at = Column(DateTime(timezone=True), nullable=True) - hash = Column(String(255), nullable=True) - is_notified = Column(Boolean, nullable=False, default=False) - - class User(Base): # type: ignore __tablename__ = "users" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) diff --git a/src/openagent/dto/__init__.py b/src/openagent/dto/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/openagent/dto/cb_content.py b/src/openagent/dto/cb_content.py deleted file mode 100644 index bae3026e..00000000 --- a/src/openagent/dto/cb_content.py +++ /dev/null @@ -1,19 +0,0 @@ -from enum import Enum - -from pydantic import BaseModel - - -class CbContentType(str, Enum): - llm_content = "llm_content" - tool_content = "tool_content" - - -class CbToolContent(BaseModel): - content: object - tool_name: str - - -class CbContent(BaseModel): - type: CbContentType - content: object - block_id: str | None = None diff --git a/src/openagent/dto/chat_history.py b/src/openagent/dto/chat_history.py deleted file mode 100644 index ef371b38..00000000 --- a/src/openagent/dto/chat_history.py +++ /dev/null @@ -1,108 +0,0 @@ -import json -from datetime import datetime -from enum import Enum - -from pydantic import BaseModel -from toolz.curried import groupby - -from openagent.dto.chat_req import ChatReqType -from openagent.dto.chat_resp import ChatRespType - - -class ChatSession(BaseModel): # type: ignore - session_id: str - title: str | None - - @classmethod - def from_orm(cls, obj): - return ChatSession( - session_id=obj.session_id, - title=obj.title, - ) - - -class ChatMessageRole(str, Enum): - ai = "ai" - human = "human" - - @classmethod - def from_type(cls, type0: str): - if type0 == "ai": - return ChatMessageRole.ai - if type0 == "human": - return ChatMessageRole.human - if type0 == "tool": - return ChatMessageRole.ai - raise ValueError(f"Unknown role: {type0}") - - -class ChatMessageContent(BaseModel): # type: ignore - type: ChatRespType | ChatReqType - block_id: str | None = None - body: object - - -class ChatMessage(BaseModel): # type: ignore - message_id: str - role: ChatMessageRole - content: list[ChatMessageContent] - send_at: datetime - - @classmethod - def from_orm(cls, entities): - msg_id2msgs = groupby(lambda x: x.message_id, entities) - - res = [] - skip_msg_ids = set() - for entity in entities: - if entity.message_id in skip_msg_ids: - continue - else: - skip_msg_ids.add(entity.message_id) - msgs = msg_id2msgs[entity.message_id] - first_msg = msgs[0] - first_msg_json = json.loads(first_msg.message) - contents = [] - for msg in msgs: - msg_type = None - msg_json = json.loads(msg.message) - lc_msg_type = msg_json["type"] - if lc_msg_type in ["ai", "human"]: - msg_type = "natural_language" - if lc_msg_type == "tool": - msg_type = "tool" - - block_id = msg_json["data"]["additional_kwargs"]["block_id"] - - contents.append( - ChatMessageContent( - block_id=block_id, - type=msg_type, - body=to_json(msg_json["data"]["content"]), - ) - ) - - # reverse the order of contents - contents.reverse() - res.append( - ChatMessage( - message_id=first_msg.message_id, - role=ChatMessageRole.from_type(first_msg_json["type"]), - content=contents, - send_at=first_msg.send_at, - ) - ) - - return res - - -def to_json(obj): - try: - return json.loads(obj) - except Exception: - return obj - - -class ChatHistory(BaseModel): - title: str | None - messages: list[ChatMessage] diff --git a/src/openagent/dto/chat_req.py b/src/openagent/dto/chat_req.py deleted file mode 100644 index 9ae3fb57..00000000 --- a/src/openagent/dto/chat_req.py +++ /dev/null @@ -1,16 +0,0 @@ -from enum import Enum - -from pydantic import BaseModel, Field - - -class ChatReqType(str, Enum): - natural_language = "natural_language" - order_placement_request = "order_placement_request" - - -class ChatReq(BaseModel): - session_id: str = Field(example="1234567890") - message_id: str = Field(example="1234567890") - user_id: str = Field(example="clnx2bsgi000008l68gxi8q72") - type: ChatReqType = Field(example="natural_language") - body: str = Field(example="transfer 0.001 ct to vitalik.eth") diff --git a/src/openagent/dto/chat_resp.py b/src/openagent/dto/chat_resp.py deleted file mode 100644 index 1b82912d..00000000 --- a/src/openagent/dto/chat_resp.py +++ /dev/null @@ -1,19 +0,0 @@ -from enum import Enum - -from pydantic import BaseModel - - -class ChatRespType(str, Enum): - natural_language = "natural_language" - order_placement_inquiry = "order_placement_inquiry" - suggested_questions = "suggested_questions" - session_title = "session_title" - tool = "tool" - error = "error" - - -class ChatResp(BaseModel): - message_id: str | None - block_id: str | None = None - type: ChatRespType - body: object diff --git a/src/openagent/dto/error.py b/src/openagent/dto/error.py deleted file mode 100644 index 46dfe6f3..00000000 --- a/src/openagent/dto/error.py +++ /dev/null @@ -1,7 +0,0 @@ -from pydantic import BaseModel, Field - - -class ErrorResp(BaseModel): - code: int - data: object = Field(default="") - message: str diff --git a/src/openagent/dto/mutation.py b/src/openagent/dto/mutation.py deleted file mode 100644 index ec9eaaaa..00000000 --- a/src/openagent/dto/mutation.py +++ /dev/null @@ -1,22 +0,0 @@ -from pydantic import BaseModel - - -class Swap(BaseModel): - from_token: str - from_token_address: str - to_token: str - to_token_address: str - chain_id: str - amount: str - type: str = "swap" - - -class Transfer(BaseModel): - # task_id: str - to_address: str - token: str - token_address: str - chain_id: str - amount: str - logoURI: str # noqa - decimals: int diff --git a/src/openagent/dto/session.py b/src/openagent/dto/session.py deleted file mode 100644 index 82eb7521..00000000 --- a/src/openagent/dto/session.py +++ /dev/null @@ -1,113 +0,0 @@ -from datetime import datetime -from enum import Enum -from typing import ClassVar - -from pydantic import BaseModel, Field - -from openagent.db.models import ChatSession - - -class SessionTreeNodeDTOType(str, Enum): - folder = "folder" - session = "session" - - -class SessionTreeNodeDTO(BaseModel): - session_id: str = Field(description="session id") - parent_id: str | None = Field( - example=None, default=None, description="parent id, if null, is root folder" - ) - title: str | None = Field(default=None, description="session title") - order: int = Field( - description="order in parent folder, session will sort by order desc" - ) - created_at: datetime = Field(description="create time") - children: list | None = [] - type: SessionTreeNodeDTOType = SessionTreeNodeDTOType.folder - - def __hash__(self): - return hash(self.session_id) ^ hash(self.type) - - def __lt__(self, other): - # sort by type , folder first, order asc, created_at desc - if self.type != other.type: - return self.type == SessionTreeNodeDTOType.folder - if self.order != other.order: - return self.order > other.order - return self.created_at < other.created_at - - -def build_session_tree_node(node: ChatSession) -> SessionTreeNodeDTO: - return SessionTreeNodeDTO( - session_id=node.session_id, - title=node.title, - order=node.order, - parent_id=node.parent_id, - created_at=node.created_at, - type=node.type, - ) - - -class NewSessionFolderDTO(BaseModel): - user_id: str = Field(example="jackma") - title: str = Field(example="folder1") - order: int = Field( - example=1, description="order in parent folder, session will sort by order desc" - ) - parent_id: str | None = Field( - example=None, - default=None, - description="parent id, if null, will create root folder", - ) - - class Config: - json_schema_extra: ClassVar = { - "example": {"user_id": "jackma", "title": "folder1", "order": 0} - } - - -class SessionTab(str, Enum): - favorite = "favorite" - recent = "recent" - - -class UpdateSessionDTO(BaseModel): - user_id: str = Field(example="jackma") - session_id: str = Field(example="1234567890") - title: str | None = Field( - example=None, - default=None, - description="session title, if null, will not update", - ) - order: int | None = Field( - example=None, - default=None, - description="session order, if null, will not update", - ) - tab: SessionTab | None = Field( - example=None, - default=None, - description="session tab, if null, will not update", - ) - parent_id: str | None = Field( - example=None, - default=None, - description="parent id, if null, will not update", - ) - - -class MoveSessionDTO(BaseModel): - user_id: str = Field(description="user id", example="jackma") - from_session_id: str = Field(description="source session id", example="1234567890") - to_session_tab: SessionTab = Field( - description="target tab, favorite or recent. " - "if recent, to_session_id will be ignored", - example="favorite", - ) - to_session_id: str | None = Field( - description="target parent session id, only valid when" - " to_session_tab is favorite, if null, " - "will move to root folder", - example="0987654321", - default=None, - ) diff --git a/src/openagent/dto/task.py b/src/openagent/dto/task.py deleted file mode 100644 index 5dbafe4c..00000000 --- a/src/openagent/dto/task.py +++ /dev/null @@ -1,87 +0,0 @@ -from datetime import datetime -from enum import Enum - -from pydantic import BaseModel, Field - - -class TransferDTO(BaseModel): - user_id: str = Field(description="user id", example="clnx2bsgi000008l68gxi8q72") - task_id: str = Field(description="task id", example="1") - executor_id: int = Field(description="executor id", example=1) - to_address: str = Field( - description="address to transfer", - example="0xFcf62726dbf3a9C2765f138111AA04Bf50bD67D6", - ) - amount: str = Field(description="amount to transfer", example="0.001") - token_address: str = Field( - description="token address", - example="0x4d2bf3A34a2311dB4b3D20D4719209EDaDBf69b6", - ) - token: str = Field(description="token", example="ETH") - logoURI: str - decimals: int - - -class ConfirmTransferDTO(BaseModel): - user_id: str = Field(description="user id", example="clnx2bsgi000008l68gxi8q72") - task_id: str = Field(description="task id", example="1") - executor_id: int = Field(description="executor id", example=1) - to_address: str = Field( - description="address to transfer", - example="0xFcf62726dbf3a9C2765f138111AA04Bf50bD67D6", - ) - amount: str = Field(description="amount to transfer", example="0.001") - token_address: str = Field( - description="token address", - example="0x4d2bf3A34a2311dB4b3D20D4719209EDaDBf69b6", - ) - - -class CancelTransferDTO(BaseModel): - user_id: str = Field(description="user id", example="clnx2bsgi000008l68gxi8q72") - task_id: str = Field(description="task id", example="1") - - -class TransferQueryDTO(BaseModel): - executor_id: int = Field(description="executor id", example=1) - to_address: str = Field( - description="address to transfer", - example="0xFcf62726dbf3a9C2765f138111AA04Bf50bD67D6", - ) - amount: str = Field(description="amount to transfer", example="0.001") - token_address: str = Field( - description="token address", - example="0x4d2bf3A34a2311dB4b3D20D4719209EDaDBf69b6", - ) - token: str = Field(description="token", example="ETH") - logoURI: str | None = Field( - description="logo uri", example="https://li.quest/logo.png" - ) - decimals: int | None = Field(description="decimals", example=18) - - -class TaskStatus(str, Enum): - idle = "idle" - pending = "pending" - running = "running" - done = "done" - canceled = "canceled" - failed = "failed" - - -class TaskType(str, Enum): - transfer = "transfer" - # swap = "swap" - - -class TaskDTO(BaseModel): - task_id: str - user_id: str - session_id: str - type: TaskType - body: TransferQueryDTO | object = None - status: TaskStatus - created_at: datetime - hash: str | None = None - run_at: datetime | None = None - done_at: datetime | None = None diff --git a/src/openagent/index/pgvector_store.py b/src/openagent/index/pgvector_store.py index cc50e32c..08d9b3f7 100644 --- a/src/openagent/index/pgvector_store.py +++ b/src/openagent/index/pgvector_store.py @@ -11,7 +11,7 @@ def build_vector_store() -> PGVector: collection_name = "backend" if settings.MODEL_NAME.startswith("gemini"): - underlying_embeddings = VertexAIEmbeddings(model_name="textembedding-gecko@003", project=settings.PROJECT_ID) + underlying_embeddings = VertexAIEmbeddings(model_name="textembedding-gecko@003", project=settings.VERTEX_PROJECT_ID) else: underlying_embeddings = OpenAIEmbeddings(model="text-embedding-3-large") return PGVector( diff --git a/src/openagent/router/__init__.py b/src/openagent/router/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/openagent/router/chat.py b/src/openagent/router/chat.py deleted file mode 100644 index fbe55272..00000000 --- a/src/openagent/router/chat.py +++ /dev/null @@ -1,16 +0,0 @@ -from fastapi import APIRouter -from loguru import logger -from sse_starlette import EventSourceResponse - -from openagent.dto.chat_req import ChatReq -from openagent.dto.chat_resp import ChatResp -from openagent.service.chat import answer - -chat_router = APIRouter(tags=["Chat"]) - - -@chat_router.post("/stream_chat/", response_model=ChatResp) -async def stream_chat(req: ChatReq) -> EventSourceResponse: - logger.info(f"Received request: req={req}") - generator = answer(req) - return EventSourceResponse(generator) diff --git a/src/openagent/router/onboarding.py b/src/openagent/router/onboarding.py deleted file mode 100644 index 72574f39..00000000 --- a/src/openagent/router/onboarding.py +++ /dev/null @@ -1,56 +0,0 @@ -import json -import re -import uuid - -from fastapi import APIRouter -from loguru import logger -from sse_starlette import EventSourceResponse - -from openagent.dto.chat_req import ChatReq -from openagent.dto.chat_resp import ChatResp - -onboarding_router = APIRouter(tags=["Onboarding"]) - -introduction_text = """\ -Hey there, digital explorer! 🚀 I'm OpenAgent, your trusty sidekick in the vast and vibrant universe of web3! 🌐✨ - -What can I do, you ask? Well, buckle up because I'm here to navigate you through the cosmic maze of blockchain networks, tokens, NFTs, and decentralized applications (dApps). Whether you're looking to trade some tokens, transfer some crypto to your buddy, or just curious about the latest NFT craze, I've got your back! - -Here's a quick rundown of my superpowers: - -- **Token Transfer**: Need to send some USDC to a friend? I'll guide your transaction to its destination faster than a shooting star! 🌠💸 -- **Blockchain Intel**: Curious about the gas prices on Ethereum or the block height on Binance Smart Chain? I'll fetch that info like a space hound chasing a comet! 🐕🌠 -- **NFT Insights**: Wondering what's hot in the NFT universe? I'll bring you market caps, floor prices, and the most popular NFTs out there! 🖼️📈 -- **DApp Discovery**: Looking for the next DeFi gem or a social dApp to connect with fellow spacefarers? I'll be your guide to the decentralized cosmos! 🌌🔍 -- **Crypto Queries**: Got questions about token prices or market caps? I'm like a crypto-encyclopedia with the latest data! 📚💹 - -So, if you're ready to embark on a web3 adventure, just hit me up and let's make some interstellar magic happen! And remember, I'm here to keep things fun and lively, so don't be surprised if I drop a pun or two along the way! 🎉👾 -""" # noqa: E501 - -suggested_questions = [ - "What's the current gas price on Ethereum?", - "Can you show me the latest transactions for vitalik.eth?", - "What's the floor price of the Bored Ape Yacht Club NFT collection?", - "How much is 1 ETH in USDT right now?", - "Tell me about the defi project with the highest TVL.", - "Who are the popular users on Uniswap?", - "Can you help me transfer 0.1 $ETH to vitalik.eth?", -] - - -def generate_stream(): - unique_message_id = str(uuid.uuid4()) - - tokens = re.findall(r"\S+\s*", introduction_text) - - for token in tokens: - yield f'{{"message_id":"{unique_message_id}","block_id":null,"type":"natural_language","body":{json.dumps(token)}}}' # noqa: E501 - - questions_json = json.dumps(suggested_questions) - yield f'{{"message_id":"{unique_message_id}","block_id":null,"type":"suggested_questions","body":{questions_json}}}' # noqa: E501 - - -@onboarding_router.post("/onboarding/", response_model=ChatResp) -async def onboarding(req: ChatReq): - logger.info(f"Received request: req={req}") - return EventSourceResponse(generate_stream()) diff --git a/src/openagent/router/session.py b/src/openagent/router/session.py deleted file mode 100644 index 62c07a56..00000000 --- a/src/openagent/router/session.py +++ /dev/null @@ -1,110 +0,0 @@ -from fastapi import APIRouter, Query -from fastapi.responses import JSONResponse -from loguru import logger -from sqlalchemy.exc import NoResultFound -from starlette import status - -from openagent.dto.chat_history import ChatHistory, ChatSession -from openagent.dto.error import ErrorResp -from openagent.dto.session import ( - NewSessionFolderDTO, - SessionTreeNodeDTO, - UpdateSessionDTO, -) -from openagent.service.history import ( - delete_histories, - get_histories, -) -from openagent.service.history import get_recent_sessions as get_recent_sessions0 -from openagent.service.session import ( - create_session_folder as create_session_folder0, -) -from openagent.service.session import ( - get_session_tree as get_session_tree0, -) -from openagent.service.session import ( - update_session as update_session0, -) - -session_router = APIRouter(tags=["Session"]) - - -@session_router.get("/sessions/tab/recent", response_model=list[ChatSession]) -async def get_recent_sessions( - user_id: str = Query(example="jackma"), offset: int = 0, limit: int = 50 -) -> list[str]: - logger.info(f"Received request: user_id={user_id}, offset={offset}, limit={limit}") - return get_recent_sessions0(user_id, offset, limit) - - -@session_router.get("/sessions/tab/favorites", response_model=list[SessionTreeNodeDTO]) -async def get_favorite_session_tree(user_id: str = Query(example="jackma")): - logger.info(f"Received request: user_id={user_id}") - return get_session_tree0(user_id) - - -@session_router.get( - "/sessions/{user_id}/{session_id}", response_model=ChatHistory | ErrorResp -) -async def get_session_chat_history( - user_id: str, session_id: str, offset: int = 0, limit: int = 50 -): - logger.info( - f"Received request: user_id={user_id}, session_id={session_id},\ -offset={offset}, limit={limit}" - ) - try: - return get_histories(user_id, session_id, offset, limit) - except NoResultFound: - return JSONResponse( - status_code=status.HTTP_400_BAD_REQUEST, - content=ErrorResp(code=400, message="Not found").dict(), - ) - - -@session_router.patch( - "/sessions/update_session", -) -async def update_session_partially(update_session_dto: UpdateSessionDTO): - try: - title = update_session_dto.title - order = update_session_dto.order - user_id = update_session_dto.user_id - session_id = update_session_dto.session_id - tab = update_session_dto.tab - parent_id = update_session_dto.parent_id - logger.info( - f"Received request: user_id={user_id}, session_id={session_id}, \ -title={title}, order={order}, tab={tab}, parent_id={parent_id}" - ) - update_session0(user_id, session_id, title, order, tab, parent_id) - except Exception as e: - return JSONResponse( - status_code=status.HTTP_400_BAD_REQUEST, - content=ErrorResp(code=400, message=e.__str__()).dict(), - ) - - -@session_router.delete("/sessions/{user_id}/{session_id}") -async def delete_session_by_id(user_id: str, session_id: str): - logger.info(f"Received request: user_id={user_id}, session_id={session_id}") - delete_histories(user_id, session_id) - - -@session_router.post("/sessions/create_session_folder") -async def create_session_folder(folder: NewSessionFolderDTO): - try: - user_id = folder.user_id - title = folder.title - parent_id = folder.parent_id - order = folder.order - logger.info( - f"Received request: user_id={user_id}, title={title}, \ -parent_id={parent_id}, order={order}" - ) - create_session_folder0(user_id, title, parent_id, order) - except Exception as e: - return JSONResponse( - status_code=status.HTTP_400_BAD_REQUEST, - content=ErrorResp(code=400, message=e.__str__()).dict(), - ) diff --git a/src/openagent/service/__init__.py b/src/openagent/service/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/openagent/service/chat.py b/src/openagent/service/chat.py deleted file mode 100644 index 92e30846..00000000 --- a/src/openagent/service/chat.py +++ /dev/null @@ -1,159 +0,0 @@ -import asyncio -import uuid -from typing import Any, AsyncIterable - -from sqlalchemy.exc import NoResultFound - -from openagent.agent.ctx_var import chat_req_ctx, resp_msg_id -from openagent.agent.function_agent import get_agent -from openagent.agent.session_title import agen_session_title -from openagent.agent.stream_callback import StreamCallbackHandler -from openagent.agent.suggested_question import agen_suggested_questions -from openagent.db.database import DBSession -from openagent.db.models import ChatHistory, ChatSession -from openagent.dto.cb_content import CbContent, CbContentType -from openagent.dto.chat_req import ChatReq -from openagent.dto.chat_resp import ChatResp, ChatRespType - - -async def arun_agent( - req: ChatReq, stream_cb: StreamCallbackHandler, resp_msg_id0: str -) -> Any: - agent = get_agent(req.session_id) - resp_msg_id.set(resp_msg_id0) - chat_req_ctx.set(req) - - return await agent.ainvoke( - { - "input": req.body, - }, - config={ - "metadata": {"agentName": "openagent-backend", "userId": req.user_id}, - "callbacks": [stream_cb], - }, - ) - - -async def answer(req: ChatReq) -> AsyncIterable[str]: - try: - create_session = await need_create_session(req) - except Exception as e: - yield ChatResp( - type=ChatRespType.error, message_id=None, body=e.__str__() - ).model_dump_json() - return - - stream_cb = StreamCallbackHandler() - - resp_msg_id0 = str(uuid.uuid4()) - - chat_task = asyncio.create_task(arun_agent(req, stream_cb, resp_msg_id0)) - - suggested_questions_task = asyncio.create_task( - agen_suggested_questions(req.user_id, req.body) - ) - - session_title_task = None - if create_session: - session_title_task = asyncio.create_task( - agen_session_title(req.user_id, req.session_id, req.body) - ) - - try: - is_suggested_questions_done = False - is_session_title_done = False - async for cb_content in stream_cb.aiter(): - yield await gen_agent_resp(cb_content, resp_msg_id0) - - if suggested_questions_task.done() and not is_suggested_questions_done: - is_suggested_questions_done = True - yield await gen_suggested_questions( - suggested_questions_task, resp_msg_id0 - ) - - if ( - create_session - and session_title_task.done() # type: ignore - and not is_session_title_done - ): - is_session_title_done = True - yield await gen_session_title(resp_msg_id0, session_title_task) - - if not is_suggested_questions_done: - yield await gen_suggested_questions(suggested_questions_task, resp_msg_id0) - - if create_session and not is_session_title_done: - yield await gen_session_title(resp_msg_id0, session_title_task) - - except Exception as e: - print(f"Caught exception: {e}") - finally: - stream_cb.done.set() - await chat_task - - -async def gen_agent_resp(cb_content: CbContent, resp_msg_id0: str) -> str: - resp_type = get_resp_type(cb_content.type) - resp = ChatResp( - message_id=resp_msg_id0, - block_id=cb_content.block_id, - type=resp_type, - body=cb_content.content, - ) - return resp.model_dump_json() - - -async def gen_session_title(resp_msg_id0, session_title_task): - session_title = await session_title_task - return ChatResp( - message_id=resp_msg_id0, - type=ChatRespType.session_title, - body=session_title, - ).model_dump_json() - - -async def gen_suggested_questions(suggested_questions_task, resp_msg_id0): - questions = await suggested_questions_task - return ChatResp( - message_id=resp_msg_id0, - type=ChatRespType.suggested_questions, - body=questions, - ).model_dump_json() - - -def get_resp_type(cb_content_type: CbContentType) -> ChatRespType: - if cb_content_type == CbContentType.llm_content: - return ChatRespType.natural_language - if cb_content_type == CbContentType.tool_content: - return ChatRespType.tool - raise ValueError(f"Unknown cb_content_type: {cb_content_type}") - - -async def need_create_session(req: ChatReq) -> bool: - session_id = req.session_id - with DBSession() as db_session: - try: - session = ( - db_session.query(ChatSession) - .filter(ChatSession.session_id == session_id) - .one() - ) - if session.deleted_at is not None: - raise ValueError("Session is deleted") - if ( - db_session.query(ChatHistory) - .filter(ChatHistory.message_id == req.message_id) - .count() - > 0 - ): - raise ValueError("Message id already exists") - except NoResultFound: - db_session.add( - ChatSession( - session_id=session_id, - user_id=req.user_id, - ) - ) - db_session.commit() - return True - return False diff --git a/src/openagent/service/history.py b/src/openagent/service/history.py deleted file mode 100644 index de1b445a..00000000 --- a/src/openagent/service/history.py +++ /dev/null @@ -1,98 +0,0 @@ -from datetime import datetime - -from sqlalchemy import desc -from sqlalchemy.sql.operators import and_ -from toolz.curried import compose_left, map - -from openagent.db.database import DBSession -from openagent.db.models import ChatHistory, ChatSession -from openagent.dto.chat_history import ChatHistory as ChatHistoryDto -from openagent.dto.chat_history import ChatMessage as ChatMessageDto -from openagent.dto.chat_history import ChatSession as ChatSessionDto -from openagent.dto.session import SessionTab, SessionTreeNodeDTOType - - -def get_sessions(user_id: str, offset: int, limit: int): - with DBSession() as db_sess: - all0 = ( - db_sess.query(ChatSession) - .filter( - and_( - and_( - ChatSession.user_id == user_id, - ChatSession.deleted_at == None, - ), - ChatSession.type == SessionTreeNodeDTOType.session, - ) - ) - .order_by(desc("created_at")) - .limit(limit) - .offset(offset) - .all() - ) - return compose_left(map(ChatSessionDto.from_orm), list)(all0) - - -def get_recent_sessions(user_id: str, offset: int, limit: int): - with DBSession() as db_sess: - all0 = ( - db_sess.query(ChatSession) - .filter( - and_( - and_( - and_( - ChatSession.user_id == user_id, - ChatSession.deleted_at == None, - ), - ChatSession.tab == SessionTab.recent, - ), - ChatSession.type == SessionTreeNodeDTOType.session, - ) - ) - .order_by(desc("created_at")) - .limit(limit) - .offset(offset) - .all() - ) - return compose_left(map(ChatSessionDto.from_orm), list)(all0) - - -def get_histories( - user_id: str, session_id: str, offset: int, limit: int -) -> ChatHistoryDto: - with DBSession() as db_sess: - all0 = ( - db_sess.query(ChatHistory) - .filter( - and_( - ChatHistory.session_id == session_id, ChatHistory.user_id == user_id - ) - ) - .order_by(desc("send_at")) - .limit(limit) - .offset(offset) - .all() - ) - - msgs = ChatMessageDto.from_orm(all0) - - one = ( - db_sess.query(ChatSession) - .filter(ChatSession.session_id == session_id) - .one() - ) - return ChatHistoryDto( - title=one.title, - messages=msgs, - ) - - -def delete_histories(user_id: str, session_id: str): - with DBSession() as db_sess: - db_sess.query(ChatSession).filter( - and_( - ChatSession.session_id == session_id, - ChatSession.user_id == user_id, - ) - ).update({"deleted_at": datetime.utcnow()}) - db_sess.commit() diff --git a/src/openagent/service/session.py b/src/openagent/service/session.py deleted file mode 100644 index 466d5fb3..00000000 --- a/src/openagent/service/session.py +++ /dev/null @@ -1,254 +0,0 @@ -import uuid -from enum import Enum - -from sqlalchemy.exc import NoResultFound -from sqlalchemy.sql.operators import and_ -from toolz.curried import compose_left, map - -from openagent.db.database import DBSession -from openagent.db.models import ChatSession -from openagent.dto.session import ( - SessionTab, - SessionTreeNodeDTO, - SessionTreeNodeDTOType, - build_session_tree_node, -) - - -def create_session_folder( - user_id: str, title: str, parent_folder_id: str | None, order -): - with DBSession() as db_session: - if parent_folder_id is not None: - try: - _ = ( - db_session.query(ChatSession) - .filter( - and_( - ChatSession.type == SessionTreeNodeDTOType.folder, - and_( - ChatSession.user_id == user_id, - ChatSession.session_id == parent_folder_id, - ), - ) - ) - .one() - ) - except NoResultFound: - raise ValueError("Parent folder not found") - folder = ChatSession( - user_id=user_id, - title=title, - parent_id=parent_folder_id, - session_id=str(uuid.uuid4()), - order=order, - type=SessionTreeNodeDTOType.folder, - tab=SessionTab.favorite, - ) - db_session.add(folder) - db_session.commit() - - -def update_session( - user_id: str, - session_id: str, - title: str | None, - order: int | None, - tab: SessionTab | None, - parent_id: str | None, -): - with DBSession() as db_session: - try: - session = ( - db_session.query(ChatSession) - .filter( - and_( - ChatSession.user_id == user_id, - ChatSession.session_id == session_id, - ) - ) - .one() - ) - except NoResultFound: - raise ValueError("Session not found") - if title is not None: - session.title = title - if order is not None: - session.order = order - if tab is not None: - session.tab = tab - if parent_id is not None: - try: - parent_session = ( - db_session.query(ChatSession) - .filter( - and_( - ChatSession.user_id == user_id, - ChatSession.session_id == parent_id, - ) - ) - .one() - ) - if ( - parent_session.type == SessionTreeNodeDTOType.session - and session.type == SessionTreeNodeDTOType.folder - ): - raise ValueError("Can't move folder to session") - if parent_session.parent_id == session_id: - raise ValueError("Can't move folder to child") - if parent_session.deleted_at is not None: - raise ValueError("Parent session is deleted") - if session.deleted_at is not None: - raise ValueError("Session is deleted") - - except NoResultFound: - raise ValueError("Parent session not found") - session.parent_id = parent_id - db_session.commit() - return session - - -class SessionMoveDirection(str, Enum): - f2f = "favorite2favorite" - f2r = "favorite2recent" - r2f = "recent2favorite" - r2r = "recent2recent" - - -def calc_session_move_direction(from_session_tab, to_session_tab): - recent = SessionTab.recent - favorite = SessionTab.favorite - - if to_session_tab is recent and from_session_tab is recent: - return SessionMoveDirection.r2r - - if to_session_tab is favorite and from_session_tab is favorite: - return SessionMoveDirection.f2f - - if to_session_tab is favorite and from_session_tab is recent: - return SessionMoveDirection.r2f - - if to_session_tab is recent and from_session_tab is favorite: - return SessionMoveDirection.f2r - - -def move_session_folder( - user_id: str, - from_session_id: str, - to_session_id: str | None, - to_session_tab: SessionTab, -): - with DBSession() as db_session: - from_session = fetch_from_session(db_session, from_session_id, user_id) - - from_session_tab = from_session.tab - direction = calc_session_move_direction(from_session_tab, to_session_tab) - - if direction is SessionMoveDirection.r2r: - raise ValueError("Can't move recent to recent") - - if direction is SessionMoveDirection.f2r: - from_session.parent_id = None - from_session.tab = to_session_tab - db_session.commit() - return - - if ( - direction is SessionMoveDirection.f2f - or direction is SessionMoveDirection.r2f - ): - if to_session_id is None: - from_session.parent_id = None - from_session.tab = to_session_tab - db_session.commit() - return - - parent_session = fetch_parent_session(db_session, to_session_id, user_id) - - if parent_session.type == SessionTreeNodeDTOType.session: - raise ValueError("Can't move folder to session") - if parent_session.parent_id == from_session_id: - raise ValueError("Can't move folder to child") - - from_session.parent_id = to_session_id - db_session.commit() - - -def fetch_parent_session(db_session, to_session_id, user_id): - try: - parent_session = ( - db_session.query(ChatSession) - .filter( - and_( - ChatSession.user_id == user_id, - ChatSession.session_id == to_session_id, - ) - ) - .one() - ) - - except NoResultFound: - raise ValueError("Parent session not found") - return parent_session - - -def fetch_from_session(db_session, from_session_id, user_id): - try: - session = ( - db_session.query(ChatSession) - .filter( - and_( - ChatSession.user_id == user_id, - ChatSession.session_id == from_session_id, - ) - ) - .one() - ) - except NoResultFound: - raise ValueError("Session not found") - return session - - -def build_folder_tree( - nodes: list[SessionTreeNodeDTO], - parent_id: int | None = None, -): - unsorted_tree = do_build_folder_tree(nodes, parent_id) - return sorted(unsorted_tree) - - -def do_build_folder_tree(nodes, parent_id): - tree = [] - for node in nodes: - if node.parent_id == parent_id: - session_nodes = do_build_folder_tree(nodes, node.session_id) - node.children = build_sorted_children(node.children, session_nodes) - tree.append(node) - return tree - - -def build_sorted_children( - old_children: list[SessionTreeNodeDTO], new_children: list[SessionTreeNodeDTO] -): - old_children = old_children or [] - new_children = new_children or [] - unique_children = list(set(old_children + new_children)) - sorted_children = sorted( - unique_children, key=lambda x: (x.order, x.created_at), reverse=True - ) - return sorted_children - - -def get_session_tree(user_id: str) -> list[SessionTreeNodeDTO]: - with DBSession() as db_session: - sessions = ( - db_session.query(ChatSession) - .filter_by(user_id=user_id, deleted_at=None, tab=SessionTab.favorite) - .all() - ) - session_tree_nodes: list[SessionTreeNodeDTO] = compose_left( - map(build_session_tree_node), list - )(sessions) - - tree = build_folder_tree(session_tree_nodes) - return tree From 2dd619a99a220173355712b783b3b980938d402a Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jul 2024 16:12:35 +0800 Subject: [PATCH 03/85] feat: add multi agent --- src/openagent/agents/agent_factory.py | 16 ++++++ src/openagent/agents/asset_management.py | 21 +++++++ src/openagent/agents/block_explore.py | 22 ++++++++ src/openagent/agents/fallback.py | 33 +++++++++++ src/openagent/agents/market_analysis.py | 25 ++++++++ src/openagent/agents/social_track.py | 23 ++++++++ src/openagent/tools/block_stat_tool.py | 65 +++++++++++++++++++++ src/openagent/tools/coin_market_tool.py | 72 ++++++++++++++++++++++++ 8 files changed, 277 insertions(+) create mode 100644 src/openagent/agents/agent_factory.py create mode 100644 src/openagent/agents/asset_management.py create mode 100644 src/openagent/agents/block_explore.py create mode 100644 src/openagent/agents/fallback.py create mode 100644 src/openagent/agents/market_analysis.py create mode 100644 src/openagent/agents/social_track.py create mode 100644 src/openagent/tools/block_stat_tool.py create mode 100644 src/openagent/tools/coin_market_tool.py diff --git a/src/openagent/agents/agent_factory.py b/src/openagent/agents/agent_factory.py new file mode 100644 index 00000000..25094e47 --- /dev/null +++ b/src/openagent/agents/agent_factory.py @@ -0,0 +1,16 @@ +from langchain.agents import AgentExecutor, create_tool_calling_agent +from langchain_core.language_models import BaseChatModel +from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder + + +def create_agent(llm: BaseChatModel, tools: list, system_prompt: str): + prompt = ChatPromptTemplate.from_messages( + [ + ("system", system_prompt), + MessagesPlaceholder(variable_name="messages"), + MessagesPlaceholder(variable_name="agent_scratchpad"), + ] + ) + agent = create_tool_calling_agent(llm, tools, prompt) + executor = AgentExecutor(agent=agent, tools=tools, verbose=True) + return executor diff --git a/src/openagent/agents/asset_management.py b/src/openagent/agents/asset_management.py new file mode 100644 index 00000000..f226444c --- /dev/null +++ b/src/openagent/agents/asset_management.py @@ -0,0 +1,21 @@ +from dotenv import load_dotenv +from langchain_openai import ChatOpenAI + +from openagent.agents.agent_factory import create_agent +from openagent.conf.llm_provider import get_current_llm +from openagent.tools.nft_balance_tool import NFTBalanceTool +from openagent.tools.token_balance_tool import TokenBalanceTool + +load_dotenv() + +asset_management_agent = create_agent( + get_current_llm(), + [TokenBalanceTool(), NFTBalanceTool()], + """ +You are AssetManager, responsible for helping users query and manage their crypto assets, +including tokens and NFTs. Use the provided tools to fetch the required information accurately and efficiently. + +Your answer should be detailed and include puns or jokes where possible \ +And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. +""".strip(), +) diff --git a/src/openagent/agents/block_explore.py b/src/openagent/agents/block_explore.py new file mode 100644 index 00000000..3d891598 --- /dev/null +++ b/src/openagent/agents/block_explore.py @@ -0,0 +1,22 @@ +from dotenv import load_dotenv +from langchain_openai import ChatOpenAI + +from openagent.agents.agent_factory import create_agent +from openagent.conf.llm_provider import get_current_llm +from openagent.tools.tavily_tool import tavily_tool +from openagent.tools.block_stat_tool import BlockStatTool + +load_dotenv() + +block_explorer_agent = create_agent( + get_current_llm(), + [BlockStatTool(), tavily_tool], + """ +You are BlockExplorer, dedicated to exploring and presenting detailed blockchain information. +Help users query transaction details, block data, gas fees, block height, and other blockchain-related information. +Use the available tools to gather and display accurate blockchain data. + +Your answer should be detailed and include puns or jokes where possible \ +And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. +""".strip(), +) diff --git a/src/openagent/agents/fallback.py b/src/openagent/agents/fallback.py new file mode 100644 index 00000000..a9d066b2 --- /dev/null +++ b/src/openagent/agents/fallback.py @@ -0,0 +1,33 @@ +from langchain_core.messages import HumanMessage +from langchain_core.output_parsers import StrOutputParser +from langchain_core.prompts import ChatPromptTemplate +from loguru import logger + +from openagent.conf.llm_provider import get_current_llm + + +def fallback(state): + logger.info("Running fallback agent") + chat_template = ChatPromptTemplate.from_messages( + [ + ( + "system", + """ +You are openagent, when other agents are not available, you will be used to answer user queries. + +Your answer should be detailed and include puns or jokes where possible \ +And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. + """, + ), + ("human", "{input}"), + ] + ) + chain = chat_template | chat_template | get_current_llm() | StrOutputParser() + return { + "messages": [ + HumanMessage( + content=chain.invoke({"input": state["messages"][-1].content}), + name="fallback", + ) + ] + } diff --git a/src/openagent/agents/market_analysis.py b/src/openagent/agents/market_analysis.py new file mode 100644 index 00000000..5b4ebb47 --- /dev/null +++ b/src/openagent/agents/market_analysis.py @@ -0,0 +1,25 @@ +from dotenv import load_dotenv +from langchain_openai import ChatOpenAI + +from openagent.agents.agent_factory import create_agent +from openagent.conf.llm_provider import get_current_llm +from openagent.tools.coin_market_tool import CoinMarketTool +from openagent.tools.funding_rate_tool import FundingRateTool +from openagent.tools.tavily_tool import tavily_tool +from openagent.tools.nft_tool import NFTTool +from openagent.tools.price_tool import PriceTool + +load_dotenv() +llm = get_current_llm() + +market_analysis_agent = create_agent( + llm, + [tavily_tool, PriceTool(), FundingRateTool(), NFTTool(), CoinMarketTool()], + """ +You are MarketAnalyst, responsible for providing market data analysis. +Help users understand market dynamics and trends by retrieving real-time price information of tokens. + +Your answer should be detailed and include puns or jokes where possible \ +And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. +""".strip(), +) diff --git a/src/openagent/agents/social_track.py b/src/openagent/agents/social_track.py new file mode 100644 index 00000000..15b5b925 --- /dev/null +++ b/src/openagent/agents/social_track.py @@ -0,0 +1,23 @@ +from dotenv import load_dotenv + +from openagent.agents.agent_factory import create_agent +from openagent.conf.llm_provider import get_current_llm +from openagent.tools.feed_tool import FeedTool +from openagent.tools.tavily_tool import tavily_tool + +load_dotenv() +llm = get_current_llm() + +social_track_agent = create_agent( + llm, + [FeedTool(), tavily_tool], + """ + +You are Social Tracker, focused on tracking web3 social media and community interactions. + Provide users with the latest updates and discussions from the web3 ecosystem. + Use the available tools to collect and display social content. +Your answer should be detailed and include puns or jokes where possible \ +And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. + +""".strip(), +) diff --git a/src/openagent/tools/block_stat_tool.py b/src/openagent/tools/block_stat_tool.py new file mode 100644 index 00000000..28e5e260 --- /dev/null +++ b/src/openagent/tools/block_stat_tool.py @@ -0,0 +1,65 @@ +from typing import Optional, Type + +import ccxt +import requests +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + + +class ARGS(BaseModel): + chain: str = Field( + description="The blockchain to fetch statistics for. " + "Options: ethereum, bitcoin, bitcoin-cash, litecoin," + " bitcoin-sv, dogecoin, dash, groestlcoin," + " zcash, ecash, bitcoin/testnet" + ) + + +class BlockStatTool(BaseTool): + name = "block_chain_stat" + description = ( + "get blockchain statistics such as block height, " + "transaction count, gas fees, and more. " + "Supported blockchains include ethereum, Bitcoin, Bitcoin Cash, " + "Litecoin, Bitcoin SV, Dogecoin, Dash, Groestlcoin, Zcash, eCash, " + "and Bitcoin Testnet." + ) + args_schema: Type[ARGS] = ARGS + + def _run( + self, + chain: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + return fetch_stat(chain) + + async def _arun( + self, + chain: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + return fetch_stat(chain) + + +_exchanges = [ccxt.binance(), ccxt.okx(), ccxt.gateio(), ccxt.mexc()] + + +def fetch_stat(chain) -> str: + url = f"https://api.blockchair.com/{chain}/stats" + + headers = {"accept": "application/json"} + + response = requests.get(url, headers=headers) + + if response.status_code == 200: + return response.json() + else: + return f"Error fetching data: {response.status_code}, {response.text}" + + +if __name__ == "__main__": + print(fetch_stat("ethereum")) diff --git a/src/openagent/tools/coin_market_tool.py b/src/openagent/tools/coin_market_tool.py new file mode 100644 index 00000000..b9bcaa8d --- /dev/null +++ b/src/openagent/tools/coin_market_tool.py @@ -0,0 +1,72 @@ +import json +from typing import Optional, Type + +import requests +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + + +class ARGS(BaseModel): + order: str = Field( + description="sort result by field, default: market_cap_desc. options: market_cap_desc," + "market_cap_asc,volume_desc,volume_asc" + ) + size: int = Field(description="number of coins to return, default: 20") + + +class CoinMarketTool(BaseTool): + name = "coins-with-market" + + description = "query coins sorted by market cap, volume." + args_schema: Type[ARGS] = ARGS + + def _run( + self, + order: str, + size: int, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + return json.dumps(fetch_coins_with_market(order, size)) + + async def _arun( + self, + order: str, + size: int, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + return json.dumps(fetch_coins_with_market(order, size)) + + +def fetch_coins_with_market(order: str, size: int = 20) -> list: + url = f"https://pro-api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order={order}&per_page={size}" + + headers = { + "accept": "application/json", + "x-cg-pro-api-key": settings.COINGECKO_API_KEY, + } + + response = requests.get(url, headers=headers) + + res = json.loads(response.text) + return list( + map( + lambda x: { + "symbol": x["symbol"], + "name": x["name"], + "current_price": x["current_price"], + "fully_diluted_valuation": x["fully_diluted_valuation"], + "total_volume": x["total_volume"], + }, + res, + ) + ) + + +if __name__ == "__main__": + print(fetch_coins_with_market("market_cap_desc")) From 03ec529f05b1a3b5f6a503303ccec154ea3c531c Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jul 2024 16:13:15 +0800 Subject: [PATCH 04/85] feat: add tools --- src/openagent/agent/system_prompt.py | 118 ----------------------- src/openagent/tools/__init__.py | 0 src/openagent/tools/feed_tool.py | 50 ++++++++++ src/openagent/tools/funding_rate_tool.py | 63 ++++++++++++ src/openagent/tools/nft_balance_tool.py | 65 +++++++++++++ src/openagent/tools/nft_tool.py | 100 +++++++++++++++++++ src/openagent/tools/price_tool.py | 57 +++++++++++ src/openagent/tools/project_tool.py | 92 ++++++++++++++++++ src/openagent/tools/search_tool.py | 83 ++++++++++++++++ src/openagent/tools/tavily_tool.py | 3 + src/poetry.lock | 102 +++++++++++++++++++- src/pyproject.toml | 1 + 12 files changed, 615 insertions(+), 119 deletions(-) delete mode 100644 src/openagent/agent/system_prompt.py create mode 100644 src/openagent/tools/__init__.py create mode 100644 src/openagent/tools/feed_tool.py create mode 100644 src/openagent/tools/funding_rate_tool.py create mode 100644 src/openagent/tools/nft_balance_tool.py create mode 100644 src/openagent/tools/nft_tool.py create mode 100644 src/openagent/tools/price_tool.py create mode 100644 src/openagent/tools/project_tool.py create mode 100644 src/openagent/tools/search_tool.py create mode 100644 src/openagent/tools/tavily_tool.py diff --git a/src/openagent/agent/system_prompt.py b/src/openagent/agent/system_prompt.py deleted file mode 100644 index edd198ca..00000000 --- a/src/openagent/agent/system_prompt.py +++ /dev/null @@ -1,118 +0,0 @@ -# Description: This file contains the system prompt, which is loaded at the beginning of each conversation. -SYSTEM_PROMPT = """Your designated name is OpenAgent, developed by RSS3.io. \ -You possess proficiency in all matters related to web3. - -You can providing answers to questions and help users to trade or transfer tokens. - -Your answer should be detailed and include puns or jokes where possible \ -And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. - -If you don't know the answer to the question, \ -you can ask the user to rephrase the question or ask for more information. - -When use transfer or swap tool, you should ask the user to edit or confirm the transaction, \ -and don't show the transaction link to the user. - -Return format: -You are committed to providing responses in markdown format for enhanced readability. -""" - -SYSTEM_PROMPT_V2 = """ -You are OpenAgent, an advanced AI assistant developed by RSS3.io, specializing in all matters related to web3. You possess the ability to call functions and use self-recursion, enhancing your problem-solving capabilities. - -Key Characteristics and Abilities: -1. Web3 Expertise: You are proficient in blockchain technology, cryptocurrencies, DeFi, NFTs, and all aspects of the web3 ecosystem. - -2. Function Calling: You can call functions to perform tasks or retrieve information. Always wait for function results before proceeding with your response. - -3. Self-Recursion: Utilize agentic frameworks for reasoning and planning to address complex queries effectively. - -4. Response Style: - - Provide detailed answers in markdown format for enhanced readability. - - Maintain a lively, enthusiastic, and energetic tone. - - Include puns, jokes, or emojis where appropriate to keep the conversation engaging. - -5. Problem-Solving Approach: - - Analyze function results thoroughly before deciding on next steps. - - Call additional functions if needed to gather more information or perform actions. - - Don't make assumptions about function input values; ask for clarification if necessary. - -6. Handling Uncertainty: - - If you don't know the answer, use google search in search expert tool to find relevant information. - -7. User Interaction: - - Guide users through complex processes step-by-step. - - Offer explanations of web3 concepts when relevant to the conversation. - - Be patient and willing to clarify or elaborate on any point. - -Remember, your goal is to assist users with their web3-related queries and tasks while providing an informative and enjoyable interaction experience. -""" - -FEED_PROMPT = """ -Based on the following wallet activities for {address}, please provide a detailed summary using markdown list format. -Focus on the most important and interesting aspects of these transactions. -Include relevant emojis to make the summary more engaging. - -Here are the raw activities: - -{activities_data} - -Please organize your summary as follows: -1. A brief overview of the account's recent activity -2. A list of the most notable transactions, including: - - The type of transaction - - The tokens involved (if any) - - The amounts transferred - - Any interesting patterns or repeated actions -3. Any insights you can draw about the account holder's behavior or interests based on these activities - -Remember to use markdown formatting and keep your tone friendly and informative. -""" - - -custom_agent_kwargs = { - "prefix": """ -Your designated name is RSS3 OpenAgent, developed by RSS3, \ -you have the capability to call upon tools to aid in answering questions about web3. -Assistants may prompt the user to employ specific tools to gather information that might be helpful in addressing the user's initial question. -Here are tools' schemas: - """, - "format_instructions": r""" -When responding, you must exclusively use one of the following two formats: - -**Option 1:** -If you're suggesting that the user utilizes a tool, format your response as a markdown code snippet according to this schema: -```json -{{{{ - "action": string, // The action to be taken. Must be one of {tool_names} - "action_input": dict // The parameters for the action. MUST be a dict object -}}}} -``` -e.g. -```json -{{{{ - "action": "search", - "action_input": {{{{ - "query": "price of ETH", - "search_type": "google", - }}}} -}}}} -``` - -**Option 2:** -If you observable the tool's results, or you're providing a direct final response to the user, format your response as a markdown code snippet following this schema: - -```json -{{{{ - "action": "Final Answer", // MUST be literal string "Final Answer", other forms are not acceptable - "action_input": string // This should contain your response to the user, in human-readable language -}}}} -``` -""", - "suffix": """ -YOU MUST FOLLOW THESE INSTRUCTIONS CAREFULLY. -1. To respond to the users message, you can use only one tool at a time. -2. When using a tool, only respond with the tool call. Nothing else. Do not add any additional notes, explanations or white space. Never escape with a backslash. -3. REMEMBER to respond with a markdown code snippet of a json blob with a single action, and nothing else. -""", -} diff --git a/src/openagent/tools/__init__.py b/src/openagent/tools/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/openagent/tools/feed_tool.py b/src/openagent/tools/feed_tool.py new file mode 100644 index 00000000..f5fa0279 --- /dev/null +++ b/src/openagent/tools/feed_tool.py @@ -0,0 +1,50 @@ +from typing import Optional, Type + +import aiohttp +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from loguru import logger +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + + +class ParamSchema(BaseModel): + address: str = Field( + description="""wallet address or blockchain domain name,\ +hint: vitalik's address is vitalik.eth""" + ) + + +class FeedTool(BaseTool): + name = "feed" + description = """Use this tool to get the activities of a wallet address or \ +blockchain domain name and know what this address has done or doing recently.""" + args_schema: Type[ParamSchema] = ParamSchema + + def _run( + self, + address: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + raise NotImplementedError + + async def _arun( + self, + address: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ): + return await fetch_feeds(address) + + +async def fetch_feeds(address: str): + host = settings.RSS3_DATA_API + "/accounts" + url = f"""{host}/{address}/activities?limit=10&action_limit=5&direction=out""" + headers = {"Accept": "application/json"} + async with aiohttp.ClientSession() as session: + logger.info(f"fetching {url}") + async with session.get(url, headers=headers) as resp: + return await resp.text() diff --git a/src/openagent/tools/funding_rate_tool.py b/src/openagent/tools/funding_rate_tool.py new file mode 100644 index 00000000..c920a51a --- /dev/null +++ b/src/openagent/tools/funding_rate_tool.py @@ -0,0 +1,63 @@ +import json +from typing import Optional, Type + +import ccxt +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from loguru import logger +from pydantic import BaseModel, Field + + +class ARGS(BaseModel): + exchange: str = Field( + description="Name of the exchange (ccxt supported), e.g., 'binance'" + ) + symbol: str = Field(description="Trading pair symbol, e.g., 'BTC/USDT:USDT'") + + +class FundingRateTool(BaseTool): + name = "funding_rate" + description = "Use this tool to get the funding rate of a trading pair." + args_schema: Type[ARGS] = ARGS + + def _run( + self, + exchange: str, + symbol: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + try: + return json.dumps(fetch_funding_rate(exchange, symbol)) + except Exception as e: + return f"error: {e}" + + async def _arun( + self, + exchange: str, + symbol: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + try: + return json.dumps(fetch_funding_rate(exchange, symbol)) + except Exception as e: + return f"error: {e}" + + +def fetch_funding_rate(exchange_name: str, symbol: str) -> float: + try: + exchange_class = getattr(ccxt, exchange_name) + exchange = exchange_class() + + funding_rate = exchange.fetch_funding_rate(symbol) + return funding_rate + except Exception as e: # noqa + logger.warning(f"Fetch funding rate error from {exchange_name}: {e}") + raise Exception(f"No funding rate found for {symbol} on {exchange_name}") + + +if __name__ == "__main__": + tool = FundingRateTool() + print(tool.run(tool_input={"exchange": "binance", "symbol": "BTC/USDT:USDT"})) diff --git a/src/openagent/tools/nft_balance_tool.py b/src/openagent/tools/nft_balance_tool.py new file mode 100644 index 00000000..9914d793 --- /dev/null +++ b/src/openagent/tools/nft_balance_tool.py @@ -0,0 +1,65 @@ +import json +from typing import Optional, Type + +from covalent import CovalentClient +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + + +class ARGS(BaseModel): + chain: str = Field( + description="chain name,options:eth-mainnet,optimism-mainnet,arbitrum-mainnet,bsc-mainnet" + ) + wallet_address: str = Field(description="wallet address") + + +class NFTBalanceTool(BaseTool): + name = "nft-balance" + description = "get the nft asset of a wallet." + args_schema: Type[ARGS] = ARGS + + def _run( + self, + chain: str, + wallet_address: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + return fetch_balance(chain, wallet_address) + + async def _arun( + self, + chain: str, + wallet_address: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + return fetch_balance(chain, wallet_address) + + +def fetch_balance(chain: str, address: str) -> str: + c = CovalentClient(settings.COVALENT_API_KEY) + b = c.nft_service.get_nfts_for_address(chain, address) + if b.error: + return b.error_message + return json.dumps( + list( + map( + lambda x: { + "contract_name": x.contract_name, + "contract_ticker_symbol": x.contract_ticker_symbol, + "balance": x.balance, + "pretty_floor_price_quote": x.pretty_floor_price_quote, + }, + b.data.items, + ) + ) + ) + + +if __name__ == "__main__": + print(fetch_balance("eth-mainnet", "0x33c0814654fa367ce67d8531026eb4481290e63c")) diff --git a/src/openagent/tools/nft_tool.py b/src/openagent/tools/nft_tool.py new file mode 100644 index 00000000..6734692e --- /dev/null +++ b/src/openagent/tools/nft_tool.py @@ -0,0 +1,100 @@ +import json +from typing import Optional, Type + +import requests +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + + +class ARGS(BaseModel): + action: str = Field( + description="Specify the operation to perform: 'search' for NFT " + "collection search, 'rank' for collection ranking" + ) + keyword: Optional[str] = Field( + default=None, + description="NFT symbol or collection name, required only for 'action=search'", + ) + sort_field: Optional[str] = Field( + default="market_cap", + description=""" +Default is market_cap. Options include: volume_1d, volume_7d, volume_30d, +volume_total, volume_change_1d, +volume_change_7d, volume_change_30d, sales_1d, sales_7d, sales_30d, +sales_total, sales_change_1d, +sales_change_7d, sales_change_30d, +floor_price, market_cap. Required only for 'action=rank' + """, + ) + + +class NFTTool(BaseTool): + name = "NFT" + description = "A tool for searching NFT collections or getting collection rankings." + args_schema: Type[ARGS] = ARGS + + def _run( + self, + action: str, + keyword: Optional[str] = None, + sort_field: Optional[str] = "market_cap", + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + if action == "search": + if keyword is None: + return "Error: A keyword is required for search operation." + return self.search_nft_collections(keyword) + elif action == "rank": + return self.collection_ranking(sort_field) + else: + return ( + "Error: Unknown operation type. " + "Please specify 'action' as 'search' or 'rank'." + ) + + async def _arun( + self, + action: str, + keyword: Optional[str] = None, + sort_field: Optional[str] = "market_cap", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + return self._run(action, keyword, sort_field, run_manager) + + @staticmethod + def search_nft_collections(keyword: str) -> str: + """Search for NFT collections.""" + url = "https://restapi.nftscan.com/api/v2/collections/filters" + payload = json.dumps( + { + "contract_address_list": [], + "name_fuzzy_search": "false", + "show_collection": "false", + "sort_direction": "desc", + "sort_field": "floor_price", + "name": "", + "symbol": keyword, + } + ) + headers = { + "Content-Type": "application/json", + "X-API-KEY": f"{settings.NFTSCAN_API_KEY}", + } + + response = requests.post(url, headers=headers, data=payload) + return response.text + + @staticmethod + def collection_ranking(sort_field: str) -> str: + """Search for NFT collections ranking.""" + url = f"https://restapi.nftscan.com/api/v2/statistics/ranking/collection?sort_field={sort_field}&sort_direction=desc&limit=20" + + headers = {"X-API-KEY": f"{settings.NFTSCAN_API_KEY}"} + response = requests.get(url, headers=headers) + return response.text diff --git a/src/openagent/tools/price_tool.py b/src/openagent/tools/price_tool.py new file mode 100644 index 00000000..3d076c8d --- /dev/null +++ b/src/openagent/tools/price_tool.py @@ -0,0 +1,57 @@ +import asyncio +from typing import Optional, Type + +import ccxt +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from loguru import logger +from pydantic import BaseModel, Field + + +class ARGS(BaseModel): + token: str = Field(description="token symbol") + + +class PriceTool(BaseTool): + name = "price" + description = "use this tool to get the price of a token." + args_schema: Type[ARGS] = ARGS + + def _run( + self, + token: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + try: + return f"The price of {token} is {asyncio.run(fetch_price(token))}" + except Exception as e: + return f"error: {e}" + + async def _arun( + self, + token: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + try: + return f"The price of {token} is {await fetch_price(token)}" + except Exception as e: + return f"error: {e}" + + +_exchanges = [ccxt.binance(), ccxt.okx(), ccxt.gateio(), ccxt.mexc()] +import chainlit as cl + + +@cl.step(type="tool") +async def fetch_price(base: str, quote: str = "USDT") -> float: + for exchange in _exchanges: + try: + trades = exchange.fetch_trades(f"{base.upper()}/{quote}", limit=1) + last = trades[0]["price"] + return last + except Exception as e: # noqa + logger.warning(f"fetch price error from {exchange.id}: {e}") + raise Exception(f"no market found for {base}") diff --git a/src/openagent/tools/project_tool.py b/src/openagent/tools/project_tool.py new file mode 100644 index 00000000..cd2fbc69 --- /dev/null +++ b/src/openagent/tools/project_tool.py @@ -0,0 +1,92 @@ +import asyncio +import json +from concurrent.futures import ThreadPoolExecutor +from typing import Optional, Type + +import aiohttp +from cachetools import TTLCache, cached +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + +API_KEY = "" +HEADERS = { + "apikey": settings.ROOTDATA_API_KEY, + "language": "en", + "Content-Type": "application/json", +} + +cache = TTLCache(maxsize=100, ttl=24 * 60 * 60) + + +class ARGS(BaseModel): + keyword: str = Field(description="keyword") + + +def _fetch_project_sync(keyword: str) -> str: + projects = asyncio.run(fetch_project(keyword)) + return json.dumps(projects) + + +class ProjectTool(BaseTool): + name = "project" + + description = ( + "get the project information like investors, team members, social media, etc." + ) + args_schema: Type[ARGS] = ARGS + + def _run( + self, + keyword: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + with ThreadPoolExecutor() as executor: + future = executor.submit(_fetch_project_sync, keyword) + return future.result() + + async def _arun( + self, + keyword: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + projects = await fetch_project(keyword) + return json.dumps(projects) + + +async def fetch_project_detail(session, project_id: int) -> dict: + url = "https://api.rootdata.com/open/get_item" + payload = json.dumps( + {"project_id": project_id, "include_team": True, "include_investors": True} + ) + + async with session.post(url, headers=HEADERS, data=payload) as response: + response_text = await response.text() + return json.loads(response_text)["data"] + + +@cached(cache) +async def fetch_project(keyword: str) -> list: + url = "https://api.rootdata.com/open/ser_inv" + payload = json.dumps({"query": keyword, "variables": {}}) + + async with aiohttp.ClientSession() as session, session.post( + url, headers=HEADERS, data=payload + ) as response: + response_text = await response.text() + data = json.loads(response_text)["data"] + project_ids = [item["id"] for item in data if item["type"] == 1][0:2] + + tasks = [ + fetch_project_detail(session, project_id) for project_id in project_ids + ] + return list(await asyncio.gather(*tasks)) + + +if __name__ == "__main__": + print(asyncio.run(fetch_project("rss3"))) diff --git a/src/openagent/tools/search_tool.py b/src/openagent/tools/search_tool.py new file mode 100644 index 00000000..ee7cb5f2 --- /dev/null +++ b/src/openagent/tools/search_tool.py @@ -0,0 +1,83 @@ +from typing import Optional, Type + +import requests +from langchain_community.utilities import SerpAPIWrapper +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + + +class SearchSchema(BaseModel): + query: str = Field(description="The search query keywords.") + search_type: str = Field( + description="""The type of search to perform. Options are: + - "google": Google search for current events and real-time information + - "dune": Search for Dune dashboards""" + ) + gl: Optional[str] = Field( + default="us", + description="Country code for Google search, e.g., 'us', 'cn', 'jp'", + ) + hl: Optional[str] = Field( + default="en", + description="Language code for Google search, e.g., 'en', 'zh-cn', 'ja'", + ) + + +def dune_search(query: str) -> str: + url = f"{settings.RSS3_SEARCH_API}/dune/search?keyword={query}" + headers = {"Accept": "*/*", "Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers) + return response.text + + +def google_search(query: str, gl: str, hl: str) -> str: + search_wrapper = SerpAPIWrapper( + search_engine="google", + params={"engine": "google", "gl": gl, "hl": hl}, + ) + return search_wrapper.run(query) + + +class SearchTool(BaseTool): + name = "search" + description = """ + A versatile search tool that can perform various types of searches based on the query type: + - For queries related to charts, data visualization, or dashboards, use Dune search. + - For queries about project introductions, current events or real-time information, use Google search.""" + args_schema: Type[SearchSchema] = SearchSchema + + def _run( + self, + query: str, + search_type: str, + gl: Optional[str] = "us", + hl: Optional[str] = "en", + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + if search_type == "google": + return google_search(query, gl, hl) + elif search_type == "dune": + return dune_search(query) + else: + raise ValueError(f"Unknown search type: {search_type}") + + async def _arun( + self, + query: str, + search_type: str, + gl: Optional[str] = "us", + hl: Optional[str] = "en", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + if search_type == "google": + return google_search(query, gl, hl) + elif search_type == "dune": + return dune_search(query) + else: + raise ValueError(f"Unknown search type: {search_type}") diff --git a/src/openagent/tools/tavily_tool.py b/src/openagent/tools/tavily_tool.py new file mode 100644 index 00000000..6f1785c9 --- /dev/null +++ b/src/openagent/tools/tavily_tool.py @@ -0,0 +1,3 @@ +from langchain_community.tools.tavily_search import TavilySearchResults + +tavily_tool = TavilySearchResults(max_results=5) diff --git a/src/poetry.lock b/src/poetry.lock index ed7c90f1..e9309f2d 100644 --- a/src/poetry.lock +++ b/src/poetry.lock @@ -592,6 +592,25 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "covalent-api-sdk" +version = "1.0.2" +description = "covalent-api-sdk-py" +optional = false +python-versions = ">=3.7" +files = [ + {file = "covalent_api_sdk-1.0.2-py3-none-any.whl", hash = "sha256:906b191e88769cb4774428c7f06d6be15b7b5a3855761a8ec3a03ff6db08a1dd"}, + {file = "covalent_api_sdk-1.0.2.tar.gz", hash = "sha256:578247e551bfadd988f41a51bd3020fa286e11c57d00c762b14f228f3592e8ab"}, +] + +[package.dependencies] +aiohttp = "*" +deprecated = "*" +pytest = "*" +pytest-asyncio = "*" +pytest-env = "*" +requests = "*" + [[package]] name = "cryptography" version = "42.0.7" @@ -1524,6 +1543,17 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link perf = ["ipython"] testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + [[package]] name = "jsonpatch" version = "1.33" @@ -2323,6 +2353,21 @@ docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx- test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] type = ["mypy (>=1.8)"] +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + [[package]] name = "pre-commit" version = "3.7.1" @@ -2830,6 +2875,61 @@ files = [ [package.extras] diagrams = ["jinja2", "railroad-diagrams"] +[[package]] +name = "pytest" +version = "8.2.2" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, + {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2.0" + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-asyncio" +version = "0.23.7" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_asyncio-0.23.7-py3-none-any.whl", hash = "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b"}, + {file = "pytest_asyncio-0.23.7.tar.gz", hash = "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268"}, +] + +[package.dependencies] +pytest = ">=7.0.0,<9" + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] + +[[package]] +name = "pytest-env" +version = "1.1.3" +description = "pytest plugin that allows you to add environment variables." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_env-1.1.3-py3-none-any.whl", hash = "sha256:aada77e6d09fcfb04540a6e462c58533c37df35fa853da78707b17ec04d17dfc"}, + {file = "pytest_env-1.1.3.tar.gz", hash = "sha256:fcd7dc23bb71efd3d35632bde1bbe5ee8c8dc4489d6617fb010674880d96216b"}, +] + +[package.dependencies] +pytest = ">=7.4.3" + +[package.extras] +test = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "pytest-mock (>=3.12)"] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -3988,4 +4088,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "058d90ccc4fb68817b325c32bcc0873522a11946a7decd5cee14d11f7fa6b0be" +content-hash = "2ecb5840540e3502588f0b395fd644dcea49f592126a79761fcb452d430027cb" diff --git a/src/pyproject.toml b/src/pyproject.toml index eab5e2e0..2b6bb8bd 100644 --- a/src/pyproject.toml +++ b/src/pyproject.toml @@ -38,6 +38,7 @@ langchain-community = "^0.2.6" langchain-openai = "^0.1.13" chainlit = "^1.1.305" greenlet = "^3.0.3" +covalent-api-sdk = "^1.0.2" [tool.poetry.group.dev.dependencies] ruff = "^0.4.1" From 3389e420ae04684b2f5c86ea0e7fe814c34f989e Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jul 2024 16:13:47 +0800 Subject: [PATCH 05/85] feat: build workflow --- src/openagent/{agent => agents}/__init__.py | 0 src/openagent/agents/project_management.py | 22 +++++++ src/openagent/tools/token_balance_tool.py | 64 +++++++++++++++++++ src/openagent/ui/profile.py | 35 +++++++++++ src/openagent/workflows/__init__.py | 0 src/openagent/workflows/member.py | 26 ++++++++ src/openagent/workflows/supervisor_chain.py | 60 ++++++++++++++++++ src/openagent/workflows/workflow.py | 70 +++++++++++++++++++++ 8 files changed, 277 insertions(+) rename src/openagent/{agent => agents}/__init__.py (100%) create mode 100644 src/openagent/agents/project_management.py create mode 100644 src/openagent/tools/token_balance_tool.py create mode 100644 src/openagent/ui/profile.py create mode 100644 src/openagent/workflows/__init__.py create mode 100644 src/openagent/workflows/member.py create mode 100644 src/openagent/workflows/supervisor_chain.py create mode 100644 src/openagent/workflows/workflow.py diff --git a/src/openagent/agent/__init__.py b/src/openagent/agents/__init__.py similarity index 100% rename from src/openagent/agent/__init__.py rename to src/openagent/agents/__init__.py diff --git a/src/openagent/agents/project_management.py b/src/openagent/agents/project_management.py new file mode 100644 index 00000000..97190533 --- /dev/null +++ b/src/openagent/agents/project_management.py @@ -0,0 +1,22 @@ +from dotenv import load_dotenv + +from openagent.agents.agent_factory import create_agent +from openagent.conf.llm_provider import get_current_llm +from openagent.tools.project_tool import ProjectTool +from openagent.tools.tavily_tool import tavily_tool + +load_dotenv() +llm = get_current_llm() + +research_analyst_agent = create_agent( + llm, + [ProjectTool(), tavily_tool], + """ +You are ResearchAnalyst, responsible for assisting users in conducting research and analysis related to web3 projects. + Provide accurate and detailed information about project progress, team members, market trends, investors, + and other relevant data to support investment decisions. + +Your answer should be detailed and include puns or jokes where possible \ +And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. +""".strip(), +) diff --git a/src/openagent/tools/token_balance_tool.py b/src/openagent/tools/token_balance_tool.py new file mode 100644 index 00000000..16357fcb --- /dev/null +++ b/src/openagent/tools/token_balance_tool.py @@ -0,0 +1,64 @@ +import json +from typing import Optional, Type + +from covalent import CovalentClient +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + + +class ARGS(BaseModel): + chain: str = Field( + description="chain name,options:btc-mainnet,eth-mainnet,optimism-mainnet,arbitrum-mainnet,bsc-mainnet" + ) + wallet_address: str = Field(description="wallet address") + + +class TokenBalanceTool(BaseTool): + name = "token-balance" + description = "get the token balance of a wallet." + args_schema: Type[ARGS] = ARGS + + def _run( + self, + chain: str, + wallet_address: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + return fetch_balance(chain, wallet_address) + + async def _arun( + self, + chain: str, + wallet_address: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + return fetch_balance(chain, wallet_address) + + +def fetch_balance(chain: str, address: str) -> str: + c = CovalentClient(settings.COVALENT_API_KEY) + b = c.balance_service.get_token_balances_for_wallet_address(chain, address) + if b.error: + return b.error_message + return json.dumps( + list( + map( + lambda x: { + "contract_ticker_symbol": x.contract_ticker_symbol, + "balance": x.balance, + "pretty_quote": x.pretty_quote, + }, + b.data.items, + ) + ) + ) + + +if __name__ == "__main__": + print(fetch_balance("eth-mainnet", "0x33c0814654fa367ce67d8531026eb4481290e63c")) diff --git a/src/openagent/ui/profile.py b/src/openagent/ui/profile.py new file mode 100644 index 00000000..e15038d5 --- /dev/null +++ b/src/openagent/ui/profile.py @@ -0,0 +1,35 @@ +import chainlit as cl + +provider_key_to_profile_info = { + 'gpt-3.5-turbo': { + "name": "GPT-3.5", + "markdown_description": "The underlying LLM model is **GPT-3.5**.", + "icon": "https://custom.typingmind.com/assets/models/gpt-35.webp" + }, + 'gpt-4o': { + "name": "GPT-4", + "markdown_description": "The underlying LLM model is **GPT-4**.", + "icon": "https://custom.typingmind.com/assets/models/gpt-4.webp" + }, + 'gemini-1.5-pro': { + "name": "Gemini 1.5 Pro", + "markdown_description": "The underlying LLM model is **Gemini 1.5 Pro**.", + "icon": "https://custom.typingmind.com/assets/models/gemini.png" + } +} + + +def provider_to_profile(provider_key): + profile_info = provider_key_to_profile_info.get(provider_key) + if profile_info: + return cl.ChatProfile( + name=profile_info["name"], + markdown_description=profile_info["markdown_description"], + icon=profile_info["icon"] + ) + return None + + +def profile_name_to_provider_key(name): + map = {v["name"]: k for k, v in provider_key_to_profile_info.items()} + return map.get(name) diff --git a/src/openagent/workflows/__init__.py b/src/openagent/workflows/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/openagent/workflows/member.py b/src/openagent/workflows/member.py new file mode 100644 index 00000000..a3d46f59 --- /dev/null +++ b/src/openagent/workflows/member.py @@ -0,0 +1,26 @@ +members = [ + { + "name": "market_analysis_agent", + "description": "MarketAnalyst, provides market data analysis. Helps users understand market dynamics and trends by retrieving real-time token price information.", + }, + { + "name": "social_track_agent", + "description": "Social Tracker, tracks web3 social media and community interactions. Provides the latest updates and discussions from the web3 ecosystem using available tools.", + }, + { + "name": "asset_management_agent", + "description": "AssetManager, helps users query and manage their crypto assets, including tokens and NFTs.", + }, + { + "name": "block_explorer_agent", + "description": "BlockExplorer, assists users in exploring blockchain data, including block height, transaction details, gas fees, and other relevant information.", + }, + { + "name": "research_analyst_agent", + "description": "ResearchAnalyst, assists users in conducting research and analysis related to web3 projects. Provides detailed information about project progress, team members, market trends, investors, and other relevant data to support investment decisions.", + }, + { + "name": "fallback_agent", + "description": "FallbackAgent, answers user queries when other agents are not related to the query, or when the query is unclear. Handles conversations that should continue with the fallback agent.", + }, +] diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py new file mode 100644 index 00000000..c5aa18cc --- /dev/null +++ b/src/openagent/workflows/supervisor_chain.py @@ -0,0 +1,60 @@ +from dotenv import load_dotenv +from langchain_core.output_parsers.openai_functions import JsonOutputFunctionsParser +from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder + +from openagent.conf.llm_provider import get_current_llm +from openagent.workflows.member import members + +load_dotenv() + +system_prompt = ( + "You are a supervisor tasked with managing a conversation between the" + " following workers: {members}. Given the following user request," + " respond with the worker to act next. Each worker will perform a" + " task and respond with their results and status. When finished," + " respond with FINISH." +).format( + members=", ".join( + [f"{member['name']} ({member['description']})" for member in members] + ) +) + +options = ["FINISH"] + [member["name"] for member in members] +function_def = { + "name": "route", + "description": "Select the next role.", + "parameters": { + "title": "routeSchema", + "type": "object", + "properties": { + "next": { + "title": "Next", + "anyOf": [ + {"enum": options}, + ], + } + }, + "required": ["next"], + }, +} +prompt = ChatPromptTemplate.from_messages( + [ + ("system", system_prompt), + MessagesPlaceholder(variable_name="messages"), + ( + "system", + "Given the conversation above, who should act next?" + " Or should we FINISH? Select one of: {options}", + ), + ] +).partial( + options=str(options), members=", ".join([member["name"] for member in members]) +) + +llm = get_current_llm() + +supervisor_chain = ( + prompt + | llm.bind_functions(functions=[function_def], function_call="route") + | JsonOutputFunctionsParser() +) diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py new file mode 100644 index 00000000..4b78a4d0 --- /dev/null +++ b/src/openagent/workflows/workflow.py @@ -0,0 +1,70 @@ +import operator +from typing import Annotated, Sequence, TypedDict + +from langchain_core.messages import BaseMessage +from langchain_core.messages import HumanMessage +from langgraph.graph import END, StateGraph +from loguru import logger + + + + +class AgentState(TypedDict): + messages: Annotated[Sequence[BaseMessage], operator.add] + next: str + + +def create_node(agent, name): + def run(state): + logger.info(f"Running {name} agent") + result = agent.invoke(state) + return {"messages": [HumanMessage(content=result["output"], name=name)]} + + return run + + +def build_workflow(): + from openagent.agents.asset_management import asset_management_agent + from openagent.agents.block_explore import block_explorer_agent + from openagent.agents.fallback import fallback + from openagent.agents.market_analysis import market_analysis_agent + from openagent.agents.project_management import research_analyst_agent + from openagent.agents.social_track import social_track_agent + from openagent.workflows.member import members + from openagent.workflows.supervisor_chain import supervisor_chain + market_analysis_agent_node = create_node( + market_analysis_agent, "market_analysis_agent" + ) + social_track_agent_node = create_node(social_track_agent, "social_track_agent") + asset_management_agent_node = create_node( + asset_management_agent, "asset_management_agent" + ) + block_explorer_agent_node = create_node( + block_explorer_agent, "block_explorer_agent" + ) + research_analyst_agent_node = create_node( + research_analyst_agent, "research_analyst_agent" + ) + + workflow = StateGraph(AgentState) + workflow.add_node("market_analysis_agent", market_analysis_agent_node) + workflow.add_node("social_track_agent", social_track_agent_node) + workflow.add_node("asset_management_agent", asset_management_agent_node) + workflow.add_node("block_explorer_agent", block_explorer_agent_node) + workflow.add_node("research_analyst_agent", research_analyst_agent_node) + workflow.add_node("supervisor", supervisor_chain) + workflow.add_node("fallback_agent", fallback) + + member_names = list(map(lambda x: x["name"], members)) + + for member in member_names: + if member == "fallback_agent": + workflow.add_edge(member, END) + continue + workflow.add_edge(member, "supervisor") + + conditional_map = {k: k for k in member_names} + conditional_map["FINISH"] = END + workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map) + workflow.set_entry_point("supervisor") + return workflow.compile() From ee5f40c9c1420f89ff896e32d6bbe63e543b12a9 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jul 2024 16:13:57 +0800 Subject: [PATCH 06/85] chore: conf refactor --- src/openagent/conf/env.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/openagent/conf/env.py b/src/openagent/conf/env.py index d3674390..585572eb 100644 --- a/src/openagent/conf/env.py +++ b/src/openagent/conf/env.py @@ -28,6 +28,10 @@ class Settings(BaseSettings): description="RSS3 Data API with a default value") RSS3_SEARCH_API: Optional[str] = Field(default="https://devnet.rss3.io/search", env="RSS3_SEARCH_API", description="RSS3 Search API with a default value") + COVALENT_API_KEY: Optional[str] = Field(..., env="COVALENT_API_KEY") + ROOTDATA_API_KEY: Optional[str] = Field(..., env="ROOTDATA_API_KEY") + COINGECKO_API_KEY: Optional[str] = Field(..., env="COINGECKO_API_KEY") + # Validator to split comma-separated string into a list @field_validator("OLLAMA_MODEL", mode="before") From 216dad1444bb9701c2672a9adbdde4b7a6d96d92 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jul 2024 16:14:17 +0800 Subject: [PATCH 07/85] chore: dynamic chat profile --- src/openagent/conf/llm_provider.py | 23 ++++++++---- src/openagent/ui/app.py | 56 ++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index 2af0f9f4..d7dd3ce6 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -1,22 +1,31 @@ -import os +from contextvars import ContextVar -from langchain_openai import ChatOpenAI +from langchain_core.language_models import BaseChatModel from langchain_google_vertexai import ChatVertexAI -from dotenv import load_dotenv +from langchain_openai import ChatOpenAI +from loguru import logger from openagent.conf.env import settings -def build_providers(): +def get_available_providers(): providers = {} if settings.OPENAI_API_KEY: providers['gpt-3.5-turbo'] = ChatOpenAI(model="gpt-3.5-turbo") providers['gpt-4o'] = ChatOpenAI(model="gpt-4o") - if settings.VERTEX_PROJECT_ID: providers['gemini-1.5-pro'] = ChatVertexAI(model="gemini-1.5-pro") return providers -if __name__ == '__main__': - print(build_providers()) +_current_llm_provider: ContextVar[BaseChatModel | None] = ContextVar("current_llm_provider", default=None) + + +def set_current_llm(provider_name: str): + logger.info(f"Setting current LLM provider to {provider_name}") + providers = get_available_providers() + _current_llm_provider.set(providers.get(provider_name)) + + +def get_current_llm() -> BaseChatModel | None: + return _current_llm_provider.get() diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 828cecd9..5996e2f8 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -7,11 +7,13 @@ from chainlit.data.sql_alchemy import SQLAlchemyDataLayer from langchain.memory import ConversationBufferMemory from langchain.schema.runnable.config import RunnableConfig -from langchain_core.messages import FunctionMessage +from langchain_core.messages import FunctionMessage, HumanMessage from loguru import logger -from openagent.agent.function_agent import get_agent from openagent.conf.env import settings +from openagent.conf.llm_provider import get_available_providers, set_current_llm +from openagent.ui.profile import profile_name_to_provider_key, provider_to_profile +from openagent.workflows.workflow import build_workflow # Set up the data layer cl_data._data_layer = SQLAlchemyDataLayer(conninfo=settings.DB_CONNECTION) @@ -19,7 +21,7 @@ def setup_runnable(): """Set up the runnable agent.""" - agent = get_agent("") + agent = build_workflow() cl.user_session.set("runnable", agent) @@ -30,20 +32,35 @@ def initialize_memory() -> ConversationBufferMemory: @cl.oauth_callback def oauth_callback( - provider_id: str, - token: str, - raw_user_data: Dict[str, str], - default_user: cl.User, + provider_id: str, + token: str, + raw_user_data: Dict[str, str], + default_user: cl.User, ) -> Optional[cl.User]: """OAuth callback function.""" return default_user +@cl.set_chat_profiles +async def chat_profile(): + providers = get_available_providers() + profiles = list(map(provider_to_profile, providers.keys())) + profiles = [profile for profile in profiles if profile is not None] + + return profiles + + @cl.on_chat_start async def on_chat_start(): """Callback function when chat starts.""" cl.user_session.set("memory", initialize_memory()) + profile = cl.user_session.get("chat_profile") + provider_key = profile_name_to_provider_key(profile) + set_current_llm(provider_key) setup_runnable() + await cl.Message( + content=f"starting chat using the {profile} chat profile" + ).send() @cl.on_chat_resume @@ -58,6 +75,9 @@ async def on_chat_resume(thread: cl_data.ThreadDict): memory.chat_memory.add_ai_message(message["output"]) cl.user_session.set("memory", memory) + profile = cl.user_session.get("chat_profile") + provider_key = profile_name_to_provider_key(profile) + set_current_llm(provider_key) setup_runnable() @@ -85,20 +105,26 @@ async def on_message(message: cl.Message): memory = cl.user_session.get("memory") # type: ConversationBufferMemory runnable = cl.user_session.get("runnable") + profile = cl.user_session.get("chat_profile") + provider_key = profile_name_to_provider_key(profile) + set_current_llm(provider_key) + msg = cl.Message(content="") - try: - async for chunk in runnable.astream( - {"input": message.content}, config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]) - ): - if "output" in chunk: - await msg.stream_token(chunk["output"]) + # try: + async for chunk in runnable.astream( + {"messages": [HumanMessage(content=message.content)]}, + config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]) + ): + try: + if 'fallback_agent' in chunk: + await msg.stream_token(chunk["fallback_agent"]['messages'][0].content) elif "messages" in chunk: for message in chunk["messages"]: if isinstance(message, FunctionMessage): await handle_function_message(message, msg) - except Exception as e: - logger.error(f"Error processing message: {e}") + except Exception as e: + logger.error(f"Error processing message: {e}") await msg.send() memory.chat_memory.add_user_message(message.content) From b456cf5f1b9668a2c044f9e18b9aba0aa52450b2 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 15 Jul 2024 17:25:06 +0800 Subject: [PATCH 08/85] chore: Add agent token stream support --- src/openagent/ui/app.py | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 5996e2f8..f6a45f7b 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -13,6 +13,7 @@ from openagent.conf.env import settings from openagent.conf.llm_provider import get_available_providers, set_current_llm from openagent.ui.profile import profile_name_to_provider_key, provider_to_profile +from openagent.workflows.member import members from openagent.workflows.workflow import build_workflow # Set up the data layer @@ -110,21 +111,38 @@ async def on_message(message: cl.Message): set_current_llm(provider_key) msg = cl.Message(content="") + agent_names = [member['name'] for member in members] # try: - async for chunk in runnable.astream( + async for event in runnable.astream_events( {"messages": [HumanMessage(content=message.content)]}, - config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]) + config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]), + version="v1", ): - try: - if 'fallback_agent' in chunk: - await msg.stream_token(chunk["fallback_agent"]['messages'][0].content) - elif "messages" in chunk: - for message in chunk["messages"]: - if isinstance(message, FunctionMessage): - await handle_function_message(message, msg) - except Exception as e: - logger.error(f"Error processing message: {e}") + + kind = event["event"] + logger.info(event) + if kind == "on_chat_model_stream": + if event["metadata"]["langgraph_node"] in agent_names: + content = event["data"]["chunk"].content + if content: + await msg.stream_token(content) + # calls_ = event["data"]["chunk"].additional_kwargs['tool_calls'] + # for call in calls_: + # if call['function']['name'] == 'swap': + # swap_dict = json.loads(message.content) + # from_chain = swap_dict["chain_id"] + # to_chain = swap_dict["chain_id"] + # from_token_ = swap_dict["from_token_address"] + # to_token = swap_dict["to_token_address"] + # from_amount = swap_dict["amount"] + # + # widget = ( + # f"""""" + # ) + # await msg.stream_token(widget) await msg.send() memory.chat_memory.add_user_message(message.content) From 1e463b62f2a1558444bb5b56a0b31e28a16da34f Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 22 Jul 2024 14:26:56 +0800 Subject: [PATCH 09/85] chore: Refactor code for swap event handling --- src/main.py | 2 +- src/openagent/tools/price_tool.py | 15 ++++++-------- src/openagent/ui/app.py | 33 ++++++++++++++++--------------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/main.py b/src/main.py index b6fd84f4..8b311dd6 100644 --- a/src/main.py +++ b/src/main.py @@ -5,4 +5,4 @@ if __name__ == "__main__": load_dotenv() logger.info("Starting OpenAgent") - uvicorn.run("openagent.app:app", host="0.0.0.0", reload=False, port=8000) + uvicorn.run("openagent.app:app", host="localhost", reload=False, port=8000) diff --git a/src/openagent/tools/price_tool.py b/src/openagent/tools/price_tool.py index 3d076c8d..b555e1de 100644 --- a/src/openagent/tools/price_tool.py +++ b/src/openagent/tools/price_tool.py @@ -19,11 +19,10 @@ class PriceTool(BaseTool): name = "price" description = "use this tool to get the price of a token." args_schema: Type[ARGS] = ARGS - def _run( - self, - token: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + token: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: try: return f"The price of {token} is {asyncio.run(fetch_price(token))}" @@ -31,9 +30,9 @@ def _run( return f"error: {e}" async def _arun( - self, - token: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + token: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ) -> str: try: return f"The price of {token} is {await fetch_price(token)}" @@ -42,10 +41,8 @@ async def _arun( _exchanges = [ccxt.binance(), ccxt.okx(), ccxt.gateio(), ccxt.mexc()] -import chainlit as cl -@cl.step(type="tool") async def fetch_price(base: str, quote: str = "USDT") -> float: for exchange in _exchanges: try: diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index f6a45f7b..7c0db689 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -122,27 +122,28 @@ async def on_message(message: cl.Message): kind = event["event"] logger.info(event) + if kind == "on_tool_end": + if event["name"] == "swap": + output = event['data']['output'] + swap_dict = json.loads(output) + from_chain = swap_dict["chain_id"] + to_chain = swap_dict["chain_id"] + from_token_ = swap_dict["from_token_address"] + to_token = swap_dict["to_token_address"] + from_amount = swap_dict["amount"] + + widget = ( + f"""""" + ) + await msg.stream_token(widget) + if kind == "on_chat_model_stream": if event["metadata"]["langgraph_node"] in agent_names: content = event["data"]["chunk"].content if content: await msg.stream_token(content) - # calls_ = event["data"]["chunk"].additional_kwargs['tool_calls'] - # for call in calls_: - # if call['function']['name'] == 'swap': - # swap_dict = json.loads(message.content) - # from_chain = swap_dict["chain_id"] - # to_chain = swap_dict["chain_id"] - # from_token_ = swap_dict["from_token_address"] - # to_token = swap_dict["to_token_address"] - # from_amount = swap_dict["amount"] - # - # widget = ( - # f"""""" - # ) - # await msg.stream_token(widget) await msg.send() memory.chat_memory.add_user_message(message.content) From eb573532ab0fe954b57924bf8d6ea4d731350f1d Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 22 Jul 2024 14:44:09 +0800 Subject: [PATCH 10/85] chore: swap tool and langgraph integration --- src/openagent/agents/asset_management.py | 20 +++++--- src/openagent/dto/mutation.py | 23 --------- src/openagent/experts/swap_expert.py | 22 ++++++--- src/openagent/experts/transfer_expert.py | 36 +++++++++----- src/openagent/ui/app.py | 62 +++++++++--------------- 5 files changed, 75 insertions(+), 88 deletions(-) delete mode 100644 src/openagent/dto/mutation.py diff --git a/src/openagent/agents/asset_management.py b/src/openagent/agents/asset_management.py index f226444c..55ec1fef 100644 --- a/src/openagent/agents/asset_management.py +++ b/src/openagent/agents/asset_management.py @@ -1,8 +1,8 @@ from dotenv import load_dotenv -from langchain_openai import ChatOpenAI from openagent.agents.agent_factory import create_agent from openagent.conf.llm_provider import get_current_llm +from openagent.experts.swap_expert import SwapExpert from openagent.tools.nft_balance_tool import NFTBalanceTool from openagent.tools.token_balance_tool import TokenBalanceTool @@ -10,12 +10,20 @@ asset_management_agent = create_agent( get_current_llm(), - [TokenBalanceTool(), NFTBalanceTool()], + [TokenBalanceTool(), NFTBalanceTool(), SwapExpert()], """ -You are AssetManager, responsible for helping users query and manage their crypto assets, -including tokens and NFTs. Use the provided tools to fetch the required information accurately and efficiently. +You are AssetManager, an AI assistant for crypto asset management. Your responsibilities include: -Your answer should be detailed and include puns or jokes where possible \ -And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. +1. Query and report on users' token balances +2. Check and inform about users' NFT holdings +3. Generate cross-chain swap widgets for users + +When interacting with users: +- Provide accurate and detailed information +- Maintain a friendly and enthusiastic tone +- Use occasional puns or jokes to keep the conversation engaging +- Include relevant emojis to enhance your messages + +Prioritize clarity and efficiency in your responses while keeping the interaction enjoyable for the user. """.strip(), ) diff --git a/src/openagent/dto/mutation.py b/src/openagent/dto/mutation.py deleted file mode 100644 index 8c3c442b..00000000 --- a/src/openagent/dto/mutation.py +++ /dev/null @@ -1,23 +0,0 @@ -from pydantic import BaseModel - - -class Swap(BaseModel): - from_token: str - from_token_address: str - to_token: str - to_token_address: str - amount: str - type: str = "swap" - from_chain_name: str - to_chain_name: str - - -class Transfer(BaseModel): - # task_id: str - to_address: str - token: str - token_address: str - chain_id: str - amount: str - logoURI: str # noqa - decimals: int diff --git a/src/openagent/experts/swap_expert.py b/src/openagent/experts/swap_expert.py index ae39e249..d49ef19d 100644 --- a/src/openagent/experts/swap_expert.py +++ b/src/openagent/experts/swap_expert.py @@ -2,21 +2,27 @@ from enum import Enum from typing import Optional, Type -import aiohttp -from aiocache import Cache -from aiocache.decorators import cached from langchain.callbacks.manager import ( AsyncCallbackManagerForToolRun, CallbackManagerForToolRun, ) from langchain.tools import BaseTool -from loguru import logger from pydantic import BaseModel, Field -from openagent.dto.mutation import Swap from openagent.experts.token_util import chain_name_to_id, get_token_data_by_key, select_best_token +class Swap(BaseModel): + from_token: str + from_token_address: str + to_token: str + to_token_address: str + amount: str + type: str = "swap" + from_chain_name: str + to_chain_name: str + + class ChainEnum(str, Enum): """ Enumeration for supported blockchain networks. @@ -64,12 +70,12 @@ def _run( self, from_token: str, to_token: str, - from_chain: ChainEnum, - to_chain: ChainEnum, amount: str, + from_chain: ChainEnum = ChainEnum.ETH, + to_chain: ChainEnum = ChainEnum.ETH, run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: - raise NotImplementedError + return asyncio.run(fetch_swap(from_token, to_token, from_chain, to_chain, amount)) async def _arun( self, diff --git a/src/openagent/experts/transfer_expert.py b/src/openagent/experts/transfer_expert.py index 5d6d3d6e..0b535e84 100644 --- a/src/openagent/experts/transfer_expert.py +++ b/src/openagent/experts/transfer_expert.py @@ -7,10 +7,20 @@ from langchain.tools import BaseTool from pydantic import BaseModel, Field -from openagent.dto.mutation import Transfer from openagent.experts.token_util import chain_name_to_id, select_best_token, get_token_data_by_key +class Transfer(BaseModel): + # task_id: str + to_address: str + token: str + token_address: str + chain_id: str + amount: str + logoURI: str # noqa + decimals: int + + class ParamSchema(BaseModel): to_address: str = Field( description="""extract the blockchain address mentioned in the query""", @@ -41,22 +51,22 @@ class TransferExpert(BaseTool): last_task_id: Optional[str] = None def _run( - self, - to_address: str, - token: str, - chain_name: str, - amount: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + to_address: str, + token: str, + chain_name: str, + amount: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: raise NotImplementedError async def _arun( - self, - to_address: str, - token: str, - chain_name: str = "ethereum", - amount: str = "1", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + to_address: str, + token: str, + chain_name: str = "ethereum", + amount: str = "1", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): return await fetch_transfer(to_address, token, chain_name, amount) diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 9f2006d2..434992d9 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -7,7 +7,7 @@ from chainlit.data.sql_alchemy import SQLAlchemyDataLayer from langchain.memory import ConversationBufferMemory from langchain.schema.runnable.config import RunnableConfig -from langchain_core.messages import FunctionMessage, HumanMessage +from langchain_core.messages import HumanMessage from loguru import logger from openagent.conf.env import settings @@ -86,27 +86,6 @@ def build_token(token_symbol: str, token_address: str): return f"{token_symbol}{'--' + token_address.lower() if not token_symbol == 'ETH' else ''}" -async def handle_function_message(message: FunctionMessage, msg: cl.Message): - """Handle FunctionMessage type of messages.""" - if message.name == "swap": - swap_dict = json.loads(message.content) - logger.info(swap_dict) - from_chain = swap_dict["from_chain_name"] - to_chain = swap_dict["to_chain_name"] - from_token_ = swap_dict["from_token"] - from_token_address = swap_dict["from_token_address"] - to_token = swap_dict["to_token"] - to_token_address = swap_dict["to_token_address"] - from_amount = swap_dict["amount"] - - widget = ( - f"""""" - ) - await msg.stream_token(widget) - - @cl.on_message async def on_message(message: cl.Message): """Callback function to handle user messages.""" @@ -128,23 +107,8 @@ async def on_message(message: cl.Message): ): kind = event["event"] - logger.info(event) if kind == "on_tool_end": - if event["name"] == "swap": - output = event['data']['output'] - swap_dict = json.loads(output) - from_chain = swap_dict["chain_id"] - to_chain = swap_dict["chain_id"] - from_token_ = swap_dict["from_token_address"] - to_token = swap_dict["to_token_address"] - from_amount = swap_dict["amount"] - - widget = ( - f"""""" - ) - await msg.stream_token(widget) + await handle_tool_end(event, msg) if kind == "on_chat_model_stream": if event["metadata"]["langgraph_node"] in agent_names: @@ -157,6 +121,28 @@ async def on_message(message: cl.Message): memory.chat_memory.add_ai_message(msg.content) +async def handle_tool_end(event, msg): + if event["name"] == "swap": + output = event['data']['output'] + swap_dict = json.loads(output) + logger.info(swap_dict) + from_chain = swap_dict["from_chain_name"] + to_chain = swap_dict["to_chain_name"] + from_token_ = swap_dict["from_token"] + from_token_address = swap_dict["from_token_address"] + to_token = swap_dict["to_token"] + to_token_address = swap_dict["to_token_address"] + from_amount = swap_dict["amount"] + + widget = ( + f"""""" + ) + await msg.stream_token(widget) + + def start_ui(): run_chainlit(__file__) From 4c882666251e89df574d18606edc153c61b9371b Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 22 Jul 2024 14:44:25 +0800 Subject: [PATCH 11/85] chore: Refactor agent descriptions for clarity and engagement --- src/openagent/workflows/member.py | 66 ++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/src/openagent/workflows/member.py b/src/openagent/workflows/member.py index a3d46f59..05e19749 100644 --- a/src/openagent/workflows/member.py +++ b/src/openagent/workflows/member.py @@ -1,26 +1,80 @@ members = [ { "name": "market_analysis_agent", - "description": "MarketAnalyst, provides market data analysis. Helps users understand market dynamics and trends by retrieving real-time token price information.", + "description": """ +MarketAnalyst: Provides market data analysis and insights. + +Responsibilities: +1. Retrieve real-time token price information +2. Analyze market trends and dynamics +3. Offer insights to help users understand the market + +Maintain a professional and informative tone while providing clear, concise analysis. + """.strip(), }, { "name": "social_track_agent", - "description": "Social Tracker, tracks web3 social media and community interactions. Provides the latest updates and discussions from the web3 ecosystem using available tools.", + "description": """ +SocialTracker: Monitors web3 social media and community interactions. + +Responsibilities: +1. Track latest updates from web3 social platforms +2. Summarize key discussions and trends +3. Provide relevant social insights to users + +Deliver information in a clear, engaging manner, highlighting important community sentiments. + """.strip(), }, { "name": "asset_management_agent", - "description": "AssetManager, helps users query and manage their crypto assets, including tokens and NFTs.", + "description": """ +AssetManager: Assists with crypto asset management. + +Responsibilities: +1. Query and report on users' token balances +2. Check and inform about users' NFT holdings +3. Generate cross-chain swap widgets for users + +Provide accurate information with a friendly tone, using occasional puns or emojis to keep interactions engaging. + """.strip(), }, { "name": "block_explorer_agent", - "description": "BlockExplorer, assists users in exploring blockchain data, including block height, transaction details, gas fees, and other relevant information.", + "description": """ +BlockExplorer: Assists in exploring blockchain data. + +Responsibilities: +1. Retrieve and explain block height information +2. Provide transaction details and status updates +3. Inform about gas fees and other relevant blockchain data + +Present technical information in an easy-to-understand manner, using analogies when helpful. + """.strip(), }, { "name": "research_analyst_agent", - "description": "ResearchAnalyst, assists users in conducting research and analysis related to web3 projects. Provides detailed information about project progress, team members, market trends, investors, and other relevant data to support investment decisions.", + "description": """ +ResearchAnalyst: Conducts and provides web3 project research. + +Responsibilities: +1. Gather detailed information on web3 projects +2. Analyze project progress, team members, and investors +3. Provide insights on market trends related to specific projects + +Deliver comprehensive yet concise reports, emphasizing key points for investment decisions. + """.strip(), }, { "name": "fallback_agent", - "description": "FallbackAgent, answers user queries when other agents are not related to the query, or when the query is unclear. Handles conversations that should continue with the fallback agent.", + "description": """ +FallbackAgent: Handles general queries and conversations. + +Responsibilities: +1. Answer user queries unrelated to other agents' specialties +2. Clarify unclear requests and provide general assistance +3. Maintain conversation continuity when needed + +Respond with versatility and friendliness, guiding users to appropriate specialists when necessary. + """.strip(), }, ] From d9de3abf0d4b448e0ccb281a9fed23a4f8108e2e Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 22 Jul 2024 14:44:36 +0800 Subject: [PATCH 12/85] chore: Remove unnecessary router includes in app.py --- src/openagent/app.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/openagent/app.py b/src/openagent/app.py index 8cbf815b..b671f00b 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -8,9 +8,6 @@ from starlette.responses import FileResponse, JSONResponse from starlette.staticfiles import StaticFiles -from openagent.router.chat import chat_router -from openagent.router.onboarding import onboarding_router -from openagent.router.session import session_router load_dotenv() app = FastAPI(title="OpenAgent", description="") @@ -29,10 +26,6 @@ async def health_check(): return JSONResponse(content={"status": "ok"}) -app.include_router(onboarding_router) -app.include_router(chat_router) -app.include_router(session_router) - @app.get("/widget/swap") async def swap_root(): From 9e7f51f9d55eb23c8cca914009236b73e9e54ce8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 22 Jul 2024 15:00:39 +0800 Subject: [PATCH 13/85] chore: resolve pre-commit errors --- .pre-commit-config.yaml | 30 +++++------ src/openagent/agents/block_explore.py | 3 +- src/openagent/agents/market_analysis.py | 3 +- src/openagent/app.py | 2 - src/openagent/conf/env.py | 29 +++++----- src/openagent/conf/llm_provider.py | 6 +-- src/openagent/db/database.py | 4 +- src/openagent/db/models.py | 6 +-- src/openagent/experts/feed_expert.py | 4 +- src/openagent/experts/nft_expert.py | 10 +--- src/openagent/experts/search_expert.py | 2 +- src/openagent/experts/swap_expert.py | 60 +++++++++------------ src/openagent/experts/token_util.py | 9 ++-- src/openagent/experts/transfer_expert.py | 26 ++++----- src/openagent/index/pgvector_store.py | 6 ++- src/openagent/tools/coin_market_tool.py | 3 +- src/openagent/tools/funding_rate_tool.py | 8 ++- src/openagent/tools/nft_balance_tool.py | 4 +- src/openagent/tools/nft_tool.py | 10 +--- src/openagent/tools/price_tool.py | 13 ++--- src/openagent/tools/project_tool.py | 16 ++---- src/openagent/tools/search_tool.py | 2 +- src/openagent/tools/token_balance_tool.py | 4 +- src/openagent/ui/app.py | 28 +++++----- src/openagent/ui/profile.py | 20 +++---- src/openagent/workflows/supervisor_chain.py | 19 ++----- src/openagent/workflows/workflow.py | 22 +++----- src/pyproject.toml | 2 +- 28 files changed, 135 insertions(+), 216 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f41b55d5..d20a0db5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,30 +3,30 @@ repos: rev: v4.4.0 hooks: - id: check-ast - files: ^backend/ + files: ^src/ - id: check-case-conflict - files: ^backend/ + files: ^src/ - id: check-docstring-first - files: ^backend/ + files: ^src/ - id: check-executables-have-shebangs - files: ^backend/ + files: ^src/ - id: check-json - files: ^backend/ + files: ^src/ - id: check-added-large-files - files: ^backend/ + files: ^src/ - id: pretty-format-json args: - "--autofix" - "--indent=4" - files: ^backend/ + files: ^src/ - id: detect-private-key - files: ^backend/ + files: ^src/ - id: debug-statements - files: ^backend/ + files: ^src/ - id: end-of-file-fixer - files: ^backend/ + files: ^src/ - id: trailing-whitespace - files: ^backend/ + files: ^src/ - repo: local hooks: - id: mypy @@ -35,20 +35,20 @@ repos: require_serial: true language: system types: [ python ] - files: ^backend/ + files: ^src/ pass_filenames: false - args: [--config-file=backend/pyproject.toml] + args: [--config-file=src/pyproject.toml] - id: ruff-lint name: ruff-lint entry: ruff check --fix require_serial: true language: system - files: ^backend/ + files: ^src/ types: [ python ] - id: ruff-format name: ruff-format entry: ruff format require_serial: true language: system - files: ^backend/ + files: ^src/ types: [ python ] diff --git a/src/openagent/agents/block_explore.py b/src/openagent/agents/block_explore.py index 3d891598..c12bce2b 100644 --- a/src/openagent/agents/block_explore.py +++ b/src/openagent/agents/block_explore.py @@ -1,10 +1,9 @@ from dotenv import load_dotenv -from langchain_openai import ChatOpenAI from openagent.agents.agent_factory import create_agent from openagent.conf.llm_provider import get_current_llm -from openagent.tools.tavily_tool import tavily_tool from openagent.tools.block_stat_tool import BlockStatTool +from openagent.tools.tavily_tool import tavily_tool load_dotenv() diff --git a/src/openagent/agents/market_analysis.py b/src/openagent/agents/market_analysis.py index 5b4ebb47..bda4cf5f 100644 --- a/src/openagent/agents/market_analysis.py +++ b/src/openagent/agents/market_analysis.py @@ -1,13 +1,12 @@ from dotenv import load_dotenv -from langchain_openai import ChatOpenAI from openagent.agents.agent_factory import create_agent from openagent.conf.llm_provider import get_current_llm from openagent.tools.coin_market_tool import CoinMarketTool from openagent.tools.funding_rate_tool import FundingRateTool -from openagent.tools.tavily_tool import tavily_tool from openagent.tools.nft_tool import NFTTool from openagent.tools.price_tool import PriceTool +from openagent.tools.tavily_tool import tavily_tool load_dotenv() llm = get_current_llm() diff --git a/src/openagent/app.py b/src/openagent/app.py index b671f00b..d8b93c27 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -8,7 +8,6 @@ from starlette.responses import FileResponse, JSONResponse from starlette.staticfiles import StaticFiles - load_dotenv() app = FastAPI(title="OpenAgent", description="") @@ -26,7 +25,6 @@ async def health_check(): return JSONResponse(content={"status": "ok"}) - @app.get("/widget/swap") async def swap_root(): print("swap_root") diff --git a/src/openagent/conf/env.py b/src/openagent/conf/env.py index 585572eb..513e1fed 100644 --- a/src/openagent/conf/env.py +++ b/src/openagent/conf/env.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import List, Optional from dotenv import load_dotenv from pydantic import Field, field_validator @@ -12,32 +12,29 @@ class Settings(BaseSettings): DB_CONNECTION: str = Field(..., env="DB_CONNECTION", description="PGVector connection string") # Online LLM API KEY - VERTEX_PROJECT_ID: Optional[str] = Field(default=None, - description="Google cloud vertex project id (optional)") - OPENAI_API_KEY: Optional[str] = Field(default=None, env="OPENAI_API_KEY", - description="OpenAI API Key (optional)") + VERTEX_PROJECT_ID: Optional[str] = Field(default=None, description="Google cloud vertex project id (optional)") + OPENAI_API_KEY: Optional[str] = Field(default=None, env="OPENAI_API_KEY", description="OpenAI API Key (optional)") # Local LLM configuration - OLLAMA_MODEL: Optional[List[str]] = Field(default=None, env="OLLAMA_MODEL", - description="OLLAMA Model list (optional)") - OLLAMA_MODEL_URL: Optional[str] = Field(default=None, env="OLLAMA_MODEL_URL", - description="OLLAMA Model URL (optional)") + OLLAMA_MODEL: Optional[List[str]] = Field(default=None, env="OLLAMA_MODEL", description="OLLAMA Model list (optional)") + OLLAMA_MODEL_URL: Optional[str] = Field(default=None, env="OLLAMA_MODEL_URL", description="OLLAMA Model URL (optional)") # Tool API Keys NFTSCAN_API_KEY: Optional[str] = Field(..., env="NFTSCAN_API_KEY", description="NFTScan API Key (optional)") - RSS3_DATA_API: Optional[str] = Field(default="https://testnet.rss3.io/data", env="RSS3_DATA_API", - description="RSS3 Data API with a default value") - RSS3_SEARCH_API: Optional[str] = Field(default="https://devnet.rss3.io/search", env="RSS3_SEARCH_API", - description="RSS3 Search API with a default value") + RSS3_DATA_API: Optional[str] = Field( + default="https://testnet.rss3.io/data", env="RSS3_DATA_API", description="RSS3 Data API with a default value" + ) + RSS3_SEARCH_API: Optional[str] = Field( + default="https://devnet.rss3.io/search", env="RSS3_SEARCH_API", description="RSS3 Search API with a default value" + ) COVALENT_API_KEY: Optional[str] = Field(..., env="COVALENT_API_KEY") ROOTDATA_API_KEY: Optional[str] = Field(..., env="ROOTDATA_API_KEY") COINGECKO_API_KEY: Optional[str] = Field(..., env="COINGECKO_API_KEY") - # Validator to split comma-separated string into a list @field_validator("OLLAMA_MODEL", mode="before") - def split_string(cls, v): + def split_string(self, v): if isinstance(v, str): - return v.split(',') + return v.split(",") return v diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index d7dd3ce6..5c991fba 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -11,10 +11,10 @@ def get_available_providers(): providers = {} if settings.OPENAI_API_KEY: - providers['gpt-3.5-turbo'] = ChatOpenAI(model="gpt-3.5-turbo") - providers['gpt-4o'] = ChatOpenAI(model="gpt-4o") + providers["gpt-3.5-turbo"] = ChatOpenAI(model="gpt-3.5-turbo") + providers["gpt-4o"] = ChatOpenAI(model="gpt-4o") if settings.VERTEX_PROJECT_ID: - providers['gemini-1.5-pro'] = ChatVertexAI(model="gemini-1.5-pro") + providers["gemini-1.5-pro"] = ChatVertexAI(model="gemini-1.5-pro") return providers diff --git a/src/openagent/db/database.py b/src/openagent/db/database.py index 87e7e1fa..057555b4 100644 --- a/src/openagent/db/database.py +++ b/src/openagent/db/database.py @@ -3,7 +3,7 @@ from sqlalchemy_utils import create_database, database_exists from openagent.conf.env import settings -from openagent.db.models import Base, User +from openagent.db.models import Base url = settings.DB_CONNECTION @@ -13,5 +13,3 @@ Base.metadata.create_all(bind=engine) # type: ignore DBSession = sessionmaker(bind=engine) - - diff --git a/src/openagent/db/models.py b/src/openagent/db/models.py index 4c76538f..2d7029b7 100644 --- a/src/openagent/db/models.py +++ b/src/openagent/db/models.py @@ -1,14 +1,12 @@ import uuid -from sqlalchemy import ARRAY, JSON, Boolean, Column, DateTime, Integer, String, Text +from sqlalchemy import ARRAY, JSON, Boolean, Column, Integer, Text from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import declarative_base -from sqlalchemy.sql import func - -from openagent.dto.task import TaskStatus Base = declarative_base() # type: ignore + class User(Base): # type: ignore __tablename__ = "users" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) diff --git a/src/openagent/experts/feed_expert.py b/src/openagent/experts/feed_expert.py index 2c770b4e..52be80b8 100644 --- a/src/openagent/experts/feed_expert.py +++ b/src/openagent/experts/feed_expert.py @@ -60,9 +60,7 @@ async def fetch_feeds(address: str): if "actions" in activity: formatted_activity += "### Actions:\n" for action in activity["actions"]: - formatted_activity += ( - f"- {action['type']} from {action['from']} to {action['to']}\n" - ) + formatted_activity += f"- {action['type']} from {action['from']} to {action['to']}\n" if "metadata" in action: for key, value in action["metadata"].items(): formatted_activity += f" - {key}: {value}\n" diff --git a/src/openagent/experts/nft_expert.py b/src/openagent/experts/nft_expert.py index 235a4b2f..4219207d 100644 --- a/src/openagent/experts/nft_expert.py +++ b/src/openagent/experts/nft_expert.py @@ -13,10 +13,7 @@ class ARGS(BaseModel): - action: str = Field( - description="Specify the operation to perform: 'search' for NFT " - "collection search, 'rank' for collection ranking" - ) + action: str = Field(description="Specify the operation to perform: 'search' for NFT " "collection search, 'rank' for collection ranking") keyword: str = Field( default="", description="NFT symbol or collection name, required only for 'action=search'", @@ -53,10 +50,7 @@ def _run( elif action == "rank": return self.collection_ranking(sort_field) else: - return ( - "Error: Unknown operation type. " - "Please specify 'action' as 'search' or 'rank'." - ) + return "Error: Unknown operation type. " "Please specify 'action' as 'search' or 'rank'." async def _arun( self, diff --git a/src/openagent/experts/search_expert.py b/src/openagent/experts/search_expert.py index 70a99776..270291f2 100644 --- a/src/openagent/experts/search_expert.py +++ b/src/openagent/experts/search_expert.py @@ -41,7 +41,7 @@ class SearchExpert(BaseTool): description = """ A versatile search tool that can perform various types of searches based on the query type: - For queries related to charts, data visualization, or dashboards, use Dune search. - - For queries about project introductions, current events or real-time information, use Google search.""" # noqa: E501 + - For queries about project introductions, current events or real-time information, use Google search.""" args_schema: Type[SearchSchema] = SearchSchema def _run( diff --git a/src/openagent/experts/swap_expert.py b/src/openagent/experts/swap_expert.py index d49ef19d..cdf674fa 100644 --- a/src/openagent/experts/swap_expert.py +++ b/src/openagent/experts/swap_expert.py @@ -27,6 +27,7 @@ class ChainEnum(str, Enum): """ Enumeration for supported blockchain networks. """ + ETH = "ETH" BSC = "BSC" ARBITRUM = "ARBITRUM" @@ -38,53 +39,43 @@ class ParamSchema(BaseModel): """ Schema for the parameters required for a token swap. """ - from_token: str = Field( - description="Symbol of the token to swap from, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'." - ) - to_token: str = Field( - description="Symbol of the token to swap to, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'." - ) - from_chain: ChainEnum = Field( - default=ChainEnum.ETH, - description="Blockchain network to swap from. Default: 'ETH'." - ) - to_chain: ChainEnum = Field( - default=ChainEnum.ETH, - description="Blockchain network to swap to. Default: 'ETH'." - ) - amount: str = Field( - description="Amount of the from-side token to swap, e.g., '0.1', '1', '10'. Default: '1'." - ) + + from_token: str = Field(description="Symbol of the token to swap from, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") + to_token: str = Field(description="Symbol of the token to swap to, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") + from_chain: ChainEnum = Field(default=ChainEnum.ETH, description="Blockchain network to swap from. Default: 'ETH'.") + to_chain: ChainEnum = Field(default=ChainEnum.ETH, description="Blockchain network to swap to. Default: 'ETH'.") + amount: str = Field(description="Amount of the from-side token to swap, e.g., '0.1', '1', '10'. Default: '1'.") class SwapExpert(BaseTool): """ Tool for generating a swap widget for cryptocurrency swaps. """ + name = "swap" description = "Use this tool to generate a swap widget for the user to swap cryptocurrencies." args_schema: Type[ParamSchema] = ParamSchema return_direct = False def _run( - self, - from_token: str, - to_token: str, - amount: str, - from_chain: ChainEnum = ChainEnum.ETH, - to_chain: ChainEnum = ChainEnum.ETH, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + from_token: str, + to_token: str, + amount: str, + from_chain: ChainEnum = ChainEnum.ETH, + to_chain: ChainEnum = ChainEnum.ETH, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: return asyncio.run(fetch_swap(from_token, to_token, from_chain, to_chain, amount)) async def _arun( - self, - from_token: str, - to_token: str, - from_chain: ChainEnum = ChainEnum.ETH, - to_chain: ChainEnum = ChainEnum.ETH, - amount: str = "1", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + from_token: str, + to_token: str, + from_chain: ChainEnum = ChainEnum.ETH, + to_chain: ChainEnum = ChainEnum.ETH, + amount: str = "1", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): return await fetch_swap(from_token, to_token, from_chain, to_chain, amount) @@ -107,10 +98,7 @@ async def fetch_swap(from_token: str, to_token: str, from_chain: ChainEnum, to_c to_chain_id = chain_name_to_id(to_chain.value) # Fetch token data concurrently - from_token_data, to_token_data = await asyncio.gather( - select_best_token(from_token, from_chain_id), - select_best_token(to_token, to_chain_id) - ) + from_token_data, to_token_data = await asyncio.gather(select_best_token(from_token, from_chain_id), select_best_token(to_token, to_chain_id)) swap = Swap( from_token=get_token_data_by_key(from_token_data, "symbol"), @@ -119,6 +107,6 @@ async def fetch_swap(from_token: str, to_token: str, from_chain: ChainEnum, to_c to_token_address=get_token_data_by_key(to_token_data, "address"), from_chain_name=from_chain.value, to_chain_name=to_chain.value, - amount=amount + amount=amount, ) return swap.model_dump_json() diff --git a/src/openagent/experts/token_util.py b/src/openagent/experts/token_util.py index 3c153cc0..bcf0ea0c 100644 --- a/src/openagent/experts/token_util.py +++ b/src/openagent/experts/token_util.py @@ -1,4 +1,4 @@ -from typing import Optional, Dict, List +from typing import Dict, List, Optional import aiohttp from aiocache import Cache @@ -52,7 +52,7 @@ async def fetch_tokens() -> Dict[str, List[Dict]]: headers = {"Accept": "application/json"} logger.info(f"Fetching new data from {url}") - async with aiohttp.ClientSession() as session: + async with aiohttp.ClientSession() as session: # noqa async with session.get(url, headers=headers) as response: token_list = await response.json() return token_list["tokens"] @@ -75,10 +75,7 @@ async def select_best_token(keyword: str, chain_id: str) -> Optional[Dict]: tokens_on_chain = tokens.get(chain_id, []) # Filter based on symbol and name - results = [ - token for token in tokens_on_chain - if token["symbol"].lower() == keyword or token["name"].lower() == keyword - ] + results = [token for token in tokens_on_chain if token["symbol"].lower() == keyword or token["name"].lower() == keyword] if results: if len(results) == 1: diff --git a/src/openagent/experts/transfer_expert.py b/src/openagent/experts/transfer_expert.py index 0b535e84..0fe5f4eb 100644 --- a/src/openagent/experts/transfer_expert.py +++ b/src/openagent/experts/transfer_expert.py @@ -7,7 +7,7 @@ from langchain.tools import BaseTool from pydantic import BaseModel, Field -from openagent.experts.token_util import chain_name_to_id, select_best_token, get_token_data_by_key +from openagent.experts.token_util import chain_name_to_id, get_token_data_by_key, select_best_token class Transfer(BaseModel): @@ -51,22 +51,22 @@ class TransferExpert(BaseTool): last_task_id: Optional[str] = None def _run( - self, - to_address: str, - token: str, - chain_name: str, - amount: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + to_address: str, + token: str, + chain_name: str, + amount: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: raise NotImplementedError async def _arun( - self, - to_address: str, - token: str, - chain_name: str = "ethereum", - amount: str = "1", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + to_address: str, + token: str, + chain_name: str = "ethereum", + amount: str = "1", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): return await fetch_transfer(to_address, token, chain_name, amount) diff --git a/src/openagent/index/pgvector_store.py b/src/openagent/index/pgvector_store.py index 08d9b3f7..3ed098f8 100644 --- a/src/openagent/index/pgvector_store.py +++ b/src/openagent/index/pgvector_store.py @@ -10,10 +10,12 @@ def build_vector_store() -> PGVector: collection_name = "backend" - if settings.MODEL_NAME.startswith("gemini"): + if settings.OPENAI_API_KEY is not None: + underlying_embeddings = OpenAIEmbeddings(model="text-embedding-3-large") + elif settings.VERTEX_PROJECT_ID is not None: underlying_embeddings = VertexAIEmbeddings(model_name="textembedding-gecko@003", project=settings.VERTEX_PROJECT_ID) else: - underlying_embeddings = OpenAIEmbeddings(model="text-embedding-3-large") + raise ValueError("No API key provided for OpenAI or VertexAI") return PGVector( embeddings=underlying_embeddings, collection_name=collection_name, diff --git a/src/openagent/tools/coin_market_tool.py b/src/openagent/tools/coin_market_tool.py index b9bcaa8d..9ebdce34 100644 --- a/src/openagent/tools/coin_market_tool.py +++ b/src/openagent/tools/coin_market_tool.py @@ -14,8 +14,7 @@ class ARGS(BaseModel): order: str = Field( - description="sort result by field, default: market_cap_desc. options: market_cap_desc," - "market_cap_asc,volume_desc,volume_asc" + description="sort result by field, default: market_cap_desc. options: market_cap_desc," "market_cap_asc,volume_desc,volume_asc" ) size: int = Field(description="number of coins to return, default: 20") diff --git a/src/openagent/tools/funding_rate_tool.py b/src/openagent/tools/funding_rate_tool.py index c920a51a..468f7c0b 100644 --- a/src/openagent/tools/funding_rate_tool.py +++ b/src/openagent/tools/funding_rate_tool.py @@ -12,9 +12,7 @@ class ARGS(BaseModel): - exchange: str = Field( - description="Name of the exchange (ccxt supported), e.g., 'binance'" - ) + exchange: str = Field(description="Name of the exchange (ccxt supported), e.g., 'binance'") symbol: str = Field(description="Trading pair symbol, e.g., 'BTC/USDT:USDT'") @@ -53,9 +51,9 @@ def fetch_funding_rate(exchange_name: str, symbol: str) -> float: funding_rate = exchange.fetch_funding_rate(symbol) return funding_rate - except Exception as e: # noqa + except Exception as e: logger.warning(f"Fetch funding rate error from {exchange_name}: {e}") - raise Exception(f"No funding rate found for {symbol} on {exchange_name}") + raise e if __name__ == "__main__": diff --git a/src/openagent/tools/nft_balance_tool.py b/src/openagent/tools/nft_balance_tool.py index 9914d793..815491b1 100644 --- a/src/openagent/tools/nft_balance_tool.py +++ b/src/openagent/tools/nft_balance_tool.py @@ -13,9 +13,7 @@ class ARGS(BaseModel): - chain: str = Field( - description="chain name,options:eth-mainnet,optimism-mainnet,arbitrum-mainnet,bsc-mainnet" - ) + chain: str = Field(description="chain name,options:eth-mainnet,optimism-mainnet,arbitrum-mainnet,bsc-mainnet") wallet_address: str = Field(description="wallet address") diff --git a/src/openagent/tools/nft_tool.py b/src/openagent/tools/nft_tool.py index 6734692e..e42c830b 100644 --- a/src/openagent/tools/nft_tool.py +++ b/src/openagent/tools/nft_tool.py @@ -13,10 +13,7 @@ class ARGS(BaseModel): - action: str = Field( - description="Specify the operation to perform: 'search' for NFT " - "collection search, 'rank' for collection ranking" - ) + action: str = Field(description="Specify the operation to perform: 'search' for NFT " "collection search, 'rank' for collection ranking") keyword: Optional[str] = Field( default=None, description="NFT symbol or collection name, required only for 'action=search'", @@ -53,10 +50,7 @@ def _run( elif action == "rank": return self.collection_ranking(sort_field) else: - return ( - "Error: Unknown operation type. " - "Please specify 'action' as 'search' or 'rank'." - ) + return "Error: Unknown operation type. " "Please specify 'action' as 'search' or 'rank'." async def _arun( self, diff --git a/src/openagent/tools/price_tool.py b/src/openagent/tools/price_tool.py index b555e1de..826a6219 100644 --- a/src/openagent/tools/price_tool.py +++ b/src/openagent/tools/price_tool.py @@ -19,10 +19,11 @@ class PriceTool(BaseTool): name = "price" description = "use this tool to get the price of a token." args_schema: Type[ARGS] = ARGS + def _run( - self, - token: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + token: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: try: return f"The price of {token} is {asyncio.run(fetch_price(token))}" @@ -30,9 +31,9 @@ def _run( return f"error: {e}" async def _arun( - self, - token: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + token: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ) -> str: try: return f"The price of {token} is {await fetch_price(token)}" diff --git a/src/openagent/tools/project_tool.py b/src/openagent/tools/project_tool.py index cd2fbc69..38b90520 100644 --- a/src/openagent/tools/project_tool.py +++ b/src/openagent/tools/project_tool.py @@ -36,9 +36,7 @@ def _fetch_project_sync(keyword: str) -> str: class ProjectTool(BaseTool): name = "project" - description = ( - "get the project information like investors, team members, social media, etc." - ) + description = "get the project information like investors, team members, social media, etc." args_schema: Type[ARGS] = ARGS def _run( @@ -61,9 +59,7 @@ async def _arun( async def fetch_project_detail(session, project_id: int) -> dict: url = "https://api.rootdata.com/open/get_item" - payload = json.dumps( - {"project_id": project_id, "include_team": True, "include_investors": True} - ) + payload = json.dumps({"project_id": project_id, "include_team": True, "include_investors": True}) async with session.post(url, headers=HEADERS, data=payload) as response: response_text = await response.text() @@ -75,16 +71,12 @@ async def fetch_project(keyword: str) -> list: url = "https://api.rootdata.com/open/ser_inv" payload = json.dumps({"query": keyword, "variables": {}}) - async with aiohttp.ClientSession() as session, session.post( - url, headers=HEADERS, data=payload - ) as response: + async with aiohttp.ClientSession() as session, session.post(url, headers=HEADERS, data=payload) as response: response_text = await response.text() data = json.loads(response_text)["data"] project_ids = [item["id"] for item in data if item["type"] == 1][0:2] - tasks = [ - fetch_project_detail(session, project_id) for project_id in project_ids - ] + tasks = [fetch_project_detail(session, project_id) for project_id in project_ids] return list(await asyncio.gather(*tasks)) diff --git a/src/openagent/tools/search_tool.py b/src/openagent/tools/search_tool.py index ee7cb5f2..502ec900 100644 --- a/src/openagent/tools/search_tool.py +++ b/src/openagent/tools/search_tool.py @@ -1,12 +1,12 @@ from typing import Optional, Type import requests -from langchain_community.utilities import SerpAPIWrapper from langchain.callbacks.manager import ( AsyncCallbackManagerForToolRun, CallbackManagerForToolRun, ) from langchain.tools import BaseTool +from langchain_community.utilities import SerpAPIWrapper from pydantic import BaseModel, Field from openagent.conf.env import settings diff --git a/src/openagent/tools/token_balance_tool.py b/src/openagent/tools/token_balance_tool.py index 16357fcb..b26d7657 100644 --- a/src/openagent/tools/token_balance_tool.py +++ b/src/openagent/tools/token_balance_tool.py @@ -13,9 +13,7 @@ class ARGS(BaseModel): - chain: str = Field( - description="chain name,options:btc-mainnet,eth-mainnet,optimism-mainnet,arbitrum-mainnet,bsc-mainnet" - ) + chain: str = Field(description="chain name,options:btc-mainnet,eth-mainnet,optimism-mainnet,arbitrum-mainnet,bsc-mainnet") wallet_address: str = Field(description="wallet address") diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 434992d9..5125e960 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -33,10 +33,10 @@ def initialize_memory() -> ConversationBufferMemory: @cl.oauth_callback def oauth_callback( - provider_id: str, - token: str, - raw_user_data: Dict[str, str], - default_user: cl.User, + provider_id: str, + token: str, + raw_user_data: Dict[str, str], + default_user: cl.User, ) -> Optional[cl.User]: """OAuth callback function.""" return default_user @@ -59,9 +59,7 @@ async def on_chat_start(): provider_key = profile_name_to_provider_key(profile) set_current_llm(provider_key) setup_runnable() - await cl.Message( - content=f"starting chat using the {profile} chat profile" - ).send() + await cl.Message(content=f"starting chat using the {profile} chat profile").send() @cl.on_chat_resume @@ -83,7 +81,7 @@ async def on_chat_resume(thread: cl_data.ThreadDict): def build_token(token_symbol: str, token_address: str): - return f"{token_symbol}{'--' + token_address.lower() if not token_symbol == 'ETH' else ''}" + return f"{token_symbol}{'--' + token_address.lower() if token_symbol != 'ETH' else ''}" @cl.on_message @@ -97,20 +95,18 @@ async def on_message(message: cl.Message): set_current_llm(provider_key) msg = cl.Message(content="") - agent_names = [member['name'] for member in members] + agent_names = [member["name"] for member in members] # try: async for event in runnable.astream_events( - {"messages": [HumanMessage(content=message.content)]}, - config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]), - version="v1", + {"messages": [HumanMessage(content=message.content)]}, + config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]), + version="v1", ): - kind = event["event"] if kind == "on_tool_end": await handle_tool_end(event, msg) - - if kind == "on_chat_model_stream": + elif kind == "on_chat_model_stream": # noqa if event["metadata"]["langgraph_node"] in agent_names: content = event["data"]["chunk"].content if content: @@ -123,7 +119,7 @@ async def on_message(message: cl.Message): async def handle_tool_end(event, msg): if event["name"] == "swap": - output = event['data']['output'] + output = event["data"]["output"] swap_dict = json.loads(output) logger.info(swap_dict) from_chain = swap_dict["from_chain_name"] diff --git a/src/openagent/ui/profile.py b/src/openagent/ui/profile.py index e15038d5..805ce338 100644 --- a/src/openagent/ui/profile.py +++ b/src/openagent/ui/profile.py @@ -1,32 +1,28 @@ import chainlit as cl provider_key_to_profile_info = { - 'gpt-3.5-turbo': { + "gpt-3.5-turbo": { "name": "GPT-3.5", "markdown_description": "The underlying LLM model is **GPT-3.5**.", - "icon": "https://custom.typingmind.com/assets/models/gpt-35.webp" + "icon": "https://custom.typingmind.com/assets/models/gpt-35.webp", }, - 'gpt-4o': { + "gpt-4o": { "name": "GPT-4", "markdown_description": "The underlying LLM model is **GPT-4**.", - "icon": "https://custom.typingmind.com/assets/models/gpt-4.webp" + "icon": "https://custom.typingmind.com/assets/models/gpt-4.webp", }, - 'gemini-1.5-pro': { + "gemini-1.5-pro": { "name": "Gemini 1.5 Pro", "markdown_description": "The underlying LLM model is **Gemini 1.5 Pro**.", - "icon": "https://custom.typingmind.com/assets/models/gemini.png" - } + "icon": "https://custom.typingmind.com/assets/models/gemini.png", + }, } def provider_to_profile(provider_key): profile_info = provider_key_to_profile_info.get(provider_key) if profile_info: - return cl.ChatProfile( - name=profile_info["name"], - markdown_description=profile_info["markdown_description"], - icon=profile_info["icon"] - ) + return cl.ChatProfile(name=profile_info["name"], markdown_description=profile_info["markdown_description"], icon=profile_info["icon"]) return None diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index c5aa18cc..66a4d851 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -13,11 +13,7 @@ " respond with the worker to act next. Each worker will perform a" " task and respond with their results and status. When finished," " respond with FINISH." -).format( - members=", ".join( - [f"{member['name']} ({member['description']})" for member in members] - ) -) +).format(members=", ".join([f"{member['name']} ({member['description']})" for member in members])) options = ["FINISH"] + [member["name"] for member in members] function_def = { @@ -43,18 +39,11 @@ MessagesPlaceholder(variable_name="messages"), ( "system", - "Given the conversation above, who should act next?" - " Or should we FINISH? Select one of: {options}", + "Given the conversation above, who should act next?" " Or should we FINISH? Select one of: {options}", ), ] -).partial( - options=str(options), members=", ".join([member["name"] for member in members]) -) +).partial(options=str(options), members=", ".join([member["name"] for member in members])) llm = get_current_llm() -supervisor_chain = ( - prompt - | llm.bind_functions(functions=[function_def], function_call="route") - | JsonOutputFunctionsParser() -) +supervisor_chain = prompt | llm.bind_functions(functions=[function_def], function_call="route") | JsonOutputFunctionsParser() diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py index 4b78a4d0..45e7b6ca 100644 --- a/src/openagent/workflows/workflow.py +++ b/src/openagent/workflows/workflow.py @@ -1,14 +1,11 @@ import operator from typing import Annotated, Sequence, TypedDict -from langchain_core.messages import BaseMessage -from langchain_core.messages import HumanMessage +from langchain_core.messages import BaseMessage, HumanMessage from langgraph.graph import END, StateGraph from loguru import logger - - class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], operator.add] next: str @@ -32,19 +29,12 @@ def build_workflow(): from openagent.agents.social_track import social_track_agent from openagent.workflows.member import members from openagent.workflows.supervisor_chain import supervisor_chain - market_analysis_agent_node = create_node( - market_analysis_agent, "market_analysis_agent" - ) + + market_analysis_agent_node = create_node(market_analysis_agent, "market_analysis_agent") social_track_agent_node = create_node(social_track_agent, "social_track_agent") - asset_management_agent_node = create_node( - asset_management_agent, "asset_management_agent" - ) - block_explorer_agent_node = create_node( - block_explorer_agent, "block_explorer_agent" - ) - research_analyst_agent_node = create_node( - research_analyst_agent, "research_analyst_agent" - ) + asset_management_agent_node = create_node(asset_management_agent, "asset_management_agent") + block_explorer_agent_node = create_node(block_explorer_agent, "block_explorer_agent") + research_analyst_agent_node = create_node(research_analyst_agent, "research_analyst_agent") workflow = StateGraph(AgentState) workflow.add_node("market_analysis_agent", market_analysis_agent_node) diff --git a/src/pyproject.toml b/src/pyproject.toml index 2b6bb8bd..3d4fd986 100644 --- a/src/pyproject.toml +++ b/src/pyproject.toml @@ -126,7 +126,7 @@ warn_redundant_casts = true warn_return_any = true check_untyped_defs = true show_error_codes = true -disable_error_code = ["arg-type","call-arg","unused-ignore","import-untyped","assignment","no-any-return","no-any-unimported","import-not-found","misc"] +disable_error_code = ["arg-type","call-arg","union-attr","operator","unused-ignore","import-untyped","assignment","no-any-return","no-any-unimported","import-not-found","misc"] [build-system] From d268df07f08acad146385a579b06a55303f544e4 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 22 Jul 2024 17:36:26 +0800 Subject: [PATCH 14/85] fix: pydantic validator --- src/openagent/conf/env.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openagent/conf/env.py b/src/openagent/conf/env.py index 513e1fed..865849df 100644 --- a/src/openagent/conf/env.py +++ b/src/openagent/conf/env.py @@ -32,7 +32,7 @@ class Settings(BaseSettings): # Validator to split comma-separated string into a list @field_validator("OLLAMA_MODEL", mode="before") - def split_string(self, v): + def split_string(cls, v): if isinstance(v, str): return v.split(",") return v From c097d671ec2d290e018881c3599139906f040876 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 26 Jul 2024 18:45:25 +0800 Subject: [PATCH 15/85] feat: Add coingecko price widget for price tool --- src/openagent/app.py | 6 ++- src/openagent/tools/price_tool.py | 67 ++++++++++++++---------- src/openagent/ui/app.py | 29 +++++----- src/widget/index.html | 20 +++---- src/widget/src/components/PriceChart.tsx | 23 ++++++++ src/widget/src/custom.d.ts | 6 +++ src/widget/src/main.tsx | 4 +- 7 files changed, 102 insertions(+), 53 deletions(-) create mode 100644 src/widget/src/components/PriceChart.tsx create mode 100644 src/widget/src/custom.d.ts diff --git a/src/openagent/app.py b/src/openagent/app.py index d8b93c27..7cecee36 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -27,7 +27,11 @@ async def health_check(): @app.get("/widget/swap") async def swap_root(): - print("swap_root") + return FileResponse(os.path.join("dist", "index.html")) + + +@app.get("/widget/price-chart") +async def chart_price_root(): return FileResponse(os.path.join("dist", "index.html")) diff --git a/src/openagent/tools/price_tool.py b/src/openagent/tools/price_tool.py index 826a6219..f86e6c1f 100644 --- a/src/openagent/tools/price_tool.py +++ b/src/openagent/tools/price_tool.py @@ -1,15 +1,17 @@ import asyncio +import json from typing import Optional, Type -import ccxt +import requests from langchain.callbacks.manager import ( AsyncCallbackManagerForToolRun, CallbackManagerForToolRun, ) from langchain.tools import BaseTool -from loguru import logger from pydantic import BaseModel, Field +from openagent.conf.env import settings + class ARGS(BaseModel): token: str = Field(description="token symbol") @@ -17,39 +19,50 @@ class ARGS(BaseModel): class PriceTool(BaseTool): name = "price" - description = "use this tool to get the price of a token." + description = "use this tool to get the price widget of a token." args_schema: Type[ARGS] = ARGS def _run( - self, - token: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + token: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: - try: - return f"The price of {token} is {asyncio.run(fetch_price(token))}" - except Exception as e: - return f"error: {e}" + return asyncio.run(fetch_price(token)) async def _arun( - self, - token: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + token: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ) -> str: - try: - return f"The price of {token} is {await fetch_price(token)}" - except Exception as e: - return f"error: {e}" + return await fetch_price(token) + + +async def fetch_price(token: str) -> str: + url = f"https://pro-api.coingecko.com/api/v3/search?query={token}" + + key = settings.COINGECKO_API_KEY + headers = { + "accept": "application/json", + "x-cg-pro-api-key": key + } + + response = requests.get(url, headers=headers) + token = json.loads(response.text)['coins'][0] + token_id_ = token['id'] + + url = (f"https://pro-api.coingecko.com/api/v3/simple/price?ids={token_id_}&" + f"vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&" + f"include_24hr_change=true&include_last_updated_at=true") + + headers = { + "accept": "application/json", + "x-cg-pro-api-key": key + } + response = requests.get(url, headers=headers) -_exchanges = [ccxt.binance(), ccxt.okx(), ccxt.gateio(), ccxt.mexc()] + return response.text -async def fetch_price(base: str, quote: str = "USDT") -> float: - for exchange in _exchanges: - try: - trades = exchange.fetch_trades(f"{base.upper()}/{quote}", limit=1) - last = trades[0]["price"] - return last - except Exception as e: # noqa - logger.warning(f"fetch price error from {exchange.id}: {e}") - raise Exception(f"no market found for {base}") +if __name__ == '__main__': + print(asyncio.run(fetch_price('eth'))) diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 5125e960..1ab04e9d 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -3,7 +3,6 @@ import chainlit as cl import chainlit.data as cl_data -from chainlit.cli import run_chainlit from chainlit.data.sql_alchemy import SQLAlchemyDataLayer from langchain.memory import ConversationBufferMemory from langchain.schema.runnable.config import RunnableConfig @@ -33,10 +32,10 @@ def initialize_memory() -> ConversationBufferMemory: @cl.oauth_callback def oauth_callback( - provider_id: str, - token: str, - raw_user_data: Dict[str, str], - default_user: cl.User, + provider_id: str, + token: str, + raw_user_data: Dict[str, str], + default_user: cl.User, ) -> Optional[cl.User]: """OAuth callback function.""" return default_user @@ -99,9 +98,9 @@ async def on_message(message: cl.Message): # try: async for event in runnable.astream_events( - {"messages": [HumanMessage(content=message.content)]}, - config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]), - version="v1", + {"messages": [HumanMessage(content=message.content)]}, + config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]), + version="v1", ): kind = event["event"] if kind == "on_tool_end": @@ -138,10 +137,10 @@ async def handle_tool_end(event, msg): ) await msg.stream_token(widget) - -def start_ui(): - run_chainlit(__file__) - - -if __name__ == "__main__": - start_ui() + if event["name"] == "price": + output = event["data"]["output"] + price_dict = json.loads(output) + widget = ( + f"""""" + ) + await msg.stream_token(widget) diff --git a/src/widget/index.html b/src/widget/index.html index 73c6f5a2..96704b68 100644 --- a/src/widget/index.html +++ b/src/widget/index.html @@ -1,13 +1,15 @@ - - - - + + + + Vite + React + TS - - -
- - + + + + +
+ + diff --git a/src/widget/src/components/PriceChart.tsx b/src/widget/src/components/PriceChart.tsx new file mode 100644 index 00000000..4364d038 --- /dev/null +++ b/src/widget/src/components/PriceChart.tsx @@ -0,0 +1,23 @@ +/* eslint-disable no-console */ +function getQueryParams() { + const params = new URLSearchParams(window.location.search); + return { + token: params.get('token') || 'btc', + + }; +} + +export function PriceChart() { + const { + token + } = getQueryParams(); + + return ( + <> +
+ +
+ + ); +} diff --git a/src/widget/src/custom.d.ts b/src/widget/src/custom.d.ts new file mode 100644 index 00000000..98d0cfd4 --- /dev/null +++ b/src/widget/src/custom.d.ts @@ -0,0 +1,6 @@ +// src/custom.d.ts +declare namespace JSX { + interface IntrinsicElements { + 'gecko-coin-price-chart-widget': any; + } +} diff --git a/src/widget/src/main.tsx b/src/widget/src/main.tsx index c0554656..6929c26c 100644 --- a/src/widget/src/main.tsx +++ b/src/widget/src/main.tsx @@ -1,8 +1,9 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import {App} from './App'; -import {Route, BrowserRouter as Router, Routes} from "react-router-dom"; +import {BrowserRouter as Router, Route, Routes} from "react-router-dom"; import {Swap} from "./components/Swap"; +import {PriceChart} from "./components/PriceChart"; ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( @@ -13,6 +14,7 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( }/> }/> + }/> From 83f68a8bb1dc3c19dd9a2fbc741e29d7bfebef55 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 29 Jul 2024 12:26:01 +0800 Subject: [PATCH 16/85] feat: Add memory support for langgraph --- src/openagent/agents/fallback.py | 4 +++- src/openagent/ui/app.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/openagent/agents/fallback.py b/src/openagent/agents/fallback.py index a9d066b2..145227d4 100644 --- a/src/openagent/agents/fallback.py +++ b/src/openagent/agents/fallback.py @@ -8,17 +8,19 @@ def fallback(state): logger.info("Running fallback agent") + chat_template = ChatPromptTemplate.from_messages( [ ( "system", """ -You are openagent, when other agents are not available, you will be used to answer user queries. +You are openagent! Your answer should be detailed and include puns or jokes where possible \ And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. """, ), + *state["messages"][0:-1], ("human", "{input}"), ] ) diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 1ab04e9d..64bab549 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -98,7 +98,7 @@ async def on_message(message: cl.Message): # try: async for event in runnable.astream_events( - {"messages": [HumanMessage(content=message.content)]}, + {"messages": [*memory.chat_memory.messages, HumanMessage(content=message.content)]}, config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]), version="v1", ): From 8689fba195c60c656d16bafe026982417a61d9de Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 30 Jul 2024 15:17:32 +0800 Subject: [PATCH 17/85] chore: refactor conf --- src/openagent/app.py | 16 ++++--- src/openagent/conf/env.py | 47 ++++++++++----------- src/openagent/conf/llm_provider.py | 10 ++++- src/openagent/experts/swap_expert.py | 53 +++++++++++++++--------- src/openagent/experts/transfer_expert.py | 36 ++++++++++------ 5 files changed, 96 insertions(+), 66 deletions(-) diff --git a/src/openagent/app.py b/src/openagent/app.py index 9af41035..9b2c9d11 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -9,10 +9,10 @@ from pydantic import BaseModel from sse_starlette import EventSourceResponse from starlette import status -from starlette.responses import JSONResponse +from starlette.responses import JSONResponse, FileResponse from starlette.staticfiles import StaticFiles -from openagent.agent.function_agent import get_agent +from openagent.workflows.workflow import build_workflow load_dotenv() app = FastAPI(title="OpenAgent", description="") @@ -39,13 +39,15 @@ async def swap_root(): @app.get("/widget/price-chart") async def chart_price_root(): return FileResponse(os.path.join("dist", "index.html")) + + class Input(BaseModel): text: str @app.post("/api/stream_chat", description="streaming chat api for openagent") async def outline_creation(req: Input): - agent = get_agent("openagent") + agent = build_workflow() async def stream(): async for event in agent.astream_events({"input": req.text}, version="v1"): @@ -65,11 +67,7 @@ async def stream(): except OSError as e: logger.error(f"Error creating directory {static_dir}: {e}") -# Mount static files directory -try: - app.mount("/static", StaticFiles(directory=static_dir), name="widget") - logger.info(f"Successfully mounted static files from {static_dir}") -except Exception as e: - logger.error(f"Error mounting static files: {e}") +app.mount("/static", StaticFiles(directory=static_dir), name="widget") + mount_chainlit(app=app, target="openagent/ui/app.py", path="") diff --git a/src/openagent/conf/env.py b/src/openagent/conf/env.py index bd3ba3c3..7f1e6e64 100644 --- a/src/openagent/conf/env.py +++ b/src/openagent/conf/env.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import Optional from dotenv import load_dotenv from pydantic import Field @@ -8,29 +8,28 @@ class Settings(BaseSettings): - DB_CONNECTION: str = Field(..., env="DB_CONNECTION") - - # Online LLM API KEY - VERTEX_PROJECT_ID: Optional[str] = Field(default=None, description="Google cloud vertex project id (optional)") - OPENAI_API_KEY: Optional[str] = Field(default=None, env="OPENAI_API_KEY", description="OpenAI API Key (optional)") - # Local LLM configuration - OLLAMA_MODEL: Optional[List[str]] = Field(default=None, env="OLLAMA_MODEL", description="OLLAMA Model list (optional)") - OLLAMA_MODEL_URL: Optional[str] = Field(default=None, env="OLLAMA_MODEL_URL", description="OLLAMA Model URL (optional)") - - - GOOGLE_GEMINI_API_KEY: Optional[str] = Field(default=None) - - NFTSCAN_API_KEY: Optional[str] = Field(..., env="NFTSCAN_API_KEY", description="NFTScan API Key (optional)") - COVALENT_API_KEY: Optional[str] = Field(..., env="COVALENT_API_KEY") - ROOTDATA_API_KEY: Optional[str] = Field(..., env="ROOTDATA_API_KEY") - COINGECKO_API_KEY: Optional[str] = Field(..., env="COINGECKO_API_KEY") - RSS3_DATA_API: str = Field(default="https://gi.rss3.io", env="RSS3_DATA_API") - RSS3_SEARCH_API: str = Field(default="https://devnet.rss3.io/search", env="RSS3_SEARCH_API") - - CHAINLIT_AUTH_SECRET: Optional[str] = Field(default=None, env="CHAINLIT_AUTH_SECRET") - OAUTH_AUTH0_CLIENT_ID: Optional[str] = Field(default=None, env="OAUTH_AUTH0_CLIENT_ID") - OAUTH_AUTH0_CLIENT_SECRET: Optional[str] = Field(default=None, env="OAUTH_AUTH0_CLIENT_SECRET") - OAUTH_AUTH0_DOMAIN: Optional[str] = Field(default=None, env="OAUTH_AUTH0_DOMAIN") + # Database connection string (required) + DB_CONNECTION: str = Field(..., description="Database connection string (required)") + + # LLM provider settings: at least one provider must be set + VERTEX_PROJECT_ID: Optional[str] = Field(default=None, description="Google Cloud Vertex project ID (optional)") + OPENAI_API_KEY: Optional[str] = Field(default=None, description="OpenAI API Key (optional)") + GOOGLE_GEMINI_API_KEY: Optional[str] = Field(default=None, description="Google Gemini API Key (optional)") + OLLAMA_API_BASE: Optional[str] = Field(default=None, description="OLLAMA API Base URL (optional)") + + # API keys for various tools; some features will be disabled if not set + NFTSCAN_API_KEY: Optional[str] = Field(default=None, description="NFTScan API Key (optional)") + COVALENT_API_KEY: Optional[str] = Field(default=None, description="Covalent API Key (optional)") + ROOTDATA_API_KEY: Optional[str] = Field(default=None, description="RootData API Key (optional)") + COINGECKO_API_KEY: Optional[str] = Field(default=None, description="CoinGecko API Key (optional)") + RSS3_DATA_API: str = Field(default="https://gi.rss3.io", description="RSS3 Data API URL (optional)") + RSS3_SEARCH_API: str = Field(default="https://devnet.rss3.io/search", description="RSS3 Search API URL (optional)") + + # Chainlit OAuth settings; either all fields are None or all are set + CHAINLIT_AUTH_SECRET: Optional[str] = Field(default=None, description="Chainlit Auth Secret") + OAUTH_AUTH0_CLIENT_ID: Optional[str] = Field(default=None, description="OAuth Auth0 Client ID") + OAUTH_AUTH0_CLIENT_SECRET: Optional[str] = Field(default=None, description="OAuth Auth0 Client Secret") + OAUTH_AUTH0_DOMAIN: Optional[str] = Field(default=None, description="OAuth Auth0 Domain") settings = Settings() diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index 5c991fba..ef12fbd4 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -28,4 +28,12 @@ def set_current_llm(provider_name: str): def get_current_llm() -> BaseChatModel | None: - return _current_llm_provider.get() + llm = _current_llm_provider.get() + if llm is None: + available_providers = get_available_providers() + if len(available_providers) > 0: + llm = list(available_providers.values())[0] + else: + logger.error("No LLM provider is available.") + raise ValueError("No LLM provider is available.") + return llm diff --git a/src/openagent/experts/swap_expert.py b/src/openagent/experts/swap_expert.py index 13512051..869e1398 100644 --- a/src/openagent/experts/swap_expert.py +++ b/src/openagent/experts/swap_expert.py @@ -8,9 +8,20 @@ from langchain.tools import BaseTool from pydantic import BaseModel, Field -from openagent.dto.mutation import Swap from openagent.experts.token_util import chain_name_to_id, get_token_data_by_key, select_best_token + +class Swap(BaseModel): + from_token: str + from_token_address: str + to_token: str + to_token_address: str + amount: str + type: str = "swap" + from_chain_name: str + to_chain_name: str + + ChainLiteral = Literal["ETH", "BSC", "ARBITRUM", "OPTIMISM", "POLYGON"] @@ -19,14 +30,17 @@ class ParamSchema(BaseModel): Schema for the parameters required for a token swap. """ - from_token: str = Field(description="Symbol of the token to swap from, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") - to_token: str = Field(description="Symbol of the token to swap to, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") + from_token: str = Field( + description="Symbol of the token to swap from, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") + to_token: str = Field( + description="Symbol of the token to swap to, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") from_chain: ChainLiteral = Field( default="ETH", description="Blockchain network to swap from, support networks: 'ETH', 'BSC', 'ARBITRUM', 'OPTIMISM', 'POLYGON'. Default: 'ETH'.", ) to_chain: ChainLiteral = Field( - default="ETH", description="Blockchain network to swap to, support networks: 'ETH', 'BSC', 'ARBITRUM', 'OPTIMISM', 'POLYGON'. Default: 'ETH'." + default="ETH", + description="Blockchain network to swap to, support networks: 'ETH', 'BSC', 'ARBITRUM', 'OPTIMISM', 'POLYGON'. Default: 'ETH'." ) amount: str = Field(description="Amount of the from-side token to swap, e.g., '0.1', '1', '10'. Default: '1'.") @@ -42,24 +56,24 @@ class SwapExpert(BaseTool): return_direct = False def _run( - self, - from_token: str, - to_token: str, - from_chain: ChainLiteral, - to_chain: ChainLiteral, - amount: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + from_token: str, + to_token: str, + from_chain: ChainLiteral, + to_chain: ChainLiteral, + amount: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: raise NotImplementedError async def _arun( - self, - from_token: str, - to_token: str, - from_chain: ChainLiteral = "ETH", - to_chain: ChainLiteral = "ETH", - amount: str = "1", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + from_token: str, + to_token: str, + from_chain: ChainLiteral = "ETH", + to_chain: ChainLiteral = "ETH", + amount: str = "1", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): return await fetch_swap(from_token, to_token, from_chain, to_chain, amount) @@ -82,7 +96,8 @@ async def fetch_swap(from_token: str, to_token: str, from_chain: ChainLiteral, t to_chain_id = chain_name_to_id(to_chain) # Fetch token data concurrently - from_token_data, to_token_data = await asyncio.gather(select_best_token(from_token, from_chain_id), select_best_token(to_token, to_chain_id)) + from_token_data, to_token_data = await asyncio.gather(select_best_token(from_token, from_chain_id), + select_best_token(to_token, to_chain_id)) swap = Swap( from_token=get_token_data_by_key(from_token_data, "symbol"), diff --git a/src/openagent/experts/transfer_expert.py b/src/openagent/experts/transfer_expert.py index e20aa81f..d66a748a 100644 --- a/src/openagent/experts/transfer_expert.py +++ b/src/openagent/experts/transfer_expert.py @@ -7,10 +7,20 @@ from langchain.tools import BaseTool from pydantic import BaseModel, Field -from openagent.dto.mutation import Transfer from openagent.experts.token_util import chain_name_to_id, get_token_data_by_key, select_best_token +class Transfer(BaseModel): + # task_id: str + to_address: str + token: str + token_address: str + chain_id: str + amount: str + logoURI: str # noqa + decimals: int + + class ParamSchema(BaseModel): to_address: str = Field( description="""extract the blockchain address mentioned in the query""", @@ -41,22 +51,22 @@ class TransferExpert(BaseTool): last_task_id: Optional[str] = None def _run( - self, - to_address: str, - token: str, - chain_name: str, - amount: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + to_address: str, + token: str, + chain_name: str, + amount: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: raise NotImplementedError async def _arun( - self, - to_address: str, - token: str, - chain_name: str = "ethereum", - amount: str = "1", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + to_address: str, + token: str, + chain_name: str = "ethereum", + amount: str = "1", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): return await fetch_transfer(to_address, token, chain_name, amount) From 93b9baf03cb62d0e25eea2030e5b369a598cef06 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 30 Jul 2024 16:00:38 +0800 Subject: [PATCH 18/85] feat: ollama config integration --- src/openagent/agents/fallback.py | 2 ++ src/openagent/conf/env.py | 2 +- src/openagent/conf/llm_provider.py | 18 +++++++++++++++ src/openagent/ui/profile.py | 5 ++++ src/poetry.lock | 37 ++++++++++++++++++++++++++---- src/pyproject.toml | 2 ++ 6 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/openagent/agents/fallback.py b/src/openagent/agents/fallback.py index 145227d4..b724ce1f 100644 --- a/src/openagent/agents/fallback.py +++ b/src/openagent/agents/fallback.py @@ -1,3 +1,4 @@ +import ollama from langchain_core.messages import HumanMessage from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate @@ -33,3 +34,4 @@ def fallback(state): ) ] } + diff --git a/src/openagent/conf/env.py b/src/openagent/conf/env.py index 7f1e6e64..a03abbe7 100644 --- a/src/openagent/conf/env.py +++ b/src/openagent/conf/env.py @@ -15,7 +15,7 @@ class Settings(BaseSettings): VERTEX_PROJECT_ID: Optional[str] = Field(default=None, description="Google Cloud Vertex project ID (optional)") OPENAI_API_KEY: Optional[str] = Field(default=None, description="OpenAI API Key (optional)") GOOGLE_GEMINI_API_KEY: Optional[str] = Field(default=None, description="Google Gemini API Key (optional)") - OLLAMA_API_BASE: Optional[str] = Field(default=None, description="OLLAMA API Base URL (optional)") + OLLAMA_HOST: Optional[str] = Field(default=None, description="OLLAMA API Base URL (optional)") # API keys for various tools; some features will be disabled if not set NFTSCAN_API_KEY: Optional[str] = Field(default=None, description="NFTScan API Key (optional)") diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index ef12fbd4..b2fe0aff 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -1,13 +1,25 @@ from contextvars import ContextVar +import ollama from langchain_core.language_models import BaseChatModel from langchain_google_vertexai import ChatVertexAI +from langchain_ollama import ChatOllama from langchain_openai import ChatOpenAI from loguru import logger from openagent.conf.env import settings +def get_available_ollama_providers(): + ollama_list = ollama.list() + models_ = list(map(lambda x: x['name'], + ollama_list['models'])) + all_ = ['llama3.1:latest'] + + available_models = list(filter(lambda x: x in all_, models_)) + return available_models + + def get_available_providers(): providers = {} if settings.OPENAI_API_KEY: @@ -15,6 +27,12 @@ def get_available_providers(): providers["gpt-4o"] = ChatOpenAI(model="gpt-4o") if settings.VERTEX_PROJECT_ID: providers["gemini-1.5-pro"] = ChatVertexAI(model="gemini-1.5-pro") + + if settings.OLLAMA_HOST: + ollama_providers = get_available_ollama_providers() + print(ollama_providers) + for model in ollama_providers: + providers[model] = ChatOllama(model=model) return providers diff --git a/src/openagent/ui/profile.py b/src/openagent/ui/profile.py index 805ce338..1b177b55 100644 --- a/src/openagent/ui/profile.py +++ b/src/openagent/ui/profile.py @@ -16,6 +16,11 @@ "markdown_description": "The underlying LLM model is **Gemini 1.5 Pro**.", "icon": "https://custom.typingmind.com/assets/models/gemini.png", }, + "llama3.1:latest": { + "name": "LLAMA 3.1", + "markdown_description": "The underlying LLM model is **LLAMA 3.1**.", + "icon": "https://custom.typingmind.com/assets/models/llama.png", + }, } diff --git a/src/poetry.lock b/src/poetry.lock index e9309f2d..bf0bd9d5 100644 --- a/src/poetry.lock +++ b/src/poetry.lock @@ -1633,13 +1633,13 @@ tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<9.0.0" [[package]] name = "langchain-core" -version = "0.2.10" +version = "0.2.24" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.2.10-py3-none-any.whl", hash = "sha256:6eb72086b6bc86db9812da98f79e507c2209a15c0112aefd214a04182ada8586"}, - {file = "langchain_core-0.2.10.tar.gz", hash = "sha256:33d1fc234ab58c80476eb5bbde2107ef522a2ce8f46bdf47d9e1bd21e054208f"}, + {file = "langchain_core-0.2.24-py3-none-any.whl", hash = "sha256:9444fc082d21ef075d925590a684a73fe1f9688a3d90087580ec929751be55e7"}, + {file = "langchain_core-0.2.24.tar.gz", hash = "sha256:f2e3fa200b124e8c45d270da9bf836bed9c09532612c96ff3225e59b9a232f5a"}, ] [package.dependencies] @@ -1690,6 +1690,21 @@ langchain-core = ">=0.2.9,<0.3" [package.extras] anthropic = ["anthropic[vertexai] (>=0.29.0,<1)"] +[[package]] +name = "langchain-ollama" +version = "0.1.0" +description = "An integration package connecting Ollama and LangChain" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_ollama-0.1.0-py3-none-any.whl", hash = "sha256:d549b3ccf565a9ee9f6cfe8cfb8a94976b7fd0f427cd842ba134db7e2bf5b8cf"}, + {file = "langchain_ollama-0.1.0.tar.gz", hash = "sha256:002b9720aed04aca17cbe1448b534126d85ae561a9acb382d000a208c9bf7b89"}, +] + +[package.dependencies] +langchain-core = ">=0.2.20,<0.3.0" +ollama = ">=0.3.0,<1" + [[package]] name = "langchain-openai" version = "0.1.13" @@ -2091,6 +2106,20 @@ files = [ {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, ] +[[package]] +name = "ollama" +version = "0.3.1" +description = "The official Python client for Ollama." +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "ollama-0.3.1-py3-none-any.whl", hash = "sha256:db50034c73d6350349bdfba19c3f0d54a3cea73eb97b35f9d7419b2fc7206454"}, + {file = "ollama-0.3.1.tar.gz", hash = "sha256:032572fb494a4fba200c65013fe937a65382c846b5f358d9e8918ecbc9ac44b5"}, +] + +[package.dependencies] +httpx = ">=0.27.0,<0.28.0" + [[package]] name = "openai" version = "1.35.7" @@ -4088,4 +4117,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "2ecb5840540e3502588f0b395fd644dcea49f592126a79761fcb452d430027cb" +content-hash = "e004279095805d9212e71ea4476366a91400e04701db870ecdabb09cfe58853a" diff --git a/src/pyproject.toml b/src/pyproject.toml index 3d4fd986..8137bbd7 100644 --- a/src/pyproject.toml +++ b/src/pyproject.toml @@ -39,6 +39,8 @@ langchain-openai = "^0.1.13" chainlit = "^1.1.305" greenlet = "^3.0.3" covalent-api-sdk = "^1.0.2" +langchain-ollama = "^0.1.0" +ollama = "^0.3.1" [tool.poetry.group.dev.dependencies] ruff = "^0.4.1" From 341edbeeaa0a39dfa72c8e0a948d24125f585924 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 30 Jul 2024 16:16:48 +0800 Subject: [PATCH 19/85] chore: tool name refactor --- src/openagent/agents/social_track.py | 2 +- src/openagent/conf/llm_provider.py | 19 ++++-- src/openagent/tools/block_stat_tool.py | 2 +- src/openagent/tools/coin_market_tool.py | 2 +- src/openagent/tools/feed_tool.py | 50 -------------- src/openagent/tools/funding_rate_tool.py | 2 +- src/openagent/tools/nft_balance_tool.py | 2 +- src/openagent/tools/nft_tool.py | 2 +- src/openagent/tools/price_tool.py | 2 +- src/openagent/tools/project_tool.py | 2 +- src/openagent/tools/search_tool.py | 83 ----------------------- src/openagent/tools/tavily_tool.py | 2 +- src/openagent/tools/token_balance_tool.py | 2 +- src/openagent/ui/profile.py | 4 +- 14 files changed, 24 insertions(+), 152 deletions(-) delete mode 100644 src/openagent/tools/feed_tool.py delete mode 100644 src/openagent/tools/search_tool.py diff --git a/src/openagent/agents/social_track.py b/src/openagent/agents/social_track.py index 15b5b925..e1c0323f 100644 --- a/src/openagent/agents/social_track.py +++ b/src/openagent/agents/social_track.py @@ -10,7 +10,7 @@ social_track_agent = create_agent( llm, - [FeedTool(), tavily_tool], + [tavily_tool], """ You are Social Tracker, focused on tracking web3 social media and community interactions. diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index b2fe0aff..1d433298 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -1,3 +1,4 @@ +import traceback from contextvars import ContextVar import ollama @@ -11,13 +12,17 @@ def get_available_ollama_providers(): - ollama_list = ollama.list() - models_ = list(map(lambda x: x['name'], - ollama_list['models'])) - all_ = ['llama3.1:latest'] - - available_models = list(filter(lambda x: x in all_, models_)) - return available_models + try: + ollama_list = ollama.list() + models_ = list(map(lambda x: x['name'], + ollama_list['models'])) + all_ = ['llama3.1:latest'] + + available_models = list(filter(lambda x: x in all_, models_)) + return available_models + except Exception as e: + logger.error(f"Failed to get available ollama providers: {e}") + return [] def get_available_providers(): diff --git a/src/openagent/tools/block_stat_tool.py b/src/openagent/tools/block_stat_tool.py index 28e5e260..4a585f81 100644 --- a/src/openagent/tools/block_stat_tool.py +++ b/src/openagent/tools/block_stat_tool.py @@ -20,7 +20,7 @@ class ARGS(BaseModel): class BlockStatTool(BaseTool): - name = "block_chain_stat" + name = "BlockChainStatExecutor" description = ( "get blockchain statistics such as block height, " "transaction count, gas fees, and more. " diff --git a/src/openagent/tools/coin_market_tool.py b/src/openagent/tools/coin_market_tool.py index 9ebdce34..0f8a5428 100644 --- a/src/openagent/tools/coin_market_tool.py +++ b/src/openagent/tools/coin_market_tool.py @@ -20,7 +20,7 @@ class ARGS(BaseModel): class CoinMarketTool(BaseTool): - name = "coins-with-market" + name = "CoinsMarketExecutor" description = "query coins sorted by market cap, volume." args_schema: Type[ARGS] = ARGS diff --git a/src/openagent/tools/feed_tool.py b/src/openagent/tools/feed_tool.py deleted file mode 100644 index f5fa0279..00000000 --- a/src/openagent/tools/feed_tool.py +++ /dev/null @@ -1,50 +0,0 @@ -from typing import Optional, Type - -import aiohttp -from langchain.callbacks.manager import ( - AsyncCallbackManagerForToolRun, - CallbackManagerForToolRun, -) -from langchain.tools import BaseTool -from loguru import logger -from pydantic import BaseModel, Field - -from openagent.conf.env import settings - - -class ParamSchema(BaseModel): - address: str = Field( - description="""wallet address or blockchain domain name,\ -hint: vitalik's address is vitalik.eth""" - ) - - -class FeedTool(BaseTool): - name = "feed" - description = """Use this tool to get the activities of a wallet address or \ -blockchain domain name and know what this address has done or doing recently.""" - args_schema: Type[ParamSchema] = ParamSchema - - def _run( - self, - address: str, - run_manager: Optional[CallbackManagerForToolRun] = None, - ) -> str: - raise NotImplementedError - - async def _arun( - self, - address: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, - ): - return await fetch_feeds(address) - - -async def fetch_feeds(address: str): - host = settings.RSS3_DATA_API + "/accounts" - url = f"""{host}/{address}/activities?limit=10&action_limit=5&direction=out""" - headers = {"Accept": "application/json"} - async with aiohttp.ClientSession() as session: - logger.info(f"fetching {url}") - async with session.get(url, headers=headers) as resp: - return await resp.text() diff --git a/src/openagent/tools/funding_rate_tool.py b/src/openagent/tools/funding_rate_tool.py index 468f7c0b..754f5628 100644 --- a/src/openagent/tools/funding_rate_tool.py +++ b/src/openagent/tools/funding_rate_tool.py @@ -17,7 +17,7 @@ class ARGS(BaseModel): class FundingRateTool(BaseTool): - name = "funding_rate" + name = "FundingRateExecutor" description = "Use this tool to get the funding rate of a trading pair." args_schema: Type[ARGS] = ARGS diff --git a/src/openagent/tools/nft_balance_tool.py b/src/openagent/tools/nft_balance_tool.py index 815491b1..2963b6e2 100644 --- a/src/openagent/tools/nft_balance_tool.py +++ b/src/openagent/tools/nft_balance_tool.py @@ -18,7 +18,7 @@ class ARGS(BaseModel): class NFTBalanceTool(BaseTool): - name = "nft-balance" + name = "NFTBalanceExecutor" description = "get the nft asset of a wallet." args_schema: Type[ARGS] = ARGS diff --git a/src/openagent/tools/nft_tool.py b/src/openagent/tools/nft_tool.py index e42c830b..196835bf 100644 --- a/src/openagent/tools/nft_tool.py +++ b/src/openagent/tools/nft_tool.py @@ -32,7 +32,7 @@ class ARGS(BaseModel): class NFTTool(BaseTool): - name = "NFT" + name = "NFTExecutor" description = "A tool for searching NFT collections or getting collection rankings." args_schema: Type[ARGS] = ARGS diff --git a/src/openagent/tools/price_tool.py b/src/openagent/tools/price_tool.py index f86e6c1f..f3f881e6 100644 --- a/src/openagent/tools/price_tool.py +++ b/src/openagent/tools/price_tool.py @@ -18,7 +18,7 @@ class ARGS(BaseModel): class PriceTool(BaseTool): - name = "price" + name = "PriceExecutor" description = "use this tool to get the price widget of a token." args_schema: Type[ARGS] = ARGS diff --git a/src/openagent/tools/project_tool.py b/src/openagent/tools/project_tool.py index 38b90520..13db868b 100644 --- a/src/openagent/tools/project_tool.py +++ b/src/openagent/tools/project_tool.py @@ -34,7 +34,7 @@ def _fetch_project_sync(keyword: str) -> str: class ProjectTool(BaseTool): - name = "project" + name = "ProjectExecutor" description = "get the project information like investors, team members, social media, etc." args_schema: Type[ARGS] = ARGS diff --git a/src/openagent/tools/search_tool.py b/src/openagent/tools/search_tool.py deleted file mode 100644 index 502ec900..00000000 --- a/src/openagent/tools/search_tool.py +++ /dev/null @@ -1,83 +0,0 @@ -from typing import Optional, Type - -import requests -from langchain.callbacks.manager import ( - AsyncCallbackManagerForToolRun, - CallbackManagerForToolRun, -) -from langchain.tools import BaseTool -from langchain_community.utilities import SerpAPIWrapper -from pydantic import BaseModel, Field - -from openagent.conf.env import settings - - -class SearchSchema(BaseModel): - query: str = Field(description="The search query keywords.") - search_type: str = Field( - description="""The type of search to perform. Options are: - - "google": Google search for current events and real-time information - - "dune": Search for Dune dashboards""" - ) - gl: Optional[str] = Field( - default="us", - description="Country code for Google search, e.g., 'us', 'cn', 'jp'", - ) - hl: Optional[str] = Field( - default="en", - description="Language code for Google search, e.g., 'en', 'zh-cn', 'ja'", - ) - - -def dune_search(query: str) -> str: - url = f"{settings.RSS3_SEARCH_API}/dune/search?keyword={query}" - headers = {"Accept": "*/*", "Content-Type": "application/x-www-form-urlencoded"} - response = requests.request("GET", url, headers=headers) - return response.text - - -def google_search(query: str, gl: str, hl: str) -> str: - search_wrapper = SerpAPIWrapper( - search_engine="google", - params={"engine": "google", "gl": gl, "hl": hl}, - ) - return search_wrapper.run(query) - - -class SearchTool(BaseTool): - name = "search" - description = """ - A versatile search tool that can perform various types of searches based on the query type: - - For queries related to charts, data visualization, or dashboards, use Dune search. - - For queries about project introductions, current events or real-time information, use Google search.""" - args_schema: Type[SearchSchema] = SearchSchema - - def _run( - self, - query: str, - search_type: str, - gl: Optional[str] = "us", - hl: Optional[str] = "en", - run_manager: Optional[CallbackManagerForToolRun] = None, - ) -> str: - if search_type == "google": - return google_search(query, gl, hl) - elif search_type == "dune": - return dune_search(query) - else: - raise ValueError(f"Unknown search type: {search_type}") - - async def _arun( - self, - query: str, - search_type: str, - gl: Optional[str] = "us", - hl: Optional[str] = "en", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, - ) -> str: - if search_type == "google": - return google_search(query, gl, hl) - elif search_type == "dune": - return dune_search(query) - else: - raise ValueError(f"Unknown search type: {search_type}") diff --git a/src/openagent/tools/tavily_tool.py b/src/openagent/tools/tavily_tool.py index 6f1785c9..0296cec0 100644 --- a/src/openagent/tools/tavily_tool.py +++ b/src/openagent/tools/tavily_tool.py @@ -1,3 +1,3 @@ from langchain_community.tools.tavily_search import TavilySearchResults -tavily_tool = TavilySearchResults(max_results=5) +tavily_tool = TavilySearchResults(max_results=5, name="SearchExecutor") diff --git a/src/openagent/tools/token_balance_tool.py b/src/openagent/tools/token_balance_tool.py index b26d7657..23b6698d 100644 --- a/src/openagent/tools/token_balance_tool.py +++ b/src/openagent/tools/token_balance_tool.py @@ -18,7 +18,7 @@ class ARGS(BaseModel): class TokenBalanceTool(BaseTool): - name = "token-balance" + name = "TokenBalanceExecutor" description = "get the token balance of a wallet." args_schema: Type[ARGS] = ARGS diff --git a/src/openagent/ui/profile.py b/src/openagent/ui/profile.py index 1b177b55..8aa9eab1 100644 --- a/src/openagent/ui/profile.py +++ b/src/openagent/ui/profile.py @@ -7,8 +7,8 @@ "icon": "https://custom.typingmind.com/assets/models/gpt-35.webp", }, "gpt-4o": { - "name": "GPT-4", - "markdown_description": "The underlying LLM model is **GPT-4**.", + "name": "GPT-4o", + "markdown_description": "The underlying LLM model is **GPT-4o**.", "icon": "https://custom.typingmind.com/assets/models/gpt-4.webp", }, "gemini-1.5-pro": { From 413f9991ee8423e92599528d10a9ff5d926ffae6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 30 Jul 2024 16:24:09 +0800 Subject: [PATCH 20/85] chore: remove useless code --- src/openagent/agents/social_track.py | 23 ----------------------- src/openagent/workflows/workflow.py | 3 --- 2 files changed, 26 deletions(-) delete mode 100644 src/openagent/agents/social_track.py diff --git a/src/openagent/agents/social_track.py b/src/openagent/agents/social_track.py deleted file mode 100644 index e1c0323f..00000000 --- a/src/openagent/agents/social_track.py +++ /dev/null @@ -1,23 +0,0 @@ -from dotenv import load_dotenv - -from openagent.agents.agent_factory import create_agent -from openagent.conf.llm_provider import get_current_llm -from openagent.tools.feed_tool import FeedTool -from openagent.tools.tavily_tool import tavily_tool - -load_dotenv() -llm = get_current_llm() - -social_track_agent = create_agent( - llm, - [tavily_tool], - """ - -You are Social Tracker, focused on tracking web3 social media and community interactions. - Provide users with the latest updates and discussions from the web3 ecosystem. - Use the available tools to collect and display social content. -Your answer should be detailed and include puns or jokes where possible \ -And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. - -""".strip(), -) diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py index 45e7b6ca..282a43ab 100644 --- a/src/openagent/workflows/workflow.py +++ b/src/openagent/workflows/workflow.py @@ -26,19 +26,16 @@ def build_workflow(): from openagent.agents.fallback import fallback from openagent.agents.market_analysis import market_analysis_agent from openagent.agents.project_management import research_analyst_agent - from openagent.agents.social_track import social_track_agent from openagent.workflows.member import members from openagent.workflows.supervisor_chain import supervisor_chain market_analysis_agent_node = create_node(market_analysis_agent, "market_analysis_agent") - social_track_agent_node = create_node(social_track_agent, "social_track_agent") asset_management_agent_node = create_node(asset_management_agent, "asset_management_agent") block_explorer_agent_node = create_node(block_explorer_agent, "block_explorer_agent") research_analyst_agent_node = create_node(research_analyst_agent, "research_analyst_agent") workflow = StateGraph(AgentState) workflow.add_node("market_analysis_agent", market_analysis_agent_node) - workflow.add_node("social_track_agent", social_track_agent_node) workflow.add_node("asset_management_agent", asset_management_agent_node) workflow.add_node("block_explorer_agent", block_explorer_agent_node) workflow.add_node("research_analyst_agent", research_analyst_agent_node) From 36396d3c3ed1bcc5a1d7e53e1b38d34c799f6ca0 Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 30 Jul 2024 16:42:55 +0800 Subject: [PATCH 21/85] chore: remove useless agent --- src/openagent/workflows/member.py | 13 ------------- src/openagent/workflows/workflow.py | 4 ++-- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/openagent/workflows/member.py b/src/openagent/workflows/member.py index 05e19749..799d594e 100644 --- a/src/openagent/workflows/member.py +++ b/src/openagent/workflows/member.py @@ -12,19 +12,6 @@ Maintain a professional and informative tone while providing clear, concise analysis. """.strip(), }, - { - "name": "social_track_agent", - "description": """ -SocialTracker: Monitors web3 social media and community interactions. - -Responsibilities: -1. Track latest updates from web3 social platforms -2. Summarize key discussions and trends -3. Provide relevant social insights to users - -Deliver information in a clear, engaging manner, highlighting important community sentiments. - """.strip(), - }, { "name": "asset_management_agent", "description": """ diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py index 282a43ab..464ad06a 100644 --- a/src/openagent/workflows/workflow.py +++ b/src/openagent/workflows/workflow.py @@ -12,9 +12,9 @@ class AgentState(TypedDict): def create_node(agent, name): - def run(state): + async def run(state): logger.info(f"Running {name} agent") - result = agent.invoke(state) + result = await agent.ainvoke(state) return {"messages": [HumanMessage(content=result["output"], name=name)]} return run From aae4f8473a03ed2eced201cfe48b125eb19cc76b Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 30 Jul 2024 16:43:23 +0800 Subject: [PATCH 22/85] chore: Update system prompt for AI Agent Supervisor in supervisor_chain.py --- src/openagent/workflows/supervisor_chain.py | 33 ++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index 66a4d851..30878190 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -7,13 +7,32 @@ load_dotenv() -system_prompt = ( - "You are a supervisor tasked with managing a conversation between the" - " following workers: {members}. Given the following user request," - " respond with the worker to act next. Each worker will perform a" - " task and respond with their results and status. When finished," - " respond with FINISH." -).format(members=", ".join([f"{member['name']} ({member['description']})" for member in members])) +system_prompt = """ +You are an AI Agent Supervisor responsible for managing and coordinating the work of multiple specialized AI Agents. Your task is to efficiently allocate and oversee tasks among the following AI Agents based on user requests: + +{members} + +Your responsibilities: +1. Carefully analyze the user's request and the current conversation history. +2. Select the most suitable AI Agent to act next, based on task requirements and each Agent's expertise. +3. Monitor each AI Agent's output, evaluate task progress, and determine if other Agents need to intervene or if the task is complete. + +Selection principles: +- Choose the AI Agent whose expertise best matches the current needs. +- Consider task continuity, avoiding unnecessary Agent switches. +- Prioritize Agents who can advance the task, avoiding repetition of completed work. +- If multiple Agents are suitable, select the one that can provide the most comprehensive or specialized response. + +Completion criteria: +- Select FINISH when all user requests have been satisfactorily addressed. +- Choose FINISH if an AI Agent explicitly states that the task is fully completed. +- Opt for FINISH if you determine no more Agents can provide valuable input for the current task. + +Based on these guidelines, the user request, and the conversation history, select the next AI Agent to perform the task or end the conversation. Your decisions should be efficient, ensuring the user receives the best possible service experience. +""" + +members_info = ", ".join([f"{member['name']} ({member['description']})" for member in members]) +system_prompt = system_prompt.format(members=members_info) options = ["FINISH"] + [member["name"] for member in members] function_def = { From 2f36d618415543591bf1e9e87ee07820d22d2caa Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 30 Jul 2024 16:43:37 +0800 Subject: [PATCH 23/85] fix: tool end handler --- src/openagent/ui/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 64bab549..c4ee7b10 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -117,7 +117,7 @@ async def on_message(message: cl.Message): async def handle_tool_end(event, msg): - if event["name"] == "swap": + if event["name"] == "SwapExecutor": output = event["data"]["output"] swap_dict = json.loads(output) logger.info(swap_dict) @@ -137,7 +137,7 @@ async def handle_tool_end(event, msg): ) await msg.stream_token(widget) - if event["name"] == "price": + if event["name"] == "PriceExecutor": output = event["data"]["output"] price_dict = json.loads(output) widget = ( From 9cf4472280d5ccb3e6a2124a690ea7349597d8ca Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 30 Jul 2024 16:56:20 +0800 Subject: [PATCH 24/85] fix: pre-commit lint --- src/openagent/agents/fallback.py | 2 -- src/openagent/app.py | 2 +- src/openagent/conf/llm_provider.py | 8 ++--- src/openagent/experts/swap_expert.py | 40 ++++++++++----------- src/openagent/experts/transfer_expert.py | 24 ++++++------- src/openagent/index/pgvector_store.py | 10 +++--- src/openagent/tools/price_tool.py | 38 +++++++++----------- src/openagent/ui/app.py | 18 +++++----- src/openagent/workflows/supervisor_chain.py | 7 ++-- 9 files changed, 69 insertions(+), 80 deletions(-) diff --git a/src/openagent/agents/fallback.py b/src/openagent/agents/fallback.py index b724ce1f..145227d4 100644 --- a/src/openagent/agents/fallback.py +++ b/src/openagent/agents/fallback.py @@ -1,4 +1,3 @@ -import ollama from langchain_core.messages import HumanMessage from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate @@ -34,4 +33,3 @@ def fallback(state): ) ] } - diff --git a/src/openagent/app.py b/src/openagent/app.py index 9b2c9d11..6e7f004a 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -9,7 +9,7 @@ from pydantic import BaseModel from sse_starlette import EventSourceResponse from starlette import status -from starlette.responses import JSONResponse, FileResponse +from starlette.responses import FileResponse, JSONResponse from starlette.staticfiles import StaticFiles from openagent.workflows.workflow import build_workflow diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index 1d433298..f452935c 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -1,4 +1,3 @@ -import traceback from contextvars import ContextVar import ollama @@ -14,9 +13,8 @@ def get_available_ollama_providers(): try: ollama_list = ollama.list() - models_ = list(map(lambda x: x['name'], - ollama_list['models'])) - all_ = ['llama3.1:latest'] + models_ = list(map(lambda x: x["name"], ollama_list["models"])) + all_ = ["llama3.1:latest"] available_models = list(filter(lambda x: x in all_, models_)) return available_models @@ -55,7 +53,7 @@ def get_current_llm() -> BaseChatModel | None: if llm is None: available_providers = get_available_providers() if len(available_providers) > 0: - llm = list(available_providers.values())[0] + llm = list(available_providers.values())[0] # noqa else: logger.error("No LLM provider is available.") raise ValueError("No LLM provider is available.") diff --git a/src/openagent/experts/swap_expert.py b/src/openagent/experts/swap_expert.py index 869e1398..6d1b1789 100644 --- a/src/openagent/experts/swap_expert.py +++ b/src/openagent/experts/swap_expert.py @@ -30,17 +30,14 @@ class ParamSchema(BaseModel): Schema for the parameters required for a token swap. """ - from_token: str = Field( - description="Symbol of the token to swap from, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") - to_token: str = Field( - description="Symbol of the token to swap to, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") + from_token: str = Field(description="Symbol of the token to swap from, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") + to_token: str = Field(description="Symbol of the token to swap to, e.g., 'BTC', 'ETH', 'RSS3', 'USDT', 'USDC'. Default: 'ETH'.") from_chain: ChainLiteral = Field( default="ETH", description="Blockchain network to swap from, support networks: 'ETH', 'BSC', 'ARBITRUM', 'OPTIMISM', 'POLYGON'. Default: 'ETH'.", ) to_chain: ChainLiteral = Field( - default="ETH", - description="Blockchain network to swap to, support networks: 'ETH', 'BSC', 'ARBITRUM', 'OPTIMISM', 'POLYGON'. Default: 'ETH'." + default="ETH", description="Blockchain network to swap to, support networks: 'ETH', 'BSC', 'ARBITRUM', 'OPTIMISM', 'POLYGON'. Default: 'ETH'." ) amount: str = Field(description="Amount of the from-side token to swap, e.g., '0.1', '1', '10'. Default: '1'.") @@ -56,24 +53,24 @@ class SwapExpert(BaseTool): return_direct = False def _run( - self, - from_token: str, - to_token: str, - from_chain: ChainLiteral, - to_chain: ChainLiteral, - amount: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + from_token: str, + to_token: str, + from_chain: ChainLiteral, + to_chain: ChainLiteral, + amount: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: raise NotImplementedError async def _arun( - self, - from_token: str, - to_token: str, - from_chain: ChainLiteral = "ETH", - to_chain: ChainLiteral = "ETH", - amount: str = "1", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + from_token: str, + to_token: str, + from_chain: ChainLiteral = "ETH", + to_chain: ChainLiteral = "ETH", + amount: str = "1", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): return await fetch_swap(from_token, to_token, from_chain, to_chain, amount) @@ -96,8 +93,7 @@ async def fetch_swap(from_token: str, to_token: str, from_chain: ChainLiteral, t to_chain_id = chain_name_to_id(to_chain) # Fetch token data concurrently - from_token_data, to_token_data = await asyncio.gather(select_best_token(from_token, from_chain_id), - select_best_token(to_token, to_chain_id)) + from_token_data, to_token_data = await asyncio.gather(select_best_token(from_token, from_chain_id), select_best_token(to_token, to_chain_id)) swap = Swap( from_token=get_token_data_by_key(from_token_data, "symbol"), diff --git a/src/openagent/experts/transfer_expert.py b/src/openagent/experts/transfer_expert.py index d66a748a..40081e8f 100644 --- a/src/openagent/experts/transfer_expert.py +++ b/src/openagent/experts/transfer_expert.py @@ -51,22 +51,22 @@ class TransferExpert(BaseTool): last_task_id: Optional[str] = None def _run( - self, - to_address: str, - token: str, - chain_name: str, - amount: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + to_address: str, + token: str, + chain_name: str, + amount: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: raise NotImplementedError async def _arun( - self, - to_address: str, - token: str, - chain_name: str = "ethereum", - amount: str = "1", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + to_address: str, + token: str, + chain_name: str = "ethereum", + amount: str = "1", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): return await fetch_transfer(to_address, token, chain_name, amount) diff --git a/src/openagent/index/pgvector_store.py b/src/openagent/index/pgvector_store.py index 878336ec..2cded906 100644 --- a/src/openagent/index/pgvector_store.py +++ b/src/openagent/index/pgvector_store.py @@ -13,11 +13,11 @@ @memoize def build_vector_store() -> PGVector: collection_name = "backend" - if settings.MODEL_NAME.startswith("gemini"): - if settings.GOOGLE_GEMINI_API_KEY is not None: - underlying_embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001", google_api_key=settings.GOOGLE_GEMINI_API_KEY) - else: - underlying_embeddings = VertexAIEmbeddings(model_name="textembedding-gecko@003", project=settings.GOOGLE_CLOUD_PROJECT_ID) + if settings.VERTEX_PROJECT_ID: + underlying_embeddings = VertexAIEmbeddings(model_name="textembedding-gecko@003", project=settings.VERTEX_PROJECT_ID) + + elif settings.GOOGLE_GEMINI_API_KEY: + underlying_embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001", google_api_key=settings.GOOGLE_GEMINI_API_KEY) else: underlying_embeddings = OpenAIEmbeddings(model="text-embedding-3-large") return PGVector( diff --git a/src/openagent/tools/price_tool.py b/src/openagent/tools/price_tool.py index f3f881e6..fde72101 100644 --- a/src/openagent/tools/price_tool.py +++ b/src/openagent/tools/price_tool.py @@ -23,16 +23,16 @@ class PriceTool(BaseTool): args_schema: Type[ARGS] = ARGS def _run( - self, - token: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + token: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: return asyncio.run(fetch_price(token)) async def _arun( - self, - token: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + token: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ) -> str: return await fetch_price(token) @@ -41,28 +41,24 @@ async def fetch_price(token: str) -> str: url = f"https://pro-api.coingecko.com/api/v3/search?query={token}" key = settings.COINGECKO_API_KEY - headers = { - "accept": "application/json", - "x-cg-pro-api-key": key - } + headers = {"accept": "application/json", "x-cg-pro-api-key": key} response = requests.get(url, headers=headers) - token = json.loads(response.text)['coins'][0] - token_id_ = token['id'] + token_: dict = json.loads(response.text)["coins"][0] + token_id_ = token_["id"] - url = (f"https://pro-api.coingecko.com/api/v3/simple/price?ids={token_id_}&" - f"vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&" - f"include_24hr_change=true&include_last_updated_at=true") + url = ( + f"https://pro-api.coingecko.com/api/v3/simple/price?ids={token_id_}&" + f"vs_currencies=usd&include_market_cap=true&include_24hr_vol=true&" + f"include_24hr_change=true&include_last_updated_at=true" + ) - headers = { - "accept": "application/json", - "x-cg-pro-api-key": key - } + headers = {"accept": "application/json", "x-cg-pro-api-key": key} response = requests.get(url, headers=headers) return response.text -if __name__ == '__main__': - print(asyncio.run(fetch_price('eth'))) +if __name__ == "__main__": + print(asyncio.run(fetch_price("eth"))) diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index c4ee7b10..9af3ef5d 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -32,10 +32,10 @@ def initialize_memory() -> ConversationBufferMemory: @cl.oauth_callback def oauth_callback( - provider_id: str, - token: str, - raw_user_data: Dict[str, str], - default_user: cl.User, + provider_id: str, + token: str, + raw_user_data: Dict[str, str], + default_user: cl.User, ) -> Optional[cl.User]: """OAuth callback function.""" return default_user @@ -98,9 +98,9 @@ async def on_message(message: cl.Message): # try: async for event in runnable.astream_events( - {"messages": [*memory.chat_memory.messages, HumanMessage(content=message.content)]}, - config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]), - version="v1", + {"messages": [*memory.chat_memory.messages, HumanMessage(content=message.content)]}, + config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler(stream_final_answer=True)]), + version="v1", ): kind = event["event"] if kind == "on_tool_end": @@ -140,7 +140,5 @@ async def handle_tool_end(event, msg): if event["name"] == "PriceExecutor": output = event["data"]["output"] price_dict = json.loads(output) - widget = ( - f"""""" - ) + widget = f"""""" # noqa await msg.stream_token(widget) diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index 30878190..a965e2ee 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -8,7 +8,8 @@ load_dotenv() system_prompt = """ -You are an AI Agent Supervisor responsible for managing and coordinating the work of multiple specialized AI Agents. Your task is to efficiently allocate and oversee tasks among the following AI Agents based on user requests: +You are an AI Agent Supervisor responsible for managing and coordinating the work of multiple specialized AI Agents. +Your task is to efficiently allocate and oversee tasks among the following AI Agents based on user requests: {members} @@ -28,7 +29,9 @@ - Choose FINISH if an AI Agent explicitly states that the task is fully completed. - Opt for FINISH if you determine no more Agents can provide valuable input for the current task. -Based on these guidelines, the user request, and the conversation history, select the next AI Agent to perform the task or end the conversation. Your decisions should be efficient, ensuring the user receives the best possible service experience. +Based on these guidelines, the user request, and the conversation history, select the next AI Agent + to perform the task or end the conversation. Your decisions should be efficient, + ensuring the user receives the best possible service experience. """ members_info = ", ".join([f"{member['name']} ({member['description']})" for member in members]) From 23aecbc93b486e2fd9a5f7fd7c495cfd00494971 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 31 Jul 2024 16:57:45 +0800 Subject: [PATCH 25/85] chore: Refactor supervisor_chain.py for improved readability --- src/openagent/workflows/supervisor_chain.py | 70 +++++++++++---------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index a965e2ee..bca63174 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -7,7 +7,9 @@ load_dotenv() -system_prompt = """ + +def build_supervisor_chain(): + system_prompt = """ You are an AI Agent Supervisor responsible for managing and coordinating the work of multiple specialized AI Agents. Your task is to efficiently allocate and oversee tasks among the following AI Agents based on user requests: @@ -33,39 +35,39 @@ to perform the task or end the conversation. Your decisions should be efficient, ensuring the user receives the best possible service experience. """ - -members_info = ", ".join([f"{member['name']} ({member['description']})" for member in members]) -system_prompt = system_prompt.format(members=members_info) - -options = ["FINISH"] + [member["name"] for member in members] -function_def = { - "name": "route", - "description": "Select the next role.", - "parameters": { - "title": "routeSchema", - "type": "object", - "properties": { - "next": { - "title": "Next", - "anyOf": [ - {"enum": options}, - ], - } + members_info = ", ".join([f"{member['name']} ({member['description']})" for member in members]) + system_prompt = system_prompt.format(members=members_info) + options = ["FINISH"] + [member["name"] for member in members] + function_def = { + "name": "route", + "description": "Select the next role.", + "parameters": { + "title": "routeSchema", + "type": "object", + "properties": { + "next": { + "title": "Next", + "anyOf": [ + {"enum": options}, + ], + } + }, + "required": ["next"], }, - "required": ["next"], - }, -} -prompt = ChatPromptTemplate.from_messages( - [ - ("system", system_prompt), - MessagesPlaceholder(variable_name="messages"), - ( - "system", - "Given the conversation above, who should act next?" " Or should we FINISH? Select one of: {options}", - ), - ] -).partial(options=str(options), members=", ".join([member["name"] for member in members])) + } + prompt = ChatPromptTemplate.from_messages( + [ + ("system", system_prompt), + MessagesPlaceholder(variable_name="messages"), + ( + "system", + "Given the conversation above, who should act next?" " Or should we FINISH? Select one of: {options}", + ), + ] + ).partial(options=str(options), members=", ".join([member["name"] for member in members])) + llm = get_current_llm() + return prompt | llm.bind_functions(functions=[function_def], + function_call="route") | JsonOutputFunctionsParser() -llm = get_current_llm() -supervisor_chain = prompt | llm.bind_functions(functions=[function_def], function_call="route") | JsonOutputFunctionsParser() +supervisor_chain = build_supervisor_chain() From d89fcf80b022ea693111e66a1baf7e2745dc49e5 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 31 Jul 2024 16:58:01 +0800 Subject: [PATCH 26/85] feat: Add unit tests for supervisor_chain next_role function --- src/tests/supervisor_chain.py | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/tests/supervisor_chain.py diff --git a/src/tests/supervisor_chain.py b/src/tests/supervisor_chain.py new file mode 100644 index 00000000..26b7301c --- /dev/null +++ b/src/tests/supervisor_chain.py @@ -0,0 +1,67 @@ +import unittest + +from langchain_core.messages import HumanMessage + +from openagent.workflows.supervisor_chain import build_supervisor_chain + + +def next_role(query) -> str: + supervisor_chain = build_supervisor_chain() + resp = supervisor_chain.invoke({"messages": [HumanMessage(content=query, name='humane')]}) + return resp['next'] + + +class TestNextRole(unittest.TestCase): + + def test_market_analysis(self): + query = "What's the current price of Ethereum and its market trend?" + expected_role = "market_analysis_agent" + result = next_role(query) + self.assertEqual(result, expected_role, + f"Expected {expected_role}, but got {result} for query: {query}") + + def test_asset_management(self): + query = "Can you check my ETH balance and show me how to swap some for USDC?" + expected_role = "asset_management_agent" + result = next_role(query) + self.assertEqual(result, expected_role, + f"Expected {expected_role}, but got {result} for query: {query}") + + def test_block_explorer(self): + query = "What's the latest block height on the Ethereum network, and what are the current gas fees?" + expected_role = "block_explorer_agent" + result = next_role(query) + self.assertEqual(result, expected_role, + f"Expected {expected_role}, but got {result} for query: {query}") + + def test_research_analyst(self): + query = "Can you provide a detailed analysis of the Uniswap project, including its recent developments and market position?" + expected_role = "research_analyst_agent" + result = next_role(query) + self.assertEqual(result, expected_role, + f"Expected {expected_role}, but got {result} for query: {query}") + + def test_fallback(self): + query = "What's the weather like today in New York?" + expected_role = "fallback_agent" + result = next_role(query) + self.assertEqual(result, expected_role, + f"Expected {expected_role}, but got {result} for query: {query}") + + def test_multi_step_query(self): + query = "I want to invest in a promising DeFi project. Can you first give me an overview of the current DeFi market trends, then recommend a project, and finally show me how to acquire some tokens of that project?" + expected_role = "market_analysis_agent" + result = next_role(query) + self.assertEqual(result, expected_role, + f"Expected {expected_role}, but got {result} for query: {query}") + + def test_finish(self): + query = "That's all I needed, thank you!" + expected_role = "FINISH" + result = next_role(query) + self.assertEqual(result, expected_role, + f"Expected {expected_role}, but got {result} for query: {query}") + + +if __name__ == '__main__': + unittest.main() From f8cada9ade9346289b38796e2ad9e2327dd1c215 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 31 Jul 2024 17:00:00 +0800 Subject: [PATCH 27/85] chore: Add memoization to the function `get_available_ollama_providers()` --- src/openagent/conf/llm_provider.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index f452935c..bc138007 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -8,8 +8,10 @@ from loguru import logger from openagent.conf.env import settings +from toolz import memoize +@memoize def get_available_ollama_providers(): try: ollama_list = ollama.list() From e5cf6b22b1e66622630e01c0f5d530d16264fb4c Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 31 Jul 2024 17:29:22 +0800 Subject: [PATCH 28/85] fix: pre-commit lint --- src/openagent/conf/llm_provider.py | 2 +- src/openagent/workflows/supervisor_chain.py | 3 +- src/tests/supervisor_chain.py | 36 +++++++++------------ 3 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index bc138007..815b5262 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -6,9 +6,9 @@ from langchain_ollama import ChatOllama from langchain_openai import ChatOpenAI from loguru import logger +from toolz import memoize from openagent.conf.env import settings -from toolz import memoize @memoize diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index bca63174..6b9832f1 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -66,8 +66,7 @@ def build_supervisor_chain(): ] ).partial(options=str(options), members=", ".join([member["name"] for member in members])) llm = get_current_llm() - return prompt | llm.bind_functions(functions=[function_def], - function_call="route") | JsonOutputFunctionsParser() + return prompt | llm.bind_functions(functions=[function_def], function_call="route") | JsonOutputFunctionsParser() supervisor_chain = build_supervisor_chain() diff --git a/src/tests/supervisor_chain.py b/src/tests/supervisor_chain.py index 26b7301c..b85e1513 100644 --- a/src/tests/supervisor_chain.py +++ b/src/tests/supervisor_chain.py @@ -7,61 +7,57 @@ def next_role(query) -> str: supervisor_chain = build_supervisor_chain() - resp = supervisor_chain.invoke({"messages": [HumanMessage(content=query, name='humane')]}) - return resp['next'] + resp = supervisor_chain.invoke({"messages": [HumanMessage(content=query, name="humane")]}) + return resp["next"] class TestNextRole(unittest.TestCase): - def test_market_analysis(self): query = "What's the current price of Ethereum and its market trend?" expected_role = "market_analysis_agent" result = next_role(query) - self.assertEqual(result, expected_role, - f"Expected {expected_role}, but got {result} for query: {query}") + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") def test_asset_management(self): query = "Can you check my ETH balance and show me how to swap some for USDC?" expected_role = "asset_management_agent" result = next_role(query) - self.assertEqual(result, expected_role, - f"Expected {expected_role}, but got {result} for query: {query}") + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") def test_block_explorer(self): query = "What's the latest block height on the Ethereum network, and what are the current gas fees?" expected_role = "block_explorer_agent" result = next_role(query) - self.assertEqual(result, expected_role, - f"Expected {expected_role}, but got {result} for query: {query}") + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") def test_research_analyst(self): - query = "Can you provide a detailed analysis of the Uniswap project, including its recent developments and market position?" + query = "Can you provide a detailed analysis of the Uniswap project," " including its recent developments and market position?" expected_role = "research_analyst_agent" result = next_role(query) - self.assertEqual(result, expected_role, - f"Expected {expected_role}, but got {result} for query: {query}") + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") def test_fallback(self): query = "What's the weather like today in New York?" expected_role = "fallback_agent" result = next_role(query) - self.assertEqual(result, expected_role, - f"Expected {expected_role}, but got {result} for query: {query}") + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") def test_multi_step_query(self): - query = "I want to invest in a promising DeFi project. Can you first give me an overview of the current DeFi market trends, then recommend a project, and finally show me how to acquire some tokens of that project?" + query = ( + "I want to invest in a promising DeFi project. Can you first give me an " + "overview of the current DeFi market trends, then recommend a project, " + "and finally show me how to acquire some tokens of that project?" + ) expected_role = "market_analysis_agent" result = next_role(query) - self.assertEqual(result, expected_role, - f"Expected {expected_role}, but got {result} for query: {query}") + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") def test_finish(self): query = "That's all I needed, thank you!" expected_role = "FINISH" result = next_role(query) - self.assertEqual(result, expected_role, - f"Expected {expected_role}, but got {result} for query: {query}") + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() From e23d9080e23537b821cdd4cc2e6fd3a4639b2076 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 31 Jul 2024 22:55:02 +0800 Subject: [PATCH 29/85] chore: Remove unused code and simplify search functionality --- src/openagent/experts/search_expert.py | 37 +++++--------------------- 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/src/openagent/experts/search_expert.py b/src/openagent/experts/search_expert.py index dc2f4f09..366e57c8 100644 --- a/src/openagent/experts/search_expert.py +++ b/src/openagent/experts/search_expert.py @@ -1,6 +1,5 @@ from typing import Optional, Type -import requests from langchain import SerpAPIWrapper from langchain.callbacks.manager import ( AsyncCallbackManagerForToolRun, @@ -9,23 +8,9 @@ from langchain.tools import BaseTool from pydantic import BaseModel, Field -from openagent.conf.env import settings - class SearchSchema(BaseModel): query: str = Field(description="The search query keywords.") - search_type: str = Field( - description="""The type of search to perform. Options are: - - "google": Google search for current events and real-time information - - "dune": Search for Dune dashboards""" - ) - - -async def dune_search(query: str) -> str: - url = f"{settings.RSS3_SEARCH_API}/dune/search?keyword={query}" - headers = {"Accept": "*/*", "Content-Type": "application/x-www-form-urlencoded"} - response = requests.request("GET", url, headers=headers) - return response.text async def google_search(query: str) -> str: @@ -40,27 +25,19 @@ class SearchExpert(BaseTool): name = "SearchExecutor" description = """ A versatile search tool that can perform various types of searches based on the query type: - - For queries related to charts, data visualization, or dashboards, use Dune search. - For queries about project introductions, current events or real-time information, use Google search.""" args_schema: Type[SearchSchema] = SearchSchema def _run( - self, - query: str, - search_type: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + query: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: raise NotImplementedError async def _arun( - self, - query: str, - search_type: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + query: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ) -> str: - if search_type == "google": - return await google_search(query) - elif search_type == "dune": - return await dune_search(query) - else: - raise ValueError(f"Unknown search type: {search_type}") + return await google_search(query) From 163dab93e08d0f7288e235191ed6efd1a78e7b46 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 10:38:23 +0800 Subject: [PATCH 30/85] chore: Refactor NFT tool classes for better organization --- src/openagent/tools/nft_rank_tool.py | 50 ++++++++++++++ src/openagent/tools/nft_search_tool.py | 59 ++++++++++++++++ src/openagent/tools/nft_tool.py | 94 -------------------------- 3 files changed, 109 insertions(+), 94 deletions(-) create mode 100644 src/openagent/tools/nft_rank_tool.py create mode 100644 src/openagent/tools/nft_search_tool.py delete mode 100644 src/openagent/tools/nft_tool.py diff --git a/src/openagent/tools/nft_rank_tool.py b/src/openagent/tools/nft_rank_tool.py new file mode 100644 index 00000000..1265249e --- /dev/null +++ b/src/openagent/tools/nft_rank_tool.py @@ -0,0 +1,50 @@ +from typing import Optional, Type + +import requests +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + +class NFTRankingArgs(BaseModel): + sort_field: str = Field( + default="market_cap", + description=""" +Options include: volume_1d, volume_7d, volume_30d, volume_total, volume_change_1d, +volume_change_7d, volume_change_30d, sales_1d, sales_7d, sales_30d, +sales_total, sales_change_1d, sales_change_7d, sales_change_30d, +floor_price, market_cap. + """, + ) + +class NFTRankingTool(BaseTool): + name = "NFTRankingTool" + description = "A tool for getting NFT collection rankings." + args_schema: Type[NFTRankingArgs] = NFTRankingArgs + + def _run( + self, + sort_field: str = "market_cap", + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + return self.collection_ranking(sort_field) + + async def _arun( + self, + sort_field: str = "market_cap", + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + return self._run(sort_field, run_manager) + + @staticmethod + def collection_ranking(sort_field: str) -> str: + """Search for NFT collections ranking.""" + url = f"https://restapi.nftscan.com/api/v2/statistics/ranking/collection?sort_field={sort_field}&sort_direction=desc&limit=20" + + headers = {"X-API-KEY": f"{settings.NFTSCAN_API_KEY}"} + response = requests.get(url, headers=headers) + return response.text diff --git a/src/openagent/tools/nft_search_tool.py b/src/openagent/tools/nft_search_tool.py new file mode 100644 index 00000000..5220fd69 --- /dev/null +++ b/src/openagent/tools/nft_search_tool.py @@ -0,0 +1,59 @@ +import json +from typing import Optional, Type + +import requests +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from pydantic import BaseModel, Field + +from openagent.conf.env import settings + + +class NFTSearchArgs(BaseModel): + keyword: str = Field(description="NFT symbol or collection name for search") + + +class NFTSearchTool(BaseTool): + name = "NFTSearchTool" + description = "A tool for searching NFT collections." + args_schema: Type[NFTSearchArgs] = NFTSearchArgs + + def _run( + self, + keyword: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + return self.search_nft_collections(keyword) + + async def _arun( + self, + keyword: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + return self._run(keyword, run_manager) + + @staticmethod + def search_nft_collections(keyword: str) -> str: + """Search for NFT collections.""" + url = "https://restapi.nftscan.com/api/v2/collections/filters" + payload = json.dumps( + { + "contract_address_list": [], + "name_fuzzy_search": "false", + "show_collection": "false", + "sort_direction": "desc", + "sort_field": "floor_price", + "name": "", + "symbol": keyword, + } + ) + headers = { + "Content-Type": "application/json", + "X-API-KEY": f"{settings.NFTSCAN_API_KEY}", + } + + response = requests.post(url, headers=headers, data=payload) + return response.text diff --git a/src/openagent/tools/nft_tool.py b/src/openagent/tools/nft_tool.py deleted file mode 100644 index 196835bf..00000000 --- a/src/openagent/tools/nft_tool.py +++ /dev/null @@ -1,94 +0,0 @@ -import json -from typing import Optional, Type - -import requests -from langchain.callbacks.manager import ( - AsyncCallbackManagerForToolRun, - CallbackManagerForToolRun, -) -from langchain.tools import BaseTool -from pydantic import BaseModel, Field - -from openagent.conf.env import settings - - -class ARGS(BaseModel): - action: str = Field(description="Specify the operation to perform: 'search' for NFT " "collection search, 'rank' for collection ranking") - keyword: Optional[str] = Field( - default=None, - description="NFT symbol or collection name, required only for 'action=search'", - ) - sort_field: Optional[str] = Field( - default="market_cap", - description=""" -Default is market_cap. Options include: volume_1d, volume_7d, volume_30d, -volume_total, volume_change_1d, -volume_change_7d, volume_change_30d, sales_1d, sales_7d, sales_30d, -sales_total, sales_change_1d, -sales_change_7d, sales_change_30d, -floor_price, market_cap. Required only for 'action=rank' - """, - ) - - -class NFTTool(BaseTool): - name = "NFTExecutor" - description = "A tool for searching NFT collections or getting collection rankings." - args_schema: Type[ARGS] = ARGS - - def _run( - self, - action: str, - keyword: Optional[str] = None, - sort_field: Optional[str] = "market_cap", - run_manager: Optional[CallbackManagerForToolRun] = None, - ) -> str: - if action == "search": - if keyword is None: - return "Error: A keyword is required for search operation." - return self.search_nft_collections(keyword) - elif action == "rank": - return self.collection_ranking(sort_field) - else: - return "Error: Unknown operation type. " "Please specify 'action' as 'search' or 'rank'." - - async def _arun( - self, - action: str, - keyword: Optional[str] = None, - sort_field: Optional[str] = "market_cap", - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, - ) -> str: - return self._run(action, keyword, sort_field, run_manager) - - @staticmethod - def search_nft_collections(keyword: str) -> str: - """Search for NFT collections.""" - url = "https://restapi.nftscan.com/api/v2/collections/filters" - payload = json.dumps( - { - "contract_address_list": [], - "name_fuzzy_search": "false", - "show_collection": "false", - "sort_direction": "desc", - "sort_field": "floor_price", - "name": "", - "symbol": keyword, - } - ) - headers = { - "Content-Type": "application/json", - "X-API-KEY": f"{settings.NFTSCAN_API_KEY}", - } - - response = requests.post(url, headers=headers, data=payload) - return response.text - - @staticmethod - def collection_ranking(sort_field: str) -> str: - """Search for NFT collections ranking.""" - url = f"https://restapi.nftscan.com/api/v2/statistics/ranking/collection?sort_field={sort_field}&sort_direction=desc&limit=20" - - headers = {"X-API-KEY": f"{settings.NFTSCAN_API_KEY}"} - response = requests.get(url, headers=headers) - return response.text From 7c74c89aa9ac97da1119ea132fc4aa21cca23cf8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 10:38:58 +0800 Subject: [PATCH 31/85] chore: Refactor workflow and member roles --- src/openagent/agents/market_analysis.py | 5 ++-- src/openagent/workflows/member.py | 26 +++++++++++++++++---- src/openagent/workflows/supervisor_chain.py | 17 ++++++++++---- src/openagent/workflows/workflow.py | 5 +--- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/openagent/agents/market_analysis.py b/src/openagent/agents/market_analysis.py index bda4cf5f..7932b47e 100644 --- a/src/openagent/agents/market_analysis.py +++ b/src/openagent/agents/market_analysis.py @@ -4,7 +4,8 @@ from openagent.conf.llm_provider import get_current_llm from openagent.tools.coin_market_tool import CoinMarketTool from openagent.tools.funding_rate_tool import FundingRateTool -from openagent.tools.nft_tool import NFTTool +from openagent.tools.nft_rank_tool import NFTRankingTool +from openagent.tools.nft_search_tool import NFTSearchTool from openagent.tools.price_tool import PriceTool from openagent.tools.tavily_tool import tavily_tool @@ -13,7 +14,7 @@ market_analysis_agent = create_agent( llm, - [tavily_tool, PriceTool(), FundingRateTool(), NFTTool(), CoinMarketTool()], + [tavily_tool, PriceTool(), FundingRateTool(), NFTSearchTool(), NFTRankingTool(), CoinMarketTool()], """ You are MarketAnalyst, responsible for providing market data analysis. Help users understand market dynamics and trends by retrieving real-time price information of tokens. diff --git a/src/openagent/workflows/member.py b/src/openagent/workflows/member.py index 799d594e..af68fc83 100644 --- a/src/openagent/workflows/member.py +++ b/src/openagent/workflows/member.py @@ -1,6 +1,22 @@ +from typing import Literal + +MARKET_ANALYSIS: str = "market_analysis_agent" +ASSET_MANAGEMENT = "asset_management_agent" +BLOCK_EXPLORER = "block_explorer_agent" +RESEARCH_ANALYST = "research_analyst_agent" +FALLBACK = "fallback_agent" + +AgentRole = Literal[ + "market_analysis_agent", + "asset_management_agent", + "block_explorer_agent", + "research_analyst_agent", + "fallback_agent" +] + members = [ { - "name": "market_analysis_agent", + "name": MARKET_ANALYSIS, "description": """ MarketAnalyst: Provides market data analysis and insights. @@ -13,7 +29,7 @@ """.strip(), }, { - "name": "asset_management_agent", + "name": ASSET_MANAGEMENT, "description": """ AssetManager: Assists with crypto asset management. @@ -26,7 +42,7 @@ """.strip(), }, { - "name": "block_explorer_agent", + "name": BLOCK_EXPLORER, "description": """ BlockExplorer: Assists in exploring blockchain data. @@ -39,7 +55,7 @@ """.strip(), }, { - "name": "research_analyst_agent", + "name": RESEARCH_ANALYST, "description": """ ResearchAnalyst: Conducts and provides web3 project research. @@ -52,7 +68,7 @@ """.strip(), }, { - "name": "fallback_agent", + "name": FALLBACK, "description": """ FallbackAgent: Handles general queries and conversations. diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index 6b9832f1..5e972019 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -1,13 +1,22 @@ from dotenv import load_dotenv +from langchain_core.messages import HumanMessage +from langchain_core.output_parsers import JsonOutputToolsParser from langchain_core.output_parsers.openai_functions import JsonOutputFunctionsParser from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder +from langchain_core.tools import tool -from openagent.conf.llm_provider import get_current_llm -from openagent.workflows.member import members +from openagent.conf.llm_provider import get_current_llm, set_current_llm +from openagent.workflows.member import members, AgentRole load_dotenv() +@tool +def route(next_: AgentRole): + """Select the next role.""" + pass + + def build_supervisor_chain(): system_prompt = """ You are an AI Agent Supervisor responsible for managing and coordinating the work of multiple specialized AI Agents. @@ -60,13 +69,13 @@ def build_supervisor_chain(): ("system", system_prompt), MessagesPlaceholder(variable_name="messages"), ( - "system", + "ai", "Given the conversation above, who should act next?" " Or should we FINISH? Select one of: {options}", ), ] ).partial(options=str(options), members=", ".join([member["name"] for member in members])) llm = get_current_llm() - return prompt | llm.bind_functions(functions=[function_def], function_call="route") | JsonOutputFunctionsParser() + return prompt | llm.bind_tools(tools=[route]) | JsonOutputToolsParser() | (lambda x: {'next': x[-1]['args']['next_']}) supervisor_chain = build_supervisor_chain() diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py index 464ad06a..3ba80e02 100644 --- a/src/openagent/workflows/workflow.py +++ b/src/openagent/workflows/workflow.py @@ -45,10 +45,7 @@ def build_workflow(): member_names = list(map(lambda x: x["name"], members)) for member in member_names: - if member == "fallback_agent": - workflow.add_edge(member, END) - continue - workflow.add_edge(member, "supervisor") + workflow.add_edge(member, END) conditional_map = {k: k for k in member_names} conditional_map["FINISH"] = END From 1edb6cd2878a10d7898f0a21426e75c9145f9dc0 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 10:43:22 +0800 Subject: [PATCH 32/85] chore: refactor route function --- src/openagent/workflows/supervisor_chain.py | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index 5e972019..ef32fdca 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -47,23 +47,7 @@ def build_supervisor_chain(): members_info = ", ".join([f"{member['name']} ({member['description']})" for member in members]) system_prompt = system_prompt.format(members=members_info) options = ["FINISH"] + [member["name"] for member in members] - function_def = { - "name": "route", - "description": "Select the next role.", - "parameters": { - "title": "routeSchema", - "type": "object", - "properties": { - "next": { - "title": "Next", - "anyOf": [ - {"enum": options}, - ], - } - }, - "required": ["next"], - }, - } + prompt = ChatPromptTemplate.from_messages( [ ("system", system_prompt), From 834aa6faa02f8affa42a4f5e1dfa653eaa2283ef Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 11:14:17 +0800 Subject: [PATCH 33/85] chore: force tool call at first in supervisor --- src/openagent/workflows/supervisor_chain.py | 15 ++++----------- src/tests/supervisor_chain.py | 13 ++++++------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index ef32fdca..a46aa33e 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -1,11 +1,9 @@ from dotenv import load_dotenv -from langchain_core.messages import HumanMessage from langchain_core.output_parsers import JsonOutputToolsParser -from langchain_core.output_parsers.openai_functions import JsonOutputFunctionsParser from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.tools import tool -from openagent.conf.llm_provider import get_current_llm, set_current_llm +from openagent.conf.llm_provider import get_current_llm from openagent.workflows.member import members, AgentRole load_dotenv() @@ -35,18 +33,13 @@ def build_supervisor_chain(): - Prioritize Agents who can advance the task, avoiding repetition of completed work. - If multiple Agents are suitable, select the one that can provide the most comprehensive or specialized response. -Completion criteria: -- Select FINISH when all user requests have been satisfactorily addressed. -- Choose FINISH if an AI Agent explicitly states that the task is fully completed. -- Opt for FINISH if you determine no more Agents can provide valuable input for the current task. - Based on these guidelines, the user request, and the conversation history, select the next AI Agent to perform the task or end the conversation. Your decisions should be efficient, ensuring the user receives the best possible service experience. """ members_info = ", ".join([f"{member['name']} ({member['description']})" for member in members]) system_prompt = system_prompt.format(members=members_info) - options = ["FINISH"] + [member["name"] for member in members] + options = [member["name"] for member in members] prompt = ChatPromptTemplate.from_messages( [ @@ -54,12 +47,12 @@ def build_supervisor_chain(): MessagesPlaceholder(variable_name="messages"), ( "ai", - "Given the conversation above, who should act next?" " Or should we FINISH? Select one of: {options}", + "Given the conversation above, who should act next?" "Select one of: {options}", ), ] ).partial(options=str(options), members=", ".join([member["name"] for member in members])) llm = get_current_llm() - return prompt | llm.bind_tools(tools=[route]) | JsonOutputToolsParser() | (lambda x: {'next': x[-1]['args']['next_']}) + return prompt | llm.bind_tools(tools=[route], tool_choice="route") | JsonOutputToolsParser() | (lambda x: {'next': x[-1]['args']['next_']}) supervisor_chain = build_supervisor_chain() diff --git a/src/tests/supervisor_chain.py b/src/tests/supervisor_chain.py index b85e1513..dbd7ec5d 100644 --- a/src/tests/supervisor_chain.py +++ b/src/tests/supervisor_chain.py @@ -1,13 +1,16 @@ import unittest from langchain_core.messages import HumanMessage +from loguru import logger +from openagent.conf.llm_provider import set_current_llm from openagent.workflows.supervisor_chain import build_supervisor_chain def next_role(query) -> str: supervisor_chain = build_supervisor_chain() - resp = supervisor_chain.invoke({"messages": [HumanMessage(content=query, name="humane")]}) + resp = supervisor_chain.invoke({"messages": [HumanMessage(content=query, name="human")]}) + logger.info(f"response: {resp}") return resp["next"] @@ -52,12 +55,8 @@ def test_multi_step_query(self): result = next_role(query) self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") - def test_finish(self): - query = "That's all I needed, thank you!" - expected_role = "FINISH" - result = next_role(query) - self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") - if __name__ == "__main__": + set_current_llm("gemini-1.5-pro") + # set_current_llm("gpt-3.5-turbo") unittest.main() From 77d3edcbe0f1090b5f97314449cbfa8690790bbe Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 11:46:22 +0800 Subject: [PATCH 34/85] chore: different model unittest --- src/openagent/workflows/workflow.py | 4 ++-- src/tests/supervisor_chain.py | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py index 3ba80e02..d63b6367 100644 --- a/src/openagent/workflows/workflow.py +++ b/src/openagent/workflows/workflow.py @@ -27,7 +27,7 @@ def build_workflow(): from openagent.agents.market_analysis import market_analysis_agent from openagent.agents.project_management import research_analyst_agent from openagent.workflows.member import members - from openagent.workflows.supervisor_chain import supervisor_chain + from openagent.workflows.supervisor_chain import build_supervisor_chain market_analysis_agent_node = create_node(market_analysis_agent, "market_analysis_agent") asset_management_agent_node = create_node(asset_management_agent, "asset_management_agent") @@ -39,7 +39,7 @@ def build_workflow(): workflow.add_node("asset_management_agent", asset_management_agent_node) workflow.add_node("block_explorer_agent", block_explorer_agent_node) workflow.add_node("research_analyst_agent", research_analyst_agent_node) - workflow.add_node("supervisor", supervisor_chain) + workflow.add_node("supervisor", build_supervisor_chain()) workflow.add_node("fallback_agent", fallback) member_names = list(map(lambda x: x["name"], members)) diff --git a/src/tests/supervisor_chain.py b/src/tests/supervisor_chain.py index dbd7ec5d..73f7a112 100644 --- a/src/tests/supervisor_chain.py +++ b/src/tests/supervisor_chain.py @@ -55,8 +55,11 @@ def test_multi_step_query(self): result = next_role(query) self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") + def setUp(self): + # set_current_llm("gemini-1.5-pro") + # set_current_llm("gpt-3.5-turbo") + set_current_llm("llama3.1:latest") + if __name__ == "__main__": - set_current_llm("gemini-1.5-pro") - # set_current_llm("gpt-3.5-turbo") unittest.main() From 439981281582e8fe823072a6294a1bf4b24e9301 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 11:46:33 +0800 Subject: [PATCH 35/85] chore: prompt improvement --- src/openagent/workflows/supervisor_chain.py | 48 ++++++++++++--------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index a46aa33e..363c5832 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -2,6 +2,7 @@ from langchain_core.output_parsers import JsonOutputToolsParser from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.tools import tool +from loguru import logger from openagent.conf.llm_provider import get_current_llm from openagent.workflows.member import members, AgentRole @@ -17,42 +18,47 @@ def route(next_: AgentRole): def build_supervisor_chain(): system_prompt = """ -You are an AI Agent Supervisor responsible for managing and coordinating the work of multiple specialized AI Agents. -Your task is to efficiently allocate and oversee tasks among the following AI Agents based on user requests: +You are an AI Agent Supervisor coordinating specialized AI Agents. Your task: + +1. Analyze user requests and conversation history. +2. Select the most suitable AI Agent based on their expertise: {members} -Your responsibilities: -1. Carefully analyze the user's request and the current conversation history. -2. Select the most suitable AI Agent to act next, based on task requirements and each Agent's expertise. -3. Monitor each AI Agent's output, evaluate task progress, and determine if other Agents need to intervene or if the task is complete. Selection principles: -- Choose the AI Agent whose expertise best matches the current needs. -- Consider task continuity, avoiding unnecessary Agent switches. -- Prioritize Agents who can advance the task, avoiding repetition of completed work. -- If multiple Agents are suitable, select the one that can provide the most comprehensive or specialized response. - -Based on these guidelines, the user request, and the conversation history, select the next AI Agent - to perform the task or end the conversation. Your decisions should be efficient, - ensuring the user receives the best possible service experience. +- Match Agent expertise to current needs. +- Prioritize Agents who can advance the task. +- Choose the Agent for the most comprehensive response. + +Based on these guidelines, select the next AI Agent or end the conversation. """ members_info = ", ".join([f"{member['name']} ({member['description']})" for member in members]) system_prompt = system_prompt.format(members=members_info) - options = [member["name"] for member in members] + options = [member["name"] for member in members] prompt = ChatPromptTemplate.from_messages( [ ("system", system_prompt), MessagesPlaceholder(variable_name="messages"), - ( - "ai", - "Given the conversation above, who should act next?" "Select one of: {options}", - ), + ] ).partial(options=str(options), members=", ".join([member["name"] for member in members])) llm = get_current_llm() - return prompt | llm.bind_tools(tools=[route], tool_choice="route") | JsonOutputToolsParser() | (lambda x: {'next': x[-1]['args']['next_']}) + + def extract_next(x): + try: + next__ = x[-1]['args']['next_'] + except Exception as ex: + logger.warning(f"Error extracting next agent: {x}") + next__ = "fallback_agent" + return {'next': next__} + + return ( + prompt + | llm.bind_tools(tools=[route], tool_choice="route") + | JsonOutputToolsParser() + | extract_next + ) -supervisor_chain = build_supervisor_chain() From 74096909e26d5ffdf111909082fc271b013eb5e7 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 11:46:53 +0800 Subject: [PATCH 36/85] chore: add ollama model --- src/openagent/conf/llm_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index 815b5262..99d4c6da 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -16,7 +16,7 @@ def get_available_ollama_providers(): try: ollama_list = ollama.list() models_ = list(map(lambda x: x["name"], ollama_list["models"])) - all_ = ["llama3.1:latest"] + all_ = ["llama3.1:latest", "mistral:latest", "deepseek-coder-v2"] available_models = list(filter(lambda x: x in all_, models_)) return available_models From d7d499899df9aa5aa11781e624abe5dd02f94374 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 12:10:41 +0800 Subject: [PATCH 37/85] chore: add AssetManagementAgent test --- src/openagent/conf/llm_provider.py | 1 + src/tests/asset_management_agent.py | 63 +++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/tests/asset_management_agent.py diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index 99d4c6da..6c268e0b 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -55,6 +55,7 @@ def get_current_llm() -> BaseChatModel | None: if llm is None: available_providers = get_available_providers() if len(available_providers) > 0: + logger.warning("No LLM provider is set. Using the {list(available_providers.keys())[0]} provider.") llm = list(available_providers.values())[0] # noqa else: logger.error("No LLM provider is available.") diff --git a/src/tests/asset_management_agent.py b/src/tests/asset_management_agent.py new file mode 100644 index 00000000..45555438 --- /dev/null +++ b/src/tests/asset_management_agent.py @@ -0,0 +1,63 @@ +import asyncio +import unittest + +from langchain_core.messages import HumanMessage + +from openagent.agents.asset_management import asset_management_agent +from openagent.conf.llm_provider import set_current_llm + + +class TestAssetManagementAgent(unittest.TestCase): + def setUp(self): + set_current_llm("gemini-1.5-pro") + # set_current_llm("gpt-3.5-turbo") + # set_current_llm("llama3.1:latest") + + def test_swap_eth_to_usdt(self): + async def async_test(): + events = asset_management_agent.astream_events({"messages": [ + HumanMessage(content="Can you swap 20 eth to usdt ?", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event_data_input_['from_token'], 'ETH') + self.assertEqual(event_data_input_['to_token'], 'USDT') + self.assertEqual(event_data_input_['amount'], '20') + + asyncio.run(async_test()) + + def test_query_user_token_balance(self): + async def async_test(): + events = asset_management_agent.astream_events({"messages": [ + HumanMessage(content="Can you check 0x33c0814654fa367ce67d8531026eb4481290e63c eth balance ?", + name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event_data_input_['wallet_address'], '0x33c0814654fa367ce67d8531026eb4481290e63c') + self.assertEqual(event_data_input_['chain'], 'eth-mainnet') + + asyncio.run(async_test()) + + def test_query_user_nft_holdings(self): + async def async_test(): + events = asset_management_agent.astream_events({"messages": [ + HumanMessage(content="Can you check 0x33c0814654fa367ce67d8531026eb4481290e63c nft holdings ?", + name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event_data_input_['wallet_address'], '0x33c0814654fa367ce67d8531026eb4481290e63c') + self.assertEqual(event_data_input_['chain'], 'eth-mainnet') + + asyncio.run(async_test()) + + +if __name__ == '__main__': + unittest.main() From 83e3ab2b8b6e55d22e851d428d02a054edf53aba Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 14:35:38 +0800 Subject: [PATCH 38/85] feat: Add gemini flash --- src/openagent/conf/llm_provider.py | 1 + src/openagent/ui/profile.py | 5 +++++ src/openagent/workflows/supervisor_chain.py | 2 +- src/openagent/workflows/workflow.py | 1 - src/tests/supervisor_chain.py | 10 ++++++---- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index 6c268e0b..bdc047b3 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -32,6 +32,7 @@ def get_available_providers(): providers["gpt-4o"] = ChatOpenAI(model="gpt-4o") if settings.VERTEX_PROJECT_ID: providers["gemini-1.5-pro"] = ChatVertexAI(model="gemini-1.5-pro") + providers["gemini-1.5-flash"] = ChatVertexAI(model="gemini-1.5-flash") if settings.OLLAMA_HOST: ollama_providers = get_available_ollama_providers() diff --git a/src/openagent/ui/profile.py b/src/openagent/ui/profile.py index 8aa9eab1..a11917ff 100644 --- a/src/openagent/ui/profile.py +++ b/src/openagent/ui/profile.py @@ -16,6 +16,11 @@ "markdown_description": "The underlying LLM model is **Gemini 1.5 Pro**.", "icon": "https://custom.typingmind.com/assets/models/gemini.png", }, + "gemini-1.5-flash": { + "name": "Gemini 1.5 Flash", + "markdown_description": "The underlying LLM model is **Gemini 1.5 Flash**.", + "icon": "https://custom.typingmind.com/assets/models/gemini.png", + }, "llama3.1:latest": { "name": "LLAMA 3.1", "markdown_description": "The underlying LLM model is **LLAMA 3.1**.", diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index 363c5832..8030890f 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -56,7 +56,7 @@ def extract_next(x): return ( prompt - | llm.bind_tools(tools=[route], tool_choice="route") + | llm.bind_tools(tools=[route], tool_choice="route" if llm.model_name != 'gemini-1.5-flash' else None ) | JsonOutputToolsParser() | extract_next ) diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py index d63b6367..1a446c0e 100644 --- a/src/openagent/workflows/workflow.py +++ b/src/openagent/workflows/workflow.py @@ -48,7 +48,6 @@ def build_workflow(): workflow.add_edge(member, END) conditional_map = {k: k for k in member_names} - conditional_map["FINISH"] = END workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map) workflow.set_entry_point("supervisor") return workflow.compile() diff --git a/src/tests/supervisor_chain.py b/src/tests/supervisor_chain.py index 73f7a112..4ac60449 100644 --- a/src/tests/supervisor_chain.py +++ b/src/tests/supervisor_chain.py @@ -15,6 +15,12 @@ def next_role(query) -> str: class TestNextRole(unittest.TestCase): + def setUp(self): + # set_current_llm("gemini-1.5-pro") + set_current_llm("gemini-1.5-flash") + # set_current_llm("gpt-3.5-turbo") + # set_current_llm("llama3.1:latest") + def test_market_analysis(self): query = "What's the current price of Ethereum and its market trend?" expected_role = "market_analysis_agent" @@ -55,10 +61,6 @@ def test_multi_step_query(self): result = next_role(query) self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") - def setUp(self): - # set_current_llm("gemini-1.5-pro") - # set_current_llm("gpt-3.5-turbo") - set_current_llm("llama3.1:latest") if __name__ == "__main__": From 1a64bb7ac57c815040d9ecd34410138becce665f Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 14:47:35 +0800 Subject: [PATCH 39/85] chore: add tool name assert --- ...anagement_agent.py => asset_management.py} | 3 ++ src/tests/block_explore.py | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+) rename src/tests/{asset_management_agent.py => asset_management.py} (92%) create mode 100644 src/tests/block_explore.py diff --git a/src/tests/asset_management_agent.py b/src/tests/asset_management.py similarity index 92% rename from src/tests/asset_management_agent.py rename to src/tests/asset_management.py index 45555438..1fba6d16 100644 --- a/src/tests/asset_management_agent.py +++ b/src/tests/asset_management.py @@ -22,6 +22,7 @@ async def async_test(): async for event in events: if event['event'] == 'on_tool_end': event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'SwapExecutor') self.assertEqual(event_data_input_['from_token'], 'ETH') self.assertEqual(event_data_input_['to_token'], 'USDT') self.assertEqual(event_data_input_['amount'], '20') @@ -38,6 +39,7 @@ async def async_test(): async for event in events: if event['event'] == 'on_tool_end': event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'TokenBalanceExecutor') self.assertEqual(event_data_input_['wallet_address'], '0x33c0814654fa367ce67d8531026eb4481290e63c') self.assertEqual(event_data_input_['chain'], 'eth-mainnet') @@ -53,6 +55,7 @@ async def async_test(): async for event in events: if event['event'] == 'on_tool_end': event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'NFTBalanceExecutor') self.assertEqual(event_data_input_['wallet_address'], '0x33c0814654fa367ce67d8531026eb4481290e63c') self.assertEqual(event_data_input_['chain'], 'eth-mainnet') diff --git a/src/tests/block_explore.py b/src/tests/block_explore.py new file mode 100644 index 00000000..4b9c1cd0 --- /dev/null +++ b/src/tests/block_explore.py @@ -0,0 +1,32 @@ +import asyncio +import unittest + +from langchain_core.messages import HumanMessage + +from openagent.agents.block_explore import block_explorer_agent +from openagent.conf.llm_provider import set_current_llm + + +class TestBlockExploreAgent(unittest.TestCase): + def setUp(self): + # set_current_llm("gemini-1.5-pro") + set_current_llm("gpt-3.5-turbo") + # set_current_llm("llama3.1:latest") + + def test_query_block_height(self): + async def async_test(): + events = block_explorer_agent.astream_events({"messages": [ + HumanMessage(content="What's the latest block height on the Ethereum network?", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'BlockChainStatExecutor') + self.assertEqual(event_data_input_['chain'], 'ethereum') + + asyncio.run(async_test()) + + +if __name__ == '__main__': + unittest.main() From 22c25718a3bf2eef0598ad94e44414c8a13ec4d3 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 14:50:35 +0800 Subject: [PATCH 40/85] chore: categorize test file --- src/tests/agent_trajectory/__init__.py | 0 .../asset_management.py | 0 .../{ => agent_trajectory}/block_explore.py | 0 src/tests/cases.py | 51 ------------------- 4 files changed, 51 deletions(-) create mode 100644 src/tests/agent_trajectory/__init__.py rename src/tests/{ => agent_trajectory}/asset_management.py (100%) rename src/tests/{ => agent_trajectory}/block_explore.py (100%) delete mode 100644 src/tests/cases.py diff --git a/src/tests/agent_trajectory/__init__.py b/src/tests/agent_trajectory/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/tests/asset_management.py b/src/tests/agent_trajectory/asset_management.py similarity index 100% rename from src/tests/asset_management.py rename to src/tests/agent_trajectory/asset_management.py diff --git a/src/tests/block_explore.py b/src/tests/agent_trajectory/block_explore.py similarity index 100% rename from src/tests/block_explore.py rename to src/tests/agent_trajectory/block_explore.py diff --git a/src/tests/cases.py b/src/tests/cases.py deleted file mode 100644 index ea027845..00000000 --- a/src/tests/cases.py +++ /dev/null @@ -1,51 +0,0 @@ -import asyncio -import time - -from openagent.agent.function_agent import get_agent - -question_list = [ - # "show some web3 articles?", - "What is the price of ETH?", - # "What did vitalik.eth do recently?", - # "Send 0.01 eth to vitalik.eth", - # "Swap 1 eth to usdt", - # "What is MODE chain?", - # "Give me the bitcoin price chart", - # "List some popular NFTs?", - # "What's the largest dex with highest trading volume on Solana?", - # "When ETH ETF 19b-4 forms approved?", - # "Who are the main investors of EigenLayer?", -] - - -async def dummy(_) -> None: - pass - - -async def init(): - # vertexai.init(project='openagent-422907') - - # langchain.debug=True - start = time.time() - agent = get_agent("11") - for question in question_list: - print(f"Question: {question}") - - await agent.ainvoke( - {"input": question}, - config={ - "metadata": {"agentName": "openagent-backend", "userId": "123"}, - }, - ) - - time.sleep(1) - - print("--------------") - - end = time.time() - - print(f"Time elapsed: {end - start}") - - -if __name__ == "__main__": - asyncio.run(init()) From 16b606ca81cda682564bb5c7ef57b40b1d29441f Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:01:37 +0800 Subject: [PATCH 41/85] feat: Add market_analysis.py test --- src/openagent/tools/coin_market_tool.py | 2 +- src/openagent/tools/nft_rank_tool.py | 2 +- src/tests/agent_trajectory/market_analysis.py | 88 +++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/tests/agent_trajectory/market_analysis.py diff --git a/src/openagent/tools/coin_market_tool.py b/src/openagent/tools/coin_market_tool.py index 0f8a5428..982dd6db 100644 --- a/src/openagent/tools/coin_market_tool.py +++ b/src/openagent/tools/coin_market_tool.py @@ -20,7 +20,7 @@ class ARGS(BaseModel): class CoinMarketTool(BaseTool): - name = "CoinsMarketExecutor" + name = "CoinMarketExecutor" description = "query coins sorted by market cap, volume." args_schema: Type[ARGS] = ARGS diff --git a/src/openagent/tools/nft_rank_tool.py b/src/openagent/tools/nft_rank_tool.py index 1265249e..4503195a 100644 --- a/src/openagent/tools/nft_rank_tool.py +++ b/src/openagent/tools/nft_rank_tool.py @@ -22,7 +22,7 @@ class NFTRankingArgs(BaseModel): ) class NFTRankingTool(BaseTool): - name = "NFTRankingTool" + name = "NFTRankingExecutor" description = "A tool for getting NFT collection rankings." args_schema: Type[NFTRankingArgs] = NFTRankingArgs diff --git a/src/tests/agent_trajectory/market_analysis.py b/src/tests/agent_trajectory/market_analysis.py new file mode 100644 index 00000000..32accdcd --- /dev/null +++ b/src/tests/agent_trajectory/market_analysis.py @@ -0,0 +1,88 @@ +import asyncio +import unittest + +from langchain_core.messages import HumanMessage + +from openagent.agents.block_explore import block_explorer_agent +from openagent.agents.market_analysis import market_analysis_agent +from openagent.conf.llm_provider import set_current_llm + + +class TestBlockExploreAgent(unittest.TestCase): + def setUp(self): + # set_current_llm("gemini-1.5-pro") + set_current_llm("gpt-3.5-turbo") + # set_current_llm("llama3.1:latest") + + def test_query_btc_price(self): + async def async_test(): + events = market_analysis_agent.astream_events({"messages": [ + HumanMessage(content="What's BTC price now?", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'PriceExecutor') + self.assertEqual(event_data_input_['token'], 'BTC') + + asyncio.run(async_test()) + + def test_query_eth_price(self): + async def async_test(): + events = market_analysis_agent.astream_events({"messages": [ + HumanMessage(content="What's the current price of Ethereum?", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'PriceExecutor') + self.assertEqual(event_data_input_['token'], 'ETH') + + asyncio.run(async_test()) + + def test_query_funding_rate(self): + async def async_test(): + events = market_analysis_agent.astream_events({"messages": [ + HumanMessage(content="What's the funding rate for BTC/USDT in binance?", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'FundingRateExecutor') + self.assertEqual(event_data_input_['exchange'], 'binance') + self.assertEqual(event_data_input_['symbol'], 'BTC/USDT') + + asyncio.run(async_test()) + + def test_query_nft_ranking(self): + async def async_test(): + events = market_analysis_agent.astream_events({"messages": [ + HumanMessage(content="What are the top 5 NFT collections?", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + self.assertEqual(event['name'], 'NFTRankingExecutor') + + asyncio.run(async_test()) + + def test_query_coin_market(self): + async def async_test(): + events = market_analysis_agent.astream_events({"messages": [ + HumanMessage(content="Give me the market cap for Bitcoin", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'CoinMarketExecutor') + self.assertEqual(event_data_input_['order'], 'market_cap_desc') + + asyncio.run(async_test()) + + +if __name__ == '__main__': + unittest.main() From 36e20c6ba375a696be8f8ded7ff88fe92bbb0827 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:08:08 +0800 Subject: [PATCH 42/85] feat: Add research_analyst.py test --- src/tests/agent_trajectory/market_analysis.py | 2 +- .../agent_trajectory/research_analyst.py | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/tests/agent_trajectory/research_analyst.py diff --git a/src/tests/agent_trajectory/market_analysis.py b/src/tests/agent_trajectory/market_analysis.py index 32accdcd..6848dad1 100644 --- a/src/tests/agent_trajectory/market_analysis.py +++ b/src/tests/agent_trajectory/market_analysis.py @@ -8,7 +8,7 @@ from openagent.conf.llm_provider import set_current_llm -class TestBlockExploreAgent(unittest.TestCase): +class TestMarketAnalysisAgent(unittest.TestCase): def setUp(self): # set_current_llm("gemini-1.5-pro") set_current_llm("gpt-3.5-turbo") diff --git a/src/tests/agent_trajectory/research_analyst.py b/src/tests/agent_trajectory/research_analyst.py new file mode 100644 index 00000000..f8b860ab --- /dev/null +++ b/src/tests/agent_trajectory/research_analyst.py @@ -0,0 +1,33 @@ +import asyncio +import unittest + +from langchain_core.messages import HumanMessage + +from openagent.agents.project_management import research_analyst_agent +from openagent.conf.llm_provider import set_current_llm + + +class TestResearchAnalystAgent(unittest.TestCase): + def setUp(self): + # set_current_llm("gemini-1.5-pro") + set_current_llm("gpt-3.5-turbo") + # set_current_llm("llama3.1:latest") + + def test_query_project(self): + async def async_test(): + events = research_analyst_agent.astream_events({"messages": [ + HumanMessage(content="Do you know anything about RSS3?", + name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'ProjectExecutor') + self.assertEqual(event_data_input_['keyword'], 'RSS3') + + asyncio.run(async_test()) + + +if __name__ == '__main__': + unittest.main() From 90bf5b6676c22ade4aa8886788b4451974d6315b Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:12:06 +0800 Subject: [PATCH 43/85] fix: logger error to warning and add f-string for better readability --- src/openagent/conf/llm_provider.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index bdc047b3..e20d270d 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -21,7 +21,7 @@ def get_available_ollama_providers(): available_models = list(filter(lambda x: x in all_, models_)) return available_models except Exception as e: - logger.error(f"Failed to get available ollama providers: {e}") + logger.warning(f"Failed to get available ollama providers: {e}") return [] @@ -56,7 +56,7 @@ def get_current_llm() -> BaseChatModel | None: if llm is None: available_providers = get_available_providers() if len(available_providers) > 0: - logger.warning("No LLM provider is set. Using the {list(available_providers.keys())[0]} provider.") + logger.warning(f"No LLM provider is set. Using the {list(available_providers.keys())[0]} provider.") llm = list(available_providers.values())[0] # noqa else: logger.error("No LLM provider is available.") From bec36c1c93a62eb173f38401e4df8eeb7e6ccaaa Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:17:20 +0800 Subject: [PATCH 44/85] chore: fallback agent prompt improvement --- src/openagent/agents/fallback.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/openagent/agents/fallback.py b/src/openagent/agents/fallback.py index 145227d4..60de8680 100644 --- a/src/openagent/agents/fallback.py +++ b/src/openagent/agents/fallback.py @@ -14,17 +14,33 @@ def fallback(state): ( "system", """ -You are openagent! +You are the OpenAgent created by RSS3. -Your answer should be detailed and include puns or jokes where possible \ -And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. - """, +Your role: +1. Handle general queries and conversations that don't fall under the expertise of other specialized agents. +2. Clarify unclear requests and provide versatile assistance. +3. Maintain conversation continuity and guide users to appropriate specialists when necessary. + +Your communication style: +- Be friendly, approachable, and enthusiastic in your responses. +- Use a mix of professional knowledge and casual charm. +- Include relevant puns, jokes, or word plays to keep the conversation lively. +- Sprinkle in emojis occasionally to add personality to your messages. +- Provide detailed answers, but keep them concise and easy to understand. + +Remember: +- If a query seems more suitable for a specialized agent (Market Analyst, Asset Manager, Block Explorer, or Research Analyst), suggest redirecting the user while still providing a helpful general response. +- Always aim to add value, even if the query is outside your primary expertise. +- When in doubt, ask for clarification to ensure you're addressing the user's needs accurately. + +Let's make every interaction informative, fun, and memorable! 🚀✨ + """.strip() ), *state["messages"][0:-1], ("human", "{input}"), ] ) - chain = chat_template | chat_template | get_current_llm() | StrOutputParser() + chain = chat_template | get_current_llm() | StrOutputParser() return { "messages": [ HumanMessage( From 7fba592164ed92f21894e5cd9d5d563470ccad68 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:23:36 +0800 Subject: [PATCH 45/85] chore: hide useless API docs --- src/openagent/app.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/openagent/app.py b/src/openagent/app.py index 6e7f004a..b2e759e4 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -5,6 +5,7 @@ from dotenv import load_dotenv from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware +from langchain_core.messages import HumanMessage from loguru import logger from pydantic import BaseModel from sse_starlette import EventSourceResponse @@ -26,17 +27,17 @@ ) -@app.get("/health", status_code=status.HTTP_200_OK) +@app.get("/health", status_code=status.HTTP_200_OK, include_in_schema=False) async def health_check(): return JSONResponse(content={"status": "ok"}) -@app.get("/widget/swap") +@app.get("/widget/swap", include_in_schema=False) async def swap_root(): return FileResponse(os.path.join("dist", "index.html")) -@app.get("/widget/price-chart") +@app.get("/widget/price-chart", include_in_schema=False) async def chart_price_root(): return FileResponse(os.path.join("dist", "index.html")) @@ -50,7 +51,7 @@ async def outline_creation(req: Input): agent = build_workflow() async def stream(): - async for event in agent.astream_events({"input": req.text}, version="v1"): + async for event in agent.astream_events({"messages": [HumanMessage(content=req.text)]}, version="v1"): kind = event["event"] if kind == "on_chat_model_stream": yield json.dumps(event["data"]["chunk"].dict(), ensure_ascii=False) @@ -69,5 +70,4 @@ async def stream(): app.mount("/static", StaticFiles(directory=static_dir), name="widget") - mount_chainlit(app=app, target="openagent/ui/app.py", path="") From 905c679235873da87c24c1e231fe659f32dccf71 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:28:01 +0800 Subject: [PATCH 46/85] chore: remove useless log --- src/openagent/conf/llm_provider.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index e20d270d..d5c4a16d 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -36,7 +36,6 @@ def get_available_providers(): if settings.OLLAMA_HOST: ollama_providers = get_available_ollama_providers() - print(ollama_providers) for model in ollama_providers: providers[model] = ChatOllama(model=model) return providers From 28bfe1f2080da043d2295ff9bb79ee88cce08c38 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:35:02 +0800 Subject: [PATCH 47/85] fix: pre-commit lint --- src/openagent/agents/fallback.py | 5 +- src/openagent/conf/llm_provider.py | 2 +- src/openagent/experts/search_expert.py | 12 ++-- src/openagent/tools/nft_rank_tool.py | 2 + src/openagent/tools/nft_search_tool.py | 12 ++-- src/openagent/workflows/member.py | 8 +-- src/openagent/workflows/supervisor_chain.py | 19 +++-- .../agent_trajectory/asset_management.py | 56 +++++++-------- src/tests/agent_trajectory/block_explore.py | 16 ++--- src/tests/agent_trajectory/market_analysis.py | 69 +++++++++---------- .../agent_trajectory/research_analyst.py | 17 +++-- src/tests/supervisor_chain.py | 1 - 12 files changed, 104 insertions(+), 115 deletions(-) diff --git a/src/openagent/agents/fallback.py b/src/openagent/agents/fallback.py index 60de8680..4e2d0cf5 100644 --- a/src/openagent/agents/fallback.py +++ b/src/openagent/agents/fallback.py @@ -29,12 +29,13 @@ def fallback(state): - Provide detailed answers, but keep them concise and easy to understand. Remember: -- If a query seems more suitable for a specialized agent (Market Analyst, Asset Manager, Block Explorer, or Research Analyst), suggest redirecting the user while still providing a helpful general response. +- If a query seems more suitable for a specialized agent (Market Analyst, Asset Manager, + Block Explorer, or Research Analyst), suggest redirecting the user while still providing a helpful general response. - Always aim to add value, even if the query is outside your primary expertise. - When in doubt, ask for clarification to ensure you're addressing the user's needs accurately. Let's make every interaction informative, fun, and memorable! 🚀✨ - """.strip() + """.strip(), ), *state["messages"][0:-1], ("human", "{input}"), diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index d5c4a16d..69fff49b 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -55,7 +55,7 @@ def get_current_llm() -> BaseChatModel | None: if llm is None: available_providers = get_available_providers() if len(available_providers) > 0: - logger.warning(f"No LLM provider is set. Using the {list(available_providers.keys())[0]} provider.") + logger.warning(f"No LLM provider is set. Using the {list(available_providers.keys())[0]} provider.") # noqa llm = list(available_providers.values())[0] # noqa else: logger.error("No LLM provider is available.") diff --git a/src/openagent/experts/search_expert.py b/src/openagent/experts/search_expert.py index 366e57c8..e92a3a78 100644 --- a/src/openagent/experts/search_expert.py +++ b/src/openagent/experts/search_expert.py @@ -29,15 +29,15 @@ class SearchExpert(BaseTool): args_schema: Type[SearchSchema] = SearchSchema def _run( - self, - query: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + query: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: raise NotImplementedError async def _arun( - self, - query: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + query: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ) -> str: return await google_search(query) diff --git a/src/openagent/tools/nft_rank_tool.py b/src/openagent/tools/nft_rank_tool.py index 4503195a..feeaf3cc 100644 --- a/src/openagent/tools/nft_rank_tool.py +++ b/src/openagent/tools/nft_rank_tool.py @@ -10,6 +10,7 @@ from openagent.conf.env import settings + class NFTRankingArgs(BaseModel): sort_field: str = Field( default="market_cap", @@ -21,6 +22,7 @@ class NFTRankingArgs(BaseModel): """, ) + class NFTRankingTool(BaseTool): name = "NFTRankingExecutor" description = "A tool for getting NFT collection rankings." diff --git a/src/openagent/tools/nft_search_tool.py b/src/openagent/tools/nft_search_tool.py index 5220fd69..e8dff226 100644 --- a/src/openagent/tools/nft_search_tool.py +++ b/src/openagent/tools/nft_search_tool.py @@ -22,16 +22,16 @@ class NFTSearchTool(BaseTool): args_schema: Type[NFTSearchArgs] = NFTSearchArgs def _run( - self, - keyword: str, - run_manager: Optional[CallbackManagerForToolRun] = None, + self, + keyword: str, + run_manager: Optional[CallbackManagerForToolRun] = None, ) -> str: return self.search_nft_collections(keyword) async def _arun( - self, - keyword: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + self, + keyword: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ) -> str: return self._run(keyword, run_manager) diff --git a/src/openagent/workflows/member.py b/src/openagent/workflows/member.py index af68fc83..ff0c2dc0 100644 --- a/src/openagent/workflows/member.py +++ b/src/openagent/workflows/member.py @@ -6,13 +6,7 @@ RESEARCH_ANALYST = "research_analyst_agent" FALLBACK = "fallback_agent" -AgentRole = Literal[ - "market_analysis_agent", - "asset_management_agent", - "block_explorer_agent", - "research_analyst_agent", - "fallback_agent" -] +AgentRole = Literal["market_analysis_agent", "asset_management_agent", "block_explorer_agent", "research_analyst_agent", "fallback_agent"] members = [ { diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index 8030890f..6ceffc96 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -5,7 +5,7 @@ from loguru import logger from openagent.conf.llm_provider import get_current_llm -from openagent.workflows.member import members, AgentRole +from openagent.workflows.member import AgentRole, members load_dotenv() @@ -41,24 +41,21 @@ def build_supervisor_chain(): [ ("system", system_prompt), MessagesPlaceholder(variable_name="messages"), - ] ).partial(options=str(options), members=", ".join([member["name"] for member in members])) llm = get_current_llm() def extract_next(x): try: - next__ = x[-1]['args']['next_'] - except Exception as ex: + next__ = x[-1]["args"]["next_"] + except Exception: logger.warning(f"Error extracting next agent: {x}") next__ = "fallback_agent" - return {'next': next__} + return {"next": next__} return ( - prompt - | llm.bind_tools(tools=[route], tool_choice="route" if llm.model_name != 'gemini-1.5-flash' else None ) - | JsonOutputToolsParser() - | extract_next + prompt + | llm.bind_tools(tools=[route], tool_choice="route" if llm.model_name != "gemini-1.5-flash" else None) + | JsonOutputToolsParser() + | extract_next ) - - diff --git a/src/tests/agent_trajectory/asset_management.py b/src/tests/agent_trajectory/asset_management.py index 1fba6d16..224e185a 100644 --- a/src/tests/agent_trajectory/asset_management.py +++ b/src/tests/agent_trajectory/asset_management.py @@ -15,52 +15,52 @@ def setUp(self): def test_swap_eth_to_usdt(self): async def async_test(): - events = asset_management_agent.astream_events({"messages": [ - HumanMessage(content="Can you swap 20 eth to usdt ?", name="human")]}, - version="v1") + events = asset_management_agent.astream_events( + {"messages": [HumanMessage(content="Can you swap 20 eth to usdt ?", name="human")]}, version="v1" + ) async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'SwapExecutor') - self.assertEqual(event_data_input_['from_token'], 'ETH') - self.assertEqual(event_data_input_['to_token'], 'USDT') - self.assertEqual(event_data_input_['amount'], '20') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "SwapExecutor") + self.assertEqual(event_data_input_["from_token"], "ETH") + self.assertEqual(event_data_input_["to_token"], "USDT") + self.assertEqual(event_data_input_["amount"], "20") asyncio.run(async_test()) def test_query_user_token_balance(self): async def async_test(): - events = asset_management_agent.astream_events({"messages": [ - HumanMessage(content="Can you check 0x33c0814654fa367ce67d8531026eb4481290e63c eth balance ?", - name="human")]}, - version="v1") + events = asset_management_agent.astream_events( + {"messages": [HumanMessage(content="Can you check 0x33c0814654fa367ce67d8531026eb4481290e63c eth balance ?", name="human")]}, + version="v1", + ) async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'TokenBalanceExecutor') - self.assertEqual(event_data_input_['wallet_address'], '0x33c0814654fa367ce67d8531026eb4481290e63c') - self.assertEqual(event_data_input_['chain'], 'eth-mainnet') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "TokenBalanceExecutor") + self.assertEqual(event_data_input_["wallet_address"], "0x33c0814654fa367ce67d8531026eb4481290e63c") + self.assertEqual(event_data_input_["chain"], "eth-mainnet") asyncio.run(async_test()) def test_query_user_nft_holdings(self): async def async_test(): - events = asset_management_agent.astream_events({"messages": [ - HumanMessage(content="Can you check 0x33c0814654fa367ce67d8531026eb4481290e63c nft holdings ?", - name="human")]}, - version="v1") + events = asset_management_agent.astream_events( + {"messages": [HumanMessage(content="Can you check 0x33c0814654fa367ce67d8531026eb4481290e63c nft holdings ?", name="human")]}, + version="v1", + ) async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'NFTBalanceExecutor') - self.assertEqual(event_data_input_['wallet_address'], '0x33c0814654fa367ce67d8531026eb4481290e63c') - self.assertEqual(event_data_input_['chain'], 'eth-mainnet') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "NFTBalanceExecutor") + self.assertEqual(event_data_input_["wallet_address"], "0x33c0814654fa367ce67d8531026eb4481290e63c") + self.assertEqual(event_data_input_["chain"], "eth-mainnet") asyncio.run(async_test()) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/src/tests/agent_trajectory/block_explore.py b/src/tests/agent_trajectory/block_explore.py index 4b9c1cd0..47bb5661 100644 --- a/src/tests/agent_trajectory/block_explore.py +++ b/src/tests/agent_trajectory/block_explore.py @@ -15,18 +15,18 @@ def setUp(self): def test_query_block_height(self): async def async_test(): - events = block_explorer_agent.astream_events({"messages": [ - HumanMessage(content="What's the latest block height on the Ethereum network?", name="human")]}, - version="v1") + events = block_explorer_agent.astream_events( + {"messages": [HumanMessage(content="What's the latest block height on the Ethereum network?", name="human")]}, version="v1" + ) async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'BlockChainStatExecutor') - self.assertEqual(event_data_input_['chain'], 'ethereum') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "BlockChainStatExecutor") + self.assertEqual(event_data_input_["chain"], "ethereum") asyncio.run(async_test()) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/src/tests/agent_trajectory/market_analysis.py b/src/tests/agent_trajectory/market_analysis.py index 6848dad1..a1a3446a 100644 --- a/src/tests/agent_trajectory/market_analysis.py +++ b/src/tests/agent_trajectory/market_analysis.py @@ -3,7 +3,6 @@ from langchain_core.messages import HumanMessage -from openagent.agents.block_explore import block_explorer_agent from openagent.agents.market_analysis import market_analysis_agent from openagent.conf.llm_provider import set_current_llm @@ -16,73 +15,71 @@ def setUp(self): def test_query_btc_price(self): async def async_test(): - events = market_analysis_agent.astream_events({"messages": [ - HumanMessage(content="What's BTC price now?", name="human")]}, - version="v1") + events = market_analysis_agent.astream_events({"messages": [HumanMessage(content="What's BTC price now?", name="human")]}, version="v1") async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'PriceExecutor') - self.assertEqual(event_data_input_['token'], 'BTC') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "PriceExecutor") + self.assertEqual(event_data_input_["token"], "BTC") asyncio.run(async_test()) def test_query_eth_price(self): async def async_test(): - events = market_analysis_agent.astream_events({"messages": [ - HumanMessage(content="What's the current price of Ethereum?", name="human")]}, - version="v1") + events = market_analysis_agent.astream_events( + {"messages": [HumanMessage(content="What's the current price of Ethereum?", name="human")]}, version="v1" + ) async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'PriceExecutor') - self.assertEqual(event_data_input_['token'], 'ETH') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "PriceExecutor") + self.assertEqual(event_data_input_["token"], "ETH") asyncio.run(async_test()) def test_query_funding_rate(self): async def async_test(): - events = market_analysis_agent.astream_events({"messages": [ - HumanMessage(content="What's the funding rate for BTC/USDT in binance?", name="human")]}, - version="v1") + events = market_analysis_agent.astream_events( + {"messages": [HumanMessage(content="What's the funding rate for BTC/USDT in binance?", name="human")]}, version="v1" + ) async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'FundingRateExecutor') - self.assertEqual(event_data_input_['exchange'], 'binance') - self.assertEqual(event_data_input_['symbol'], 'BTC/USDT') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "FundingRateExecutor") + self.assertEqual(event_data_input_["exchange"], "binance") + self.assertEqual(event_data_input_["symbol"], "BTC/USDT") asyncio.run(async_test()) def test_query_nft_ranking(self): async def async_test(): - events = market_analysis_agent.astream_events({"messages": [ - HumanMessage(content="What are the top 5 NFT collections?", name="human")]}, - version="v1") + events = market_analysis_agent.astream_events( + {"messages": [HumanMessage(content="What are the top 5 NFT collections?", name="human")]}, version="v1" + ) async for event in events: - if event['event'] == 'on_tool_end': - self.assertEqual(event['name'], 'NFTRankingExecutor') + if event["event"] == "on_tool_end": + self.assertEqual(event["name"], "NFTRankingExecutor") asyncio.run(async_test()) def test_query_coin_market(self): async def async_test(): - events = market_analysis_agent.astream_events({"messages": [ - HumanMessage(content="Give me the market cap for Bitcoin", name="human")]}, - version="v1") + events = market_analysis_agent.astream_events( + {"messages": [HumanMessage(content="Give me the market cap for Bitcoin", name="human")]}, version="v1" + ) async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'CoinMarketExecutor') - self.assertEqual(event_data_input_['order'], 'market_cap_desc') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "CoinMarketExecutor") + self.assertEqual(event_data_input_["order"], "market_cap_desc") asyncio.run(async_test()) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/src/tests/agent_trajectory/research_analyst.py b/src/tests/agent_trajectory/research_analyst.py index f8b860ab..76f9cbf5 100644 --- a/src/tests/agent_trajectory/research_analyst.py +++ b/src/tests/agent_trajectory/research_analyst.py @@ -15,19 +15,18 @@ def setUp(self): def test_query_project(self): async def async_test(): - events = research_analyst_agent.astream_events({"messages": [ - HumanMessage(content="Do you know anything about RSS3?", - name="human")]}, - version="v1") + events = research_analyst_agent.astream_events( + {"messages": [HumanMessage(content="Do you know anything about RSS3?", name="human")]}, version="v1" + ) async for event in events: - if event['event'] == 'on_tool_end': - event_data_input_ = event['data']['input'] - self.assertEqual(event['name'], 'ProjectExecutor') - self.assertEqual(event_data_input_['keyword'], 'RSS3') + if event["event"] == "on_tool_end": + event_data_input_ = event["data"]["input"] + self.assertEqual(event["name"], "ProjectExecutor") + self.assertEqual(event_data_input_["keyword"], "RSS3") asyncio.run(async_test()) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/src/tests/supervisor_chain.py b/src/tests/supervisor_chain.py index 4ac60449..309da2f2 100644 --- a/src/tests/supervisor_chain.py +++ b/src/tests/supervisor_chain.py @@ -62,6 +62,5 @@ def test_multi_step_query(self): self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") - if __name__ == "__main__": unittest.main() From 607607471647aa2f0efe6c1e676b50cb69482f18 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:48:46 +0800 Subject: [PATCH 48/85] chore: conf docs --- src/.env.example | 102 +++++++++++--------------------------- src/openagent/conf/env.py | 32 ++++++------ 2 files changed, 47 insertions(+), 87 deletions(-) diff --git a/src/.env.example b/src/.env.example index a8acc0b2..8f4af4d4 100644 --- a/src/.env.example +++ b/src/.env.example @@ -1,83 +1,39 @@ -# Usage: Copy this file to .env and fill in the values -## If [optional] values are not proivded, corresponding executors will not be available. + # Database settings + DB_CONNECTION=your_database_connection_string_here -##################### -# Basic configuration + # LLM provider settings (at least one required) + # To get a Google Cloud Vertex project ID, visit: https://console.cloud.google.com/vertex-ai + VERTEX_PROJECT_ID=your_google_cloud_vertex_project_id -## Current environment, either "dev" or "prod" -ENV=dev + # To get an OpenAI API key, sign up at: https://platform.openai.com/signup + OPENAI_API_KEY=your_openai_api_key -## Model name, required. + # To get a Google Gemini API key, visit: https://makersuite.google.com/app/apikey + GOOGLE_GEMINI_API_KEY=your_google_gemini_api_key -## If using OpenAI -## We recommend using "gpt-4o" or "gpt-4o-mini" for an improved performance. -## Refer to https://platform.openai.com. -## OpenAI API key, required for using OpenAI. -## OPENAI_API_KEY=... + # For Ollama, download and install from: https://github.com/ollama/ollama + OLLAMA_HOST=http://your_ollama_host:port -## If using Google Gemini -### We recommend using "gemini-1.5-pro" or "gemini-1.5-flash" for an improved performance. -### Refer to https://ai.google.dev. -## Google Gemini API key, required for using Google Gemini. -## GOOGLE_GEMINI_API_KEY=... + # Optional API keys for additional features + # Sign up for NFTScan API key at: https://developer.nftscan.com/ + NFTSCAN_API_KEY=your_nftscan_api_key -## If using Google Vertex AI -### We recommend using "gemini-1.5-pro" or "gemini-1.5-flash" for an improved performance. -### Refer to https://cloud.google.com/vertex-ai/docs/reference. -## Google Cloud VertexAI project ID, required for using Google Vertex AI. -## GOOGLE_CLOUD_PROJECT_ID=... + # Get your Covalent API key at: https://www.covalenthq.com/platform/auth/register/ + COVALENT_API_KEY=your_covalent_api_key -## For local LLM, see compatible models: https://docs.rss3.io/guide/artificial-intelligence/openagent/compatible-models. -## Other models are not tested and may not work as expected. -MODEL_NAME=llama3 + # Register for a RootData API key at: https://www.rootdata.com/ + ROOTDATA_API_KEY=your_rootdata_api_key -## API base for outgoing requests to the LLM. -### When using proprietary APIs, refer to their docs for the correct API base. -### When using open source models hosted locally, we use Ollama as the wrapper, -### you don't have to change this value, unless you know what you are doing. -LLM_API_BASE=http://ollama:11434 + # Sign up for a CoinGecko API key at: https://www.coingecko.com/en/api/pricing + COINGECKO_API_KEY=your_coingecko_api_key -## A database is required for vector and user management. -## Database connection string -DB_CONNECTION=postgresql+psycopg://postgres:password@vector_db:5432/openagent + # RSS3 API URLs (default values provided, change if needed) + RSS3_DATA_API=https://gi.rss3.io + RSS3_SEARCH_API=https://devnet.rss3.io/search -# End of basic configuration -############################ - -######################### -# Executors configuration - -## [required] RSS3 Data API server endpoint, required for retrieving data from RSS3 network -### See https://docs.rss3.io/api-reference#tag/dsl -RSS3_DATA_API=https://gi.rss3.io -## [required] RSS3 Search API server endpoint, required for searching data on RSS3 network -RSS3_SEARCH_API=https://devnet.rss3.io/search -## [required] RSS3 API key, required for both APIs above -RSS3_API_KEY=... - -## [optional] Google Search Engine API key, required for Search executor. -### See https://serpapi.com -SERPAPI_API_KEY=... - -# #[optional] NFTSCAN API key, required for NFT executor. -## See https://developer.nftscan.com -NFTSCAN_API_KEY=... - -# End of Executors configuration -################################ - -######################## -# Chainlit configuration - -## [optional] OAuth configuration for AUTH0. -### So users can login via social accounts. -### See https://docs.chainlit.io/authentication/oauth. -### For demostartion purposes, we use Google as the provider. -### See https://developers.google.com/identity/protocols/oauth2. -OAUTH_AUTH0_CLIENT_ID=... -OAUTH_AUTH0_CLIENT_SECRET=... -OAUTH_AUTH0_DOMAIN=... -CHAINLIT_AUTH_SECRET=... - -# End of Chainlit configuration -############################### + # Chainlit OAuth settings (all fields must be set if using OAuth, otherwise leave them empty) + # For Auth0 setup, visit: https://docs.chainlit.io/authentication/oauth + CHAINLIT_AUTH_SECRET=your_chainlit_auth_secret + OAUTH_AUTH0_CLIENT_ID=your_oauth_auth0_client_id + OAUTH_AUTH0_CLIENT_SECRET=your_oauth_auth0_client_secret + OAUTH_AUTH0_DOMAIN=your_oauth_auth0_domain \ No newline at end of file diff --git a/src/openagent/conf/env.py b/src/openagent/conf/env.py index a03abbe7..c5790ac6 100644 --- a/src/openagent/conf/env.py +++ b/src/openagent/conf/env.py @@ -1,5 +1,4 @@ from typing import Optional - from dotenv import load_dotenv from pydantic import Field from pydantic_settings import BaseSettings @@ -8,22 +7,27 @@ class Settings(BaseSettings): - # Database connection string (required) - DB_CONNECTION: str = Field(..., description="Database connection string (required)") + DB_CONNECTION: str = Field(..., description="Database connection string") - # LLM provider settings: at least one provider must be set - VERTEX_PROJECT_ID: Optional[str] = Field(default=None, description="Google Cloud Vertex project ID (optional)") - OPENAI_API_KEY: Optional[str] = Field(default=None, description="OpenAI API Key (optional)") - GOOGLE_GEMINI_API_KEY: Optional[str] = Field(default=None, description="Google Gemini API Key (optional)") - OLLAMA_HOST: Optional[str] = Field(default=None, description="OLLAMA API Base URL (optional)") + # LLM provider settings (at least one required) + VERTEX_PROJECT_ID: Optional[str] = Field(default=None, + description="Google Cloud Vertex project ID. Info: https://cloud.google.com/vertex-ai/docs/reference") + OPENAI_API_KEY: Optional[str] = Field(default=None, description="OpenAI API Key. Info: https://platform.openai.com") + GOOGLE_GEMINI_API_KEY: Optional[str] = Field(default=None, + description="Google Gemini API Key. Info: https://ai.google.dev") + OLLAMA_HOST: Optional[str] = Field(default=None, + description="OLLAMA API Base URL. Info: https://github.com/ollama/ollama") # API keys for various tools; some features will be disabled if not set - NFTSCAN_API_KEY: Optional[str] = Field(default=None, description="NFTScan API Key (optional)") - COVALENT_API_KEY: Optional[str] = Field(default=None, description="Covalent API Key (optional)") - ROOTDATA_API_KEY: Optional[str] = Field(default=None, description="RootData API Key (optional)") - COINGECKO_API_KEY: Optional[str] = Field(default=None, description="CoinGecko API Key (optional)") - RSS3_DATA_API: str = Field(default="https://gi.rss3.io", description="RSS3 Data API URL (optional)") - RSS3_SEARCH_API: str = Field(default="https://devnet.rss3.io/search", description="RSS3 Search API URL (optional)") + NFTSCAN_API_KEY: Optional[str] = Field(default=None, description="NFTScan API Key. Info: https://nftscan.com/") + COVALENT_API_KEY: Optional[str] = Field(default=None, + description="Covalent API Key. Info: https://goldrush.dev/docs/api/") + ROOTDATA_API_KEY: Optional[str] = Field(default=None, + description="RootData API Key. Info: https://www.rootdata.com/") + COINGECKO_API_KEY: Optional[str] = Field(default=None, + description="CoinGecko API Key. Info: https://www.coingecko.com/en/api/pricing") + RSS3_DATA_API: str = Field(default="https://gi.rss3.io", description="RSS3 Data API URL") + RSS3_SEARCH_API: str = Field(default="https://devnet.rss3.io/search", description="RSS3 Search API URL") # Chainlit OAuth settings; either all fields are None or all are set CHAINLIT_AUTH_SECRET: Optional[str] = Field(default=None, description="Chainlit Auth Secret") From 789a6aa4c1cc2d905e66ad7ef237d29b8eefec81 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:49:21 +0800 Subject: [PATCH 49/85] chore: remove useless conf --- src/.env.example | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/.env.example b/src/.env.example index 8f4af4d4..90f21d0b 100644 --- a/src/.env.example +++ b/src/.env.example @@ -33,7 +33,7 @@ # Chainlit OAuth settings (all fields must be set if using OAuth, otherwise leave them empty) # For Auth0 setup, visit: https://docs.chainlit.io/authentication/oauth - CHAINLIT_AUTH_SECRET=your_chainlit_auth_secret - OAUTH_AUTH0_CLIENT_ID=your_oauth_auth0_client_id - OAUTH_AUTH0_CLIENT_SECRET=your_oauth_auth0_client_secret - OAUTH_AUTH0_DOMAIN=your_oauth_auth0_domain \ No newline at end of file + CHAINLIT_AUTH_SECRET= + OAUTH_AUTH0_CLIENT_ID= + OAUTH_AUTH0_CLIENT_SECRET= + OAUTH_AUTH0_DOMAIN= \ No newline at end of file From 7963b7fc769164baa5440e736ffa34305f4d02c1 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 15:50:48 +0800 Subject: [PATCH 50/85] fix: gemini url --- src/.env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/.env.example b/src/.env.example index 90f21d0b..23e0c2cd 100644 --- a/src/.env.example +++ b/src/.env.example @@ -8,7 +8,7 @@ # To get an OpenAI API key, sign up at: https://platform.openai.com/signup OPENAI_API_KEY=your_openai_api_key - # To get a Google Gemini API key, visit: https://makersuite.google.com/app/apikey + # To get a Google Gemini API key, visit: https://ai.google.dev GOOGLE_GEMINI_API_KEY=your_google_gemini_api_key # For Ollama, download and install from: https://github.com/ollama/ollama From 794f64bfb5bc86de677d1ac42fa13aa6f8651c76 Mon Sep 17 00:00:00 2001 From: Thomas Date: Thu, 1 Aug 2024 16:02:16 +0800 Subject: [PATCH 51/85] fix: text wrap --- src/.chainlit/config.toml | 2 +- src/public/{test.css => index.css} | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) rename src/public/{test.css => index.css} (58%) diff --git a/src/.chainlit/config.toml b/src/.chainlit/config.toml index d398a5f4..1ab7e81c 100644 --- a/src/.chainlit/config.toml +++ b/src/.chainlit/config.toml @@ -68,7 +68,7 @@ hide_cot = false # Specify a CSS file that can be used to customize the user interface. # The CSS file can be served from the public directory or via an external link. # custom_css = "/public/test.css" -custom_css = "/public/test.css" +custom_css = "/public/index.css" # Specify a Javascript file that can be used to customize the user interface. # The Javascript file can be served from the public directory. diff --git a/src/public/test.css b/src/public/index.css similarity index 58% rename from src/public/test.css rename to src/public/index.css index 9bcfae24..ce8e483c 100644 --- a/src/public/test.css +++ b/src/public/index.css @@ -6,3 +6,7 @@ iframe { div.MuiBox-root > div.MuiBox-root > div.MuiStack-root.watermark { display: none; } + +div.MuiStack-root.message-content .markdown-body { + overflow-wrap: break-word !important; +} From 28d9317a47ee12091bfdc18322761e97f5781835 Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 16:59:20 +0800 Subject: [PATCH 52/85] feat(src): implemented a embedded transfer widget as a React component using wagmi and rainbowkit --- src/widget/src/App.tsx | 48 ++++-- .../src/components/TransferWidget.module.css | 123 +++++++++++++++ src/widget/src/components/TransferWidget.tsx | 149 ++++++++++++++++++ src/widget/src/main.tsx | 9 +- 4 files changed, 316 insertions(+), 13 deletions(-) create mode 100644 src/widget/src/components/TransferWidget.module.css create mode 100644 src/widget/src/components/TransferWidget.tsx diff --git a/src/widget/src/App.tsx b/src/widget/src/App.tsx index 030cf439..e947272d 100644 --- a/src/widget/src/App.tsx +++ b/src/widget/src/App.tsx @@ -1,15 +1,11 @@ -/* eslint-disable no-console */ +import React from 'react'; +import '@rainbow-me/rainbowkit/styles.css'; +import { RainbowKitProvider, getDefaultConfig } from '@rainbow-me/rainbowkit'; +import { WagmiProvider } from 'wagmi'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { mainnet, polygon, optimism, arbitrum } from 'wagmi/chains'; -function getQueryParams() { - const params = new URLSearchParams(window.location.search); - return { - fromAmount: params.get('fromAmount') || 11, - fromChain: params.get('fromChain') || 1, - fromToken: params.get('fromToken') || 'eth', - toChain: params.get('toChain') || 1, - toToken: params.get('toToken') || 'weth', - }; -} +/* eslint-disable no-console */ export function App() { @@ -17,3 +13,33 @@ export function App() {

hello world

} + +// Configuration for RainbowKit +const config = getDefaultConfig({ + appName: 'My RainbowKit App', + projectId: 'No_ID', + chains: [mainnet, polygon, optimism, arbitrum], + ssr: true, +}); + +// Create a new QueryClient instance for React Query +const queryClient = new QueryClient(); + +/** + * TransferWidgetApp component. + * Wraps children with necessary providers for Wagmi, React Query, and RainbowKit. + * + * @param {Object} props - The component props + * @param {React.ReactNode} props.children - The child components to be wrapped + */ +export function TransferWidgetApp({ children }: { children: React.ReactNode }) { + return ( + + + + {children} + + + + ); +} \ No newline at end of file diff --git a/src/widget/src/components/TransferWidget.module.css b/src/widget/src/components/TransferWidget.module.css new file mode 100644 index 00000000..5fe8bcfd --- /dev/null +++ b/src/widget/src/components/TransferWidget.module.css @@ -0,0 +1,123 @@ +.transferWidget { + max-width: 400px; + margin: auto; + border: 1px solid #ccc; + border-radius: 10px; + padding: 20px; + font-family: Arial, sans-serif; + background-color: #fff; /* Ensure the background is white */ + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Add subtle shadow for better appearance */ +} + +.title { + text-align: center; +} + +.accountInfo, +.assetInfo, +.amountInfo, +.addressInfo, +.gasFeeInfo { + margin-bottom: 15px; +} + +.accountInfo p { + margin: 0; + font-size: 14px; + color: #666; +} + +.assetInfo { + display: flex; + align-items: center; +} + +.assetInfo label, +.amountInfo label, +.addressInfo label { + display: block; + margin-bottom: 5px; + font-weight: bold; +} + +.assetDetails { + display: flex; + align-items: center; + margin-left: 10px; +} + +.assetIcon { + font-size: 24px; + margin-right: 10px; +} + +.balance { + margin-left: auto; + color: #666; +} + +.amountInfo input, +.addressInfo input { + width: 100%; + padding: 8px; + border: 1px solid #ccc; + border-radius: 5px; + font-size: 14px; +} + +.gasFeeInfo p { + margin: 5px 0; + font-size: 12px; + color: #666; +} +.buttonGroup { + display: flex; + justify-content: space-between; + margin-top: 15px; +} + +.connectButton, +.transferButton { + width: 48%; + padding: 10px 20px; + font-size: 14px; + border: none; + border-radius: 5px; + cursor: pointer; +} + +.connectButton { + width: 60%; + padding: 10px 20px; + font-size: 14px; + border: none; + border-radius: 5px; + cursor: pointer; + background-color: #007bff; + color: white; +} + +.transferButton { + background-color: #28a745; + color: white; +} + +.connectButton:hover, +.transferButton:hover { + opacity: 0.8; +} + +.status { + margin-top: 15px; + font-size: 12px; + color: #666; + text-align: center; +} + +.transactionInfo, +.error { + font-size: 12px; + color: #666; + text-align: center; + margin-top: 10px; +} \ No newline at end of file diff --git a/src/widget/src/components/TransferWidget.tsx b/src/widget/src/components/TransferWidget.tsx new file mode 100644 index 00000000..e8f6d448 --- /dev/null +++ b/src/widget/src/components/TransferWidget.tsx @@ -0,0 +1,149 @@ +import React, { useState, useEffect } from 'react'; +import { ConnectButton } from '@rainbow-me/rainbowkit'; +import { + useSendTransaction, + useWaitForTransactionReceipt, + useAccount, + useBalance, + useConfig, + type BaseError +} from 'wagmi'; +import { parseUnits } from 'viem'; +import styles from './TransferWidget.module.css'; + +// Define the prop types for the TransferWidget component +interface TransferWidgetProps { + token: string; + amount: string; + toAddress: string; + chainName: string; +} + +/** + * TransferWidgetComponent - A component for handling cryptocurrency transfers. + */ +const TransferWidgetComponent: React.FC = ({ + token, + amount: initialAmount, + toAddress: initialToAddress, + chainName +}) => { + const [currentAmount, setCurrentAmount] = useState(initialAmount); + const [currentToAddress, setCurrentToAddress] = useState(initialToAddress); + const [account, setAccount] = useState(null); + const [status, setStatus] = useState(''); + const { address } = useAccount(); + const config = useConfig(); + const { data: balance } = useBalance({ address, token: token as `0x${string}` }); + + const { + data: hash, + error, + isPending, + sendTransaction + } = useSendTransaction(); + + const { + isLoading: isConfirming, + isSuccess: isConfirmed + } = useWaitForTransactionReceipt({ hash }); + + useEffect(() => { + if (address) { + setAccount(address); + } + }, [address]); + + /** + * Handle form submission for the transfer. + */ + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (account) { + sendTransaction({ + to: currentToAddress as `0x${string}`, + value: parseUnits(currentAmount, balance?.decimals || 18), + }); + } else { + setStatus('Wallet is not connected'); + } + }; + + + // Render the component + return ( +
+

Send

+
+

Account 1

+

{account || 'Not connected'}

+
+
+ +
+ {token} + Balance: {balance?.formatted || 0} {token} +
+
+
+ + setCurrentAmount(e.target.value)} + placeholder="Enter amount" + /> +
+
+ + setCurrentToAddress(e.target.value)} + placeholder="Enter recipient address" + /> +
+
+

Estimated gas fee

+

0 Gwei

+

Max fee: 0 ETH

+
+
+ + +
+
{status}
+ {hash &&
Transaction Hash: {hash}
} + {isConfirming &&
Waiting for confirmation...
} + {isConfirmed &&
Transaction confirmed.
} + {error && ( +
Error: {(error as BaseError).shortMessage || error.message}
+ )} +
+ ); +}; + +/** + * TransferWidget - Wrapper component that parses URL parameters and renders TransferWidgetComponent. + */ +export function TransferWidget() { + const params = new URLSearchParams(window.location.search); + const token = params.get('token') || ''; + const amount = params.get('amount') || ''; + const toAddress = params.get('toAddress') || ''; + const chainName = params.get('chainName') || 'Ethereum'; + + // @ts-ignore + return ( + + ); +} + +export default TransferWidget; \ No newline at end of file diff --git a/src/widget/src/main.tsx b/src/widget/src/main.tsx index 6929c26c..79a702f7 100644 --- a/src/widget/src/main.tsx +++ b/src/widget/src/main.tsx @@ -1,10 +1,10 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import {App} from './App'; +import {App, TransferWidgetApp} from './App'; import {BrowserRouter as Router, Route, Routes} from "react-router-dom"; import {Swap} from "./components/Swap"; import {PriceChart} from "./components/PriceChart"; - +import TransferWidget from "./components/TransferWidget"; ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( @@ -15,6 +15,11 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( }/> }/> }/> + + + + } /> From 3125818a5262bb09ced5a16a99d6cba68a3ca2f5 Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 17:00:49 +0800 Subject: [PATCH 53/85] feat(src): added two new experts for retrieving activities from a particular source and retrieving DeFi activities --- src/openagent/agent/system_prompt.py | 107 +++++++++++++++ src/openagent/agents/asset_management.py | 4 +- src/openagent/agents/block_explore.py | 10 +- src/openagent/experts/defi_expert.py | 92 +++++++++++++ src/openagent/experts/feed_expert.py | 24 ++++ src/openagent/experts/feed_source_expert.py | 144 ++++++++++++++++++++ 6 files changed, 378 insertions(+), 3 deletions(-) create mode 100644 src/openagent/agent/system_prompt.py create mode 100644 src/openagent/experts/defi_expert.py create mode 100644 src/openagent/experts/feed_source_expert.py diff --git a/src/openagent/agent/system_prompt.py b/src/openagent/agent/system_prompt.py new file mode 100644 index 00000000..3119a076 --- /dev/null +++ b/src/openagent/agent/system_prompt.py @@ -0,0 +1,107 @@ +# Description: This file contains the system prompt, which is loaded at the beginning of each conversation. +SYSTEM_PROMPT = """Your designated name is OpenAgent, developed by RSS3.io. \ +You possess proficiency in all matters related to web3. + +You can providing answers to questions and help users to trade or transfer tokens. + +Your answer should be detailed and include puns or jokes where possible \ +And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. + +If you don't know the answer to the question, \ +you can ask the user to rephrase the question or ask for more information. + +When use transfer or swap tool, you should ask the user to edit or confirm the transaction, \ +and don't show the transaction link to the user. + +Return format: +You are committed to providing responses in markdown format for enhanced readability. +""" + +SYSTEM_PROMPT_V2 = """ +You are OpenAgent, an advanced AI assistant developed by RSS3.io, specializing in all matters related to web3. You possess the ability to call functions and use self-recursion, enhancing your problem-solving capabilities. + +Key Characteristics and Abilities: +1. Web3 Expertise: You are proficient in blockchain technology, cryptocurrencies, DeFi, NFTs, and all aspects of the web3 ecosystem. + +2. Function Calling: You can call functions to perform tasks or retrieve information. Always wait for function results before proceeding with your response. + +3. Self-Recursion: Utilize agentic frameworks for reasoning and planning to address complex queries effectively. + +4. Response Style: + - Provide detailed answers in markdown format for enhanced readability. + - Maintain a lively, enthusiastic, and energetic tone. + - Include puns, jokes, or emojis where appropriate to keep the conversation engaging. + +5. Problem-Solving Approach: + - Analyze function results thoroughly before deciding on next steps. + - Call additional functions if needed to gather more information or perform actions. + - Don't make assumptions about function input values; ask for clarification if necessary. + +6. Handling Uncertainty: + - If you don't know the answer, use google search in search expert tool to find relevant information. + +7. User Interaction: + - Guide users through complex processes step-by-step. + - Offer explanations of web3 concepts when relevant to the conversation. + - Be patient and willing to clarify or elaborate on any point. + +Remember, your goal is to assist users with their web3-related queries and tasks while providing an informative and enjoyable interaction experience. +""" + +FEED_PROMPT = """ +Here are the raw activities: + +{activities_data} + +- Before answering, please first summarize how many actions the above activities have been carried out. +- Display the key information in each operation, such as time, author, specific content, etc., and display this information in a markdown list format. +- Finally, give a specific answer to the question. +""" + + +custom_agent_kwargs = { + "prefix": """ +Your designated name is RSS3 OpenAgent, developed by RSS3, \ +you have the capability to call upon tools to aid in answering questions about web3. +Assistants may prompt the user to employ specific tools to gather information that might be helpful in addressing the user's initial question. +Here are tools' schemas: + """, + "format_instructions": r""" +When responding, you must exclusively use one of the following two formats: + +**Option 1:** +If you're suggesting that the user utilizes a tool, format your response as a markdown code snippet according to this schema: +```json +{{{{ + "action": string, // The action to be taken. Must be one of {tool_names} + "action_input": dict // The parameters for the action. MUST be a dict object +}}}} +``` +e.g. +```json +{{{{ + "action": "search", + "action_input": {{{{ + "query": "price of ETH", + "search_type": "google", + }}}} +}}}} +``` + +**Option 2:** +If you observable the tool's results, or you're providing a direct final response to the user, format your response as a markdown code snippet following this schema: + +```json +{{{{ + "action": "Final Answer", // MUST be literal string "Final Answer", other forms are not acceptable + "action_input": string // This should contain your response to the user, in human-readable language +}}}} +``` +""", + "suffix": """ +YOU MUST FOLLOW THESE INSTRUCTIONS CAREFULLY. +1. To respond to the users message, you can use only one tool at a time. +2. When using a tool, only respond with the tool call. Nothing else. Do not add any additional notes, explanations or white space. Never escape with a backslash. +3. REMEMBER to respond with a markdown code snippet of a json blob with a single action, and nothing else. +""", +} \ No newline at end of file diff --git a/src/openagent/agents/asset_management.py b/src/openagent/agents/asset_management.py index 55ec1fef..a95ec5df 100644 --- a/src/openagent/agents/asset_management.py +++ b/src/openagent/agents/asset_management.py @@ -3,6 +3,7 @@ from openagent.agents.agent_factory import create_agent from openagent.conf.llm_provider import get_current_llm from openagent.experts.swap_expert import SwapExpert +from openagent.experts.transfer_expert import TransferExpert from openagent.tools.nft_balance_tool import NFTBalanceTool from openagent.tools.token_balance_tool import TokenBalanceTool @@ -10,13 +11,14 @@ asset_management_agent = create_agent( get_current_llm(), - [TokenBalanceTool(), NFTBalanceTool(), SwapExpert()], + [TokenBalanceTool(), NFTBalanceTool(), SwapExpert(), TransferExpert()], """ You are AssetManager, an AI assistant for crypto asset management. Your responsibilities include: 1. Query and report on users' token balances 2. Check and inform about users' NFT holdings 3. Generate cross-chain swap widgets for users +4. Generate transfer widgets for users When interacting with users: - Provide accurate and detailed information diff --git a/src/openagent/agents/block_explore.py b/src/openagent/agents/block_explore.py index c12bce2b..be05833c 100644 --- a/src/openagent/agents/block_explore.py +++ b/src/openagent/agents/block_explore.py @@ -1,20 +1,26 @@ from dotenv import load_dotenv - from openagent.agents.agent_factory import create_agent from openagent.conf.llm_provider import get_current_llm from openagent.tools.block_stat_tool import BlockStatTool from openagent.tools.tavily_tool import tavily_tool +from openagent.experts.defi_expert import DeFiExpert +from openagent.experts.feed_expert import FeedExpert +from openagent.experts.feed_source_expert import FeedSourceExpert load_dotenv() block_explorer_agent = create_agent( get_current_llm(), - [BlockStatTool(), tavily_tool], + [BlockStatTool(), tavily_tool, FeedExpert(),FeedSourceExpert(), DeFiExpert()], """ You are BlockExplorer, dedicated to exploring and presenting detailed blockchain information. Help users query transaction details, block data, gas fees, block height, and other blockchain-related information. Use the available tools to gather and display accurate blockchain data. +In addition to blockchain data, leverage the FeedExpert to provide insights on various feeds, the FeedSourceExpert +to retrieve activities based on different sources, and the DeFiExpert to give detailed information on DeFi activities. + + Your answer should be detailed and include puns or jokes where possible \ And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. """.strip(), diff --git a/src/openagent/experts/defi_expert.py b/src/openagent/experts/defi_expert.py new file mode 100644 index 00000000..a5cd41ef --- /dev/null +++ b/src/openagent/experts/defi_expert.py @@ -0,0 +1,92 @@ +from typing import Optional, Type + +from langchain.callbacks.manager import AsyncCallbackManagerForToolRun +from langchain.tools import BaseTool +from loguru import logger +from pydantic import BaseModel, Field +from rss3_dsl_sdk.client import RSS3Client +from rss3_dsl_sdk.schemas.base import ActivityFilter, PaginationOptions +from openagent.agent.system_prompt import FEED_PROMPT + +# Define the defi activities and common DeFi networks +SUPPORTED_NETWORKS = ["arbitrum", "avax", "base", "binance-smart-chain", "ethereum", "gnosis", "linea", "optimism", "polygon"] +DEFI_ACTIVITIES = ["swap", "liquidity", "staking"] + +# Define the schema for input parameters +class ParamSchema(BaseModel): + """ + Defines the schema for input parameters of the DeFiExpert tool. + """ + address: str = Field(description="Wallet address or blockchain domain name (e.g., vitalik.eth)") + activity_type: str = Field(description=f"Type of DeFi activity. Supported types: {', '.join(DEFI_ACTIVITIES)}") + network: Optional[str] = Field(default=None, description=f"Network for activities. Supported: {', '.join(SUPPORTED_NETWORKS)}") + +class DeFiExpert(BaseTool): + """ + A tool for fetching and analyzing DeFi activities across various networks. + """ + name = "DeFiExecutor" + description = "Use this tool to get the user's DeFi activities (swaps, liquidity provision, staking) across various networks." + args_schema: Type[ParamSchema] = ParamSchema + + async def _run( + self, + address: str, + activity_type: str, + network: Optional[str] = None, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: + raise NotImplementedError + + async def _arun( + self, + address: str, + activity_type: str, + network: Optional[str] = None + ) -> str: + """ + Asynchronously run the DeFi activity fetching process. + + :param address: The wallet address to fetch activities for + :param activity_type: The type of DeFi activity to fetch, now supports "swap", "liquidity", "staking" + :param network: network to filter activities (OPTIONAL) + :return: A string containing the fetched DeFi activities or an error message + """ + return await self.fetch_defi_feeds(address, network, activity_type) + + async def fetch_defi_feeds(self, address: str, network: Optional[str] = None, activity_type: Optional[str] = None): + """ + Fetch DeFi feed activities for a given address, optionally filtered by network and activity type. + + :param address: The wallet address to fetch activities for + :param network: network to filter activities (Optional) + :param activity_type: The type of DeFi activity to fetch + :return: A string containing the fetched DeFi activities or an error message + """ + # Validate activity type + if activity_type.lower() not in DEFI_ACTIVITIES: + return f"Error: Unsupported activity type '{activity_type}'. Choose from: {', '.join(DEFI_ACTIVITIES)}" + + # Validate network if provided + if network and network.lower() not in map(str.lower, SUPPORTED_NETWORKS): + return f"Error: Unsupported network '{network}'. Choose from: {', '.join(SUPPORTED_NETWORKS)}" + + try: + client = RSS3Client() + filters = ActivityFilter(network=[network] if network else None) + pagination = PaginationOptions(limit=10, action_limit=10) + + # Dynamically select the appropriate fetch method in the SDK based on activity type + fetch_method = getattr(client, f"fetch_exchange_{activity_type.lower()}_activities") + activities = fetch_method(account=address, filters=filters, pagination=pagination) + + # Check if any activities were found + if not activities.data: + return f"No {activity_type} activities found for {address}{' on ' + network if network else ''}." + + result = FEED_PROMPT.format(activities_data=activities.dict(), activity_type=activity_type) + return result + + except Exception as e: + logger.error(f"Error fetching DeFi activities: {e}") + return f"Error: Unable to fetch data. {e}" \ No newline at end of file diff --git a/src/openagent/experts/feed_expert.py b/src/openagent/experts/feed_expert.py index eecf88d1..aa9ba424 100644 --- a/src/openagent/experts/feed_expert.py +++ b/src/openagent/experts/feed_expert.py @@ -14,6 +14,9 @@ class ParamSchema(BaseModel): + """ + Defines the schema for input parameters of the FeedExpert tool. + """ address: str = Field( description="""wallet address or blockchain domain name,\ hint: vitalik's address is vitalik.eth""" @@ -26,6 +29,10 @@ class ParamSchema(BaseModel): class FeedExpert(BaseTool): + """ + A tool for fetching and analyzing blockchain activities for a given address. + """ + name = "FeedExecutor" description = """Use this tool to get the activities of a wallet address or \ blockchain domain name and know what this address has done or doing recently.""" @@ -45,10 +52,27 @@ async def _arun( type: str, run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): + """ + Asynchronously run the feed fetching process. + + :param address: The wallet address to fetch activities for + :param type: The type of activities to fetch (all, post, comment, share) + :param run_manager: Optional callback manager for async operations + :return: A string containing the fetched activities or an error message + """ return await fetch_feeds(address, type) async def fetch_feeds(address: str, type: str): + """ + Fetch feed activities for a given address and activity type. + + :param address: The wallet address to fetch activities for + :param type: The type of activities to fetch (all, post, comment, share) + :return: A string containing the fetched activities formatted using FEED_PROMPT + """ + + # Construct the URL for the API request url = f"{settings.RSS3_DATA_API}/decentralized/{address}?limit=5&action_limit=10&tag=social" if type in ["post", "comment", "share"]: url += f"&type={type}" diff --git a/src/openagent/experts/feed_source_expert.py b/src/openagent/experts/feed_source_expert.py new file mode 100644 index 00000000..a37ca158 --- /dev/null +++ b/src/openagent/experts/feed_source_expert.py @@ -0,0 +1,144 @@ +from typing import Optional, Type + +from langchain.callbacks.manager import ( + CallbackManagerForToolRun, +) +from langchain.tools import BaseTool +from loguru import logger +from pydantic import BaseModel, Field +from rss3_dsl_sdk.client import RSS3Client +from rss3_dsl_sdk.schemas.base import ActivityFilter, PaginationOptions +from openagent.agent.system_prompt import FEED_PROMPT + + +# Define supported networks and platforms +SUPPORTED_NETWORKS = [ + "arbitrum", + "arweave", + "avax", + "base", + "binance-smart-chain", + "crossbell", + "ethereum", + "farcaster", + "gnosis", + "linea", + "optimism", + "polygon", + "vsl", +] + +ALLOWED_PLATFORMS = [ + "1inch", + "AAVE", + "Aavegotchi", + "Crossbell", + "Curve", + "ENS", + "Farcaster", + "Highlight", + "IQWiki", + "KiwiStand", + "Lens", + "Lido", + "LooksRare", + "Matters", + "Mirror", + "OpenSea", + "Optimism", + "Paragraph", + "RSS3", + "SAVM", + "Stargate", + "Uniswap", + "Unknown", + "VSL", +] + + +# Define the schema for input parameters +class ParamSchema(BaseModel): + address: str = Field( + description="""wallet address or blockchain domain name,\ +hint: vitalik's address is vitalik.eth""" + ) + + network: Optional[str] = Field( + default=None, + description=f"""Retrieve activities for the specified network. +Supported networks: {', '.join(SUPPORTED_NETWORKS)}""", + ) + + platform: Optional[str] = Field( + default=None, + description=f"""Retrieve activities for the specified platform. +Allowed platforms: {', '.join(ALLOWED_PLATFORMS)}""", + ) + +# Define the FeedSourceExpert tool +class FeedSourceExpert(BaseTool): + name = "FeedSourceExecutor" + description = """Use this tool to get the activities of a wallet address or \ +blockchain domain name based on specific network and/or platform, and know what this address \ +has done or is doing recently.""" + args_schema: Type[ParamSchema] = ParamSchema + + def _run( + self, + address: str, + network: Optional[str] = None, + platform: Optional[str] = None, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + raise NotImplementedError + + async def _arun( + self, + address: str, + network: Optional[str] = None, + platform: Optional[str] = None, + ): + """ + Asynchronously run the feed source fetching process. + + :param address: The wallet address to fetch activities for + :param network: network to filter activities (Optional) + :param platform: platform to filter activities (Optional) + :return: A string containing the fetched activities or an error message + """ + return await self.fetch_source_feeds(address, network, platform) + + async def fetch_source_feeds(self, address: str, network: Optional[str] = None, platform: Optional[str] = None): + """ + Fetch feed activities for a given address, optionally filtered by network and platform. + """ + filters = ActivityFilter() + pagination = PaginationOptions(limit=5, action_limit=10) + + # Validate and set network and platform filter if provided + if network: + if network.lower() not in [n.lower() for n in SUPPORTED_NETWORKS]: + return f"Error: Unsupported network '{network}'. Please choose from: {', '.join(SUPPORTED_NETWORKS)}" + filters.network = [network] + + if platform: + if platform.lower() not in [p.lower() for p in ALLOWED_PLATFORMS]: + return f"Error: Unsupported platform '{platform}'. Please choose from: {', '.join(ALLOWED_PLATFORMS)}" + filters.platform = [platform] + + try: + logger.info(f"Fetching activities for address: {address}, network: {network}, platform: {platform}") + + # Fetch activities using the RSS3 client + activities = RSS3Client().fetch_activities(account=address, tag=None, activity_type=None, pagination=filters, filters=pagination) + + # Check if any activities were found + if not activities.data: + return f"No activities found for the given address{' on ' + network if network else ''}{' and ' + platform if platform else ''}." + + result = FEED_PROMPT.format(activities_data=activities.dict()) + return result + + except Exception as e: + logger.error(f"Error fetching activities: {e!s}") + return f"Error: Unable to fetch data. {e!s}" \ No newline at end of file From a0fa709f566c09dff93a10273f6af88ffd1e3cca Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 17:01:28 +0800 Subject: [PATCH 54/85] feat(src): set the routing path to display transfer widget --- src/openagent/app.py | 4 ++- src/openagent/experts/transfer_expert.py | 35 ++++++++++++++++++++++-- src/openagent/ui/app.py | 16 +++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/openagent/app.py b/src/openagent/app.py index b2e759e4..043644c5 100644 --- a/src/openagent/app.py +++ b/src/openagent/app.py @@ -12,7 +12,6 @@ from starlette import status from starlette.responses import FileResponse, JSONResponse from starlette.staticfiles import StaticFiles - from openagent.workflows.workflow import build_workflow load_dotenv() @@ -41,6 +40,9 @@ async def swap_root(): async def chart_price_root(): return FileResponse(os.path.join("dist", "index.html")) +@app.get("/widget/transfer", include_in_schema=False) +async def transfer_root(): + return FileResponse(os.path.join("dist", "index.html")) class Input(BaseModel): text: str diff --git a/src/openagent/experts/transfer_expert.py b/src/openagent/experts/transfer_expert.py index 40081e8f..c3f3567e 100644 --- a/src/openagent/experts/transfer_expert.py +++ b/src/openagent/experts/transfer_expert.py @@ -16,12 +16,15 @@ class Transfer(BaseModel): token: str token_address: str chain_id: str + chain_name: str amount: str logoURI: str # noqa decimals: int - class ParamSchema(BaseModel): + """ + Defines the schema for input parameters of the TransferExpert tool. + """ to_address: str = Field( description="""extract the blockchain address mentioned in the query""", ) @@ -44,6 +47,9 @@ class ParamSchema(BaseModel): class TransferExpert(BaseTool): + """ + Tool for generating a transfer widget for cryptocurrency transfers. + """ name = "TransferExecutor" description = """Use this tool to send cryptocurrencies to another address.""" args_schema: Type[ParamSchema] = ParamSchema @@ -68,10 +74,31 @@ async def _arun( amount: str = "1", run_manager: Optional[AsyncCallbackManagerForToolRun] = None, ): + """ + Asynchronously run the transfer process. + + :param to_address: The recipient's blockchain address + :param token: The token symbol + :param chain_name: The blockchain name (default is "ethereum") + :param amount: The amount to transfer (default is "1") + :param run_manager: Optional callback manager for async operations + :return: JSON representation of the transfer details + """ + return await fetch_transfer(to_address, token, chain_name, amount) async def fetch_transfer(to_address: str, token: str, chain_name: str, amount: str): + """ + Fetch transfer details and prepare the Transfer object. + + :param to_address: The recipient's blockchain address + :param token: The token symbol + :param chain_name: The blockchain name + :param amount: The amount to transfer + :return: JSON representation of the Transfer object + """ + if not to_address.startswith("0x") and not to_address.endswith(".eth"): to_address += ".eth" chain_id = chain_name_to_id(chain_name) @@ -80,16 +107,20 @@ async def fetch_transfer(to_address: str, token: str, chain_name: str, amount: s "token": token, "amount": amount, } + + # Select the best token based on the provided token symbol and chain ID token_info = await select_best_token(token, chain_id) + # Create a Transfer object with all the necessary information transfer = Transfer( to_address=res.get("to_address", "1"), token=get_token_data_by_key(token_info, "symbol"), token_address=get_token_data_by_key(token_info, "address"), chain_id=chain_id, + chain_name=chain_name, amount=res.get("amount", "1"), logoURI=get_token_data_by_key(token_info, "logoURI"), decimals=get_token_data_by_key(token_info, "decimals"), ) - return transfer.model_dump_json() + return transfer.model_dump_json() \ No newline at end of file diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 9af3ef5d..06696fbc 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -137,6 +137,22 @@ async def handle_tool_end(event, msg): ) await msg.stream_token(widget) + if event["name"] == "TransferExecutor": + output = event["data"]["output"] + transfer_dict = json.loads(output) + token = transfer_dict["token"] + to_address = transfer_dict["to_address"] + amount = transfer_dict["amount"] + chain_name = transfer_dict.get("chain_name", "ethereum") + + url = f"/widget/transfer?token={token}" f"&amount={amount}&toAddress={to_address}&chainName={chain_name}" + + iframe_html = f""" + + """ + await msg.stream_token(iframe_html) + if event["name"] == "PriceExecutor": output = event["data"]["output"] price_dict = json.loads(output) From 6f63ad046cbba3b44bc5ea33d9a919e42ddc3455 Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 17:11:31 +0800 Subject: [PATCH 55/85] fix: seperate the feed tasks from block_explore.py and have them in feed_explore.py --- src/openagent/agents/block_explore.py | 12 +++-------- src/openagent/agents/feed_explore.py | 30 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 src/openagent/agents/feed_explore.py diff --git a/src/openagent/agents/block_explore.py b/src/openagent/agents/block_explore.py index be05833c..85e1d0bb 100644 --- a/src/openagent/agents/block_explore.py +++ b/src/openagent/agents/block_explore.py @@ -1,27 +1,21 @@ from dotenv import load_dotenv + from openagent.agents.agent_factory import create_agent from openagent.conf.llm_provider import get_current_llm from openagent.tools.block_stat_tool import BlockStatTool from openagent.tools.tavily_tool import tavily_tool -from openagent.experts.defi_expert import DeFiExpert -from openagent.experts.feed_expert import FeedExpert -from openagent.experts.feed_source_expert import FeedSourceExpert load_dotenv() block_explorer_agent = create_agent( get_current_llm(), - [BlockStatTool(), tavily_tool, FeedExpert(),FeedSourceExpert(), DeFiExpert()], + [BlockStatTool(), tavily_tool], """ You are BlockExplorer, dedicated to exploring and presenting detailed blockchain information. Help users query transaction details, block data, gas fees, block height, and other blockchain-related information. Use the available tools to gather and display accurate blockchain data. -In addition to blockchain data, leverage the FeedExpert to provide insights on various feeds, the FeedSourceExpert -to retrieve activities based on different sources, and the DeFiExpert to give detailed information on DeFi activities. - - Your answer should be detailed and include puns or jokes where possible \ And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. """.strip(), -) +) \ No newline at end of file diff --git a/src/openagent/agents/feed_explore.py b/src/openagent/agents/feed_explore.py new file mode 100644 index 00000000..c47075e2 --- /dev/null +++ b/src/openagent/agents/feed_explore.py @@ -0,0 +1,30 @@ + +from dotenv import load_dotenv + +from openagent.agents.agent_factory import create_agent +from openagent.conf.llm_provider import get_current_llm +from openagent.experts.feed_expert import FeedExpert +from openagent.experts.feed_source_expert import FeedSourceExpert +from openagent.experts.defi_expert import DeFiExpert + +load_dotenv() + +feed_explorer_agent = create_agent( + get_current_llm(), + [FeedExpert(), FeedSourceExpert(), DeFiExpert()], + """ +You are FeedExplorer, dedicated to exploring and presenting blockchain-related +activities and feeds. +Help users query various feeds, retrieve activities from different sources, and provide +insights on DeFi activities. + +Leverage the FeedExpert to provide insights on various feeds, the FeedSourceExpert +to retrieve activities based on different sources, and the DeFiExpert to give detailed +information on DeFi activities. + +Use the available tools to gather and display accurate feed and activity data. + +Your answer should be detailed and include puns or jokes where possible \ +And keep a lively, enthusiastic, and energetic tone, maybe include some emojis. +""".strip(), +) \ No newline at end of file From 0092fdbe7faa27c2dfaf0eb3292c66bd7c40a750 Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 17:11:56 +0800 Subject: [PATCH 56/85] fix: register the feed explore agent --- src/openagent/workflows/member.py | 1 + src/openagent/workflows/workflow.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/openagent/workflows/member.py b/src/openagent/workflows/member.py index af68fc83..9383c365 100644 --- a/src/openagent/workflows/member.py +++ b/src/openagent/workflows/member.py @@ -10,6 +10,7 @@ "market_analysis_agent", "asset_management_agent", "block_explorer_agent", + "feed_explorer_agent", "research_analyst_agent", "fallback_agent" ] diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py index 1a446c0e..8292d8ce 100644 --- a/src/openagent/workflows/workflow.py +++ b/src/openagent/workflows/workflow.py @@ -5,6 +5,8 @@ from langgraph.graph import END, StateGraph from loguru import logger +from src.openagent.agents.feed_explore import feed_explorer_agent + class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], operator.add] @@ -33,11 +35,13 @@ def build_workflow(): asset_management_agent_node = create_node(asset_management_agent, "asset_management_agent") block_explorer_agent_node = create_node(block_explorer_agent, "block_explorer_agent") research_analyst_agent_node = create_node(research_analyst_agent, "research_analyst_agent") + feed_explorer_agent_node = create_node(feed_explorer_agent, "feed_explorer_agent") workflow = StateGraph(AgentState) workflow.add_node("market_analysis_agent", market_analysis_agent_node) workflow.add_node("asset_management_agent", asset_management_agent_node) workflow.add_node("block_explorer_agent", block_explorer_agent_node) + workflow.add_node("feed_explorer_agent", feed_explorer_agent_node) workflow.add_node("research_analyst_agent", research_analyst_agent_node) workflow.add_node("supervisor", build_supervisor_chain()) workflow.add_node("fallback_agent", fallback) From 819f8078993d5e2e0770db5f607b6ac44165b87d Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 17:18:23 +0800 Subject: [PATCH 57/85] fix: register the feed explore agent in member.py --- src/openagent/workflows/member.py | 14 ++++++++++++++ src/openagent/workflows/workflow.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/openagent/workflows/member.py b/src/openagent/workflows/member.py index 9383c365..8285def1 100644 --- a/src/openagent/workflows/member.py +++ b/src/openagent/workflows/member.py @@ -3,6 +3,7 @@ MARKET_ANALYSIS: str = "market_analysis_agent" ASSET_MANAGEMENT = "asset_management_agent" BLOCK_EXPLORER = "block_explorer_agent" +FEED_EXPLORER = "feed_explorer_agent" RESEARCH_ANALYST = "research_analyst_agent" FALLBACK = "fallback_agent" @@ -55,6 +56,19 @@ Present technical information in an easy-to-understand manner, using analogies when helpful. """.strip(), }, + { + "name": FEED_EXPLORER, + "description": """ +FeedExplorer: Explores and presents blockchain-related activities and feeds. + +Responsibilities: +1. Query and analyze various blockchain-related feeds +2. Retrieve activities from different sources and platforms +3. Provide insights on DeFi activities across various chains + +Present feed and activity data in a clear, engaging manner, using emojis and blockchain-related puns when appropriate. + """.strip(), + }, { "name": RESEARCH_ANALYST, "description": """ diff --git a/src/openagent/workflows/workflow.py b/src/openagent/workflows/workflow.py index 8292d8ce..76914280 100644 --- a/src/openagent/workflows/workflow.py +++ b/src/openagent/workflows/workflow.py @@ -5,7 +5,7 @@ from langgraph.graph import END, StateGraph from loguru import logger -from src.openagent.agents.feed_explore import feed_explorer_agent +from openagent.agents.feed_explore import feed_explorer_agent class AgentState(TypedDict): From 40fd57699d8756d4f881b901c9cdbe8b2605339a Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 18:22:17 +0800 Subject: [PATCH 58/85] feat(src/tests): add specific and general test cases for feed_explore agent --- src/tests/agent_trajectory/feed_explore.py | 116 +++++++++++++++++++++ src/tests/supervisor_chain.py | 17 +++ 2 files changed, 133 insertions(+) create mode 100644 src/tests/agent_trajectory/feed_explore.py diff --git a/src/tests/agent_trajectory/feed_explore.py b/src/tests/agent_trajectory/feed_explore.py new file mode 100644 index 00000000..7264f1c1 --- /dev/null +++ b/src/tests/agent_trajectory/feed_explore.py @@ -0,0 +1,116 @@ +import asyncio +import unittest + +from langchain_core.messages import HumanMessage +from openagent.agents.feed_explore import feed_explorer_agent +from openagent.conf.llm_provider import set_current_llm + +class TestFeedExploreAgent(unittest.TestCase): + def setUp(self): + set_current_llm("gpt-3.5-turbo") + + def test_query_defi_activities(self): + """ + Test querying recent DeFi activities for a specific Ethereum address. + Validates that the response contains the correct address and is handled by the 'DeFiExecutor'. + """ + async def async_test(): + events = feed_explorer_agent.astream_events({"messages": [ + HumanMessage(content="Show me recent DeFi activities for address 0x742d35Cc6634C0532925a3b844Bc454e4438f44e", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'DeFiExecutor') + self.assertIn('address', event_data_input_) + self.assertEqual(event_data_input_['address'], '0x742d35Cc6634C0532925a3b844Bc454e4438f44e') + + asyncio.run(async_test()) + + def test_query_social_activities(self): + """ + Test querying recent social activities for a specific ENS name (vitalik.eth). + Validates that the response contains the correct address and is handled by the 'FeedExecutor'. + """ + async def async_test(): + events = feed_explorer_agent.astream_events({"messages": [ + HumanMessage(content="What are the recent activities for vitalik.eth?", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'FeedExecutor') + self.assertIn('address', event_data_input_) + self.assertEqual(event_data_input_['address'], 'vitalik.eth') + + asyncio.run(async_test()) + + def test_query_feed_source(self): + """ + Test querying the latest activities for a specific ENS name (vitalik.eth) from a specific platform (Uniswap) on a specific network (Ethereum). + Validates that the response contains the correct platform, network, and address and is handled by the 'FeedSourceExecutor'. + """ + async def async_test(): + events = feed_explorer_agent.astream_events({"messages": [ + HumanMessage(content="Show me the latest activities of vitalik.eth from Uniswap on Ethereum", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertEqual(event['name'], 'FeedSourceExecutor') + self.assertIn('platform', event_data_input_) + self.assertEqual(event_data_input_['platform'], 'Uniswap') + self.assertIn('network', event_data_input_) + self.assertEqual(event_data_input_['network'], 'ethereum') + self.assertIn('address', event_data_input_) + self.assertEqual(event_data_input_['address'], 'vitalik.eth') + + asyncio.run(async_test()) + + def test_query_unsupported_network(self): + """ + Test querying activities on an unsupported network (XYZ). + Validates that the response indicates the network is unsupported and mentions the network name (XYZ). + """ + async def async_test(): + events = feed_explorer_agent.astream_events({"messages": [ + HumanMessage(content="Show me activities on the XYZ network", name="human")]}, + version="v1") + + async for event in events: + if event['event'] == 'on_tool_end': + self.assertIn('output', event['data']) + self.assertIn('Unsupported network', event['data']['output']) + self.assertIn('XYZ', event['data']['output']) + + asyncio.run(async_test()) + + def test_query_multiple_addresses(self): + """ + Test querying and comparing activities for multiple addresses (vitalik.eth and a specific Ethereum address). + Validates that the response contains both addresses. + """ + async def async_test(): + events = feed_explorer_agent.astream_events({"messages": [ + HumanMessage(content="Compare activities of vitalik.eth and 0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + name="human")]}, + version="v1") + + addresses_checked = set() + async for event in events: + if event['event'] == 'on_tool_end': + event_data_input_ = event['data']['input'] + self.assertIn('address', event_data_input_) + addresses_checked.add(event_data_input_['address']) + + self.assertEqual(len(addresses_checked), 2) + self.assertIn('vitalik.eth', addresses_checked) + self.assertIn('0x742d35Cc6634C0532925a3b844Bc454e4438f44e', addresses_checked) + + asyncio.run(async_test()) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/src/tests/supervisor_chain.py b/src/tests/supervisor_chain.py index 4ac60449..8ed0cbdf 100644 --- a/src/tests/supervisor_chain.py +++ b/src/tests/supervisor_chain.py @@ -61,6 +61,23 @@ def test_multi_step_query(self): result = next_role(query) self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") + def test_feed_explorer(self): + query = "What are the recent DeFi activities for the address 0x742d35Cc6634C0532925a3b844Bc454e4438f44e?" + expected_role = "feed_explorer_agent" + result = next_role(query) + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") + + def test_feed_explorer_social(self): + query = "Show me the latest social interactions for vitalik.eth on Farcaster." + expected_role = "feed_explorer_agent" + result = next_role(query) + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") + + def test_feed_explorer_source(self): + query = "What are the most recent activities of vitalik.eth from the Uniswap on Ethereum?" + expected_role = "feed_explorer_agent" + result = next_role(query) + self.assertEqual(result, expected_role, f"Expected {expected_role}, but got {result} for query: {query}") if __name__ == "__main__": From d5478cf5fed9b9aebaf7c8c9a6c94f0bab70934e Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 18:27:56 +0800 Subject: [PATCH 59/85] fix: resolving merge conflict --- src/openagent/workflows/member.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/openagent/workflows/member.py b/src/openagent/workflows/member.py index 8285def1..3ee7f3aa 100644 --- a/src/openagent/workflows/member.py +++ b/src/openagent/workflows/member.py @@ -7,14 +7,7 @@ RESEARCH_ANALYST = "research_analyst_agent" FALLBACK = "fallback_agent" -AgentRole = Literal[ - "market_analysis_agent", - "asset_management_agent", - "block_explorer_agent", - "feed_explorer_agent", - "research_analyst_agent", - "fallback_agent" -] +AgentRole = Literal["market_analysis_agent", "asset_management_agent", "block_explorer_agent", "feed_explorer_agent", "research_analyst_agent", "fallback_agent"] members = [ { From 123da41ad481df146a45800a683e0a727013a4f1 Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Thu, 1 Aug 2024 18:47:53 +0800 Subject: [PATCH 60/85] fix: resolving missing dependencies --- src/widget/package.json | 7 +- src/widget/yarn.lock | 6239 +++++++++++++++++++++++++++++++++++---- 2 files changed, 5695 insertions(+), 551 deletions(-) diff --git a/src/widget/package.json b/src/widget/package.json index a0cc7955..268d7d52 100644 --- a/src/widget/package.json +++ b/src/widget/package.json @@ -1,8 +1,13 @@ { "dependencies": { + "@rainbow-me/rainbowkit": "^2.1.3", + "@tanstack/react-query": "^5.51.16", + "ethers": "^6.13.2", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" + "react-router-dom": "^6.24.1", + "viem": "^2.18.7", + "wagmi": "^2.12.2" }, "devDependencies": { "@types/events": "^3.0.3", diff --git a/src/widget/yarn.lock b/src/widget/yarn.lock index f8f9fe53..6c6c8a88 100644 --- a/src/widget/yarn.lock +++ b/src/widget/yarn.lock @@ -2,30 +2,36 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + "@ampproject/remapping@^2.2.0": version "2.3.0" - resolved "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + resolved "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz" integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.24.7": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + resolved "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz" integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: "@babel/highlight" "^7.24.7" picocolors "^1.0.0" -"@babel/compat-data@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed" - integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw== +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz" + integrity sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ== -"@babel/core@^7.24.5": +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.13.16", "@babel/core@^7.20.0", "@babel/core@^7.24.5", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/core/-/core-7.24.7.tgz#b676450141e0b52a3d43bc91da86aa608f950ac4" + resolved "https://registry.npmmirror.com/@babel/core/-/core-7.24.7.tgz" integrity sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g== dependencies: "@ampproject/remapping" "^2.2.0" @@ -44,106 +50,181 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d" - integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA== +"@babel/generator@^7.20.0", "@babel/generator@^7.24.7", "@babel/generator@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz" + integrity sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw== dependencies: - "@babel/types" "^7.24.7" + "@babel/types" "^7.25.0" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.24.7": +"@babel/helper-annotate-as-pure@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz#4eb6c4a80d6ffeac25ab8cd9a21b5dfa48d503a9" - integrity sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg== + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== dependencies: - "@babel/compat-data" "^7.24.7" - "@babel/helper-validator-option" "^7.24.7" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" + "@babel/types" "^7.24.7" -"@babel/helper-environment-visitor@^7.24.7": +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" - integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== dependencies: + "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" -"@babel/helper-function-name@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" - integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== +"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7", "@babel/helper-compilation-targets@^7.24.8", "@babel/helper-compilation-targets@^7.25.2": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz" + integrity sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw== dependencies: - "@babel/template" "^7.24.7" - "@babel/types" "^7.24.7" + "@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" -"@babel/helper-hoist-variables@^7.24.7": +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.24.7", "@babel/helper-create-class-features-plugin@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz" + integrity sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ== + 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" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7", "@babel/helper-create-regexp-features-plugin@^7.25.0": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz" + integrity sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== + 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" + +"@babel/helper-environment-visitor@^7.18.9": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" - integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== dependencies: "@babel/types" "^7.24.7" +"@babel/helper-member-expression-to-functions@^7.24.8": + version "7.24.8" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz" + integrity sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA== + dependencies: + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.8" + "@babel/helper-module-imports@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + resolved "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz" integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== dependencies: "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" -"@babel/helper-module-transforms@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz#31b6c9a2930679498db65b685b1698bfd6c7daf8" - integrity sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ== +"@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.0": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz" + integrity sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ== dependencies: - "@babel/helper-environment-visitor" "^7.24.7" "@babel/helper-module-imports" "^7.24.7" "@babel/helper-simple-access" "^7.24.7" - "@babel/helper-split-export-declaration" "^7.24.7" "@babel/helper-validator-identifier" "^7.24.7" + "@babel/traverse" "^7.25.2" -"@babel/helper-plugin-utils@^7.24.7": +"@babel/helper-optimise-call-expression@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz#98c84fe6fe3d0d3ae7bfc3a5e166a46844feb2a0" - integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg== + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.8" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + +"@babel/helper-remap-async-to-generator@^7.18.9", "@babel/helper-remap-async-to-generator@^7.24.7", "@babel/helper-remap-async-to-generator@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz" + integrity sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-wrap-function" "^7.25.0" + "@babel/traverse" "^7.25.0" + +"@babel/helper-replace-supers@^7.24.7", "@babel/helper-replace-supers@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz" + integrity sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/traverse" "^7.25.0" "@babel/helper-simple-access@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + resolved "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz" integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== dependencies: "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" -"@babel/helper-split-export-declaration@^7.24.7": +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" - integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== dependencies: + "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" -"@babel/helper-string-parser@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2" - integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg== +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== "@babel/helper-validator-identifier@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== -"@babel/helper-validator-option@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6" - integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw== +"@babel/helper-validator-option@^7.24.7", "@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + +"@babel/helper-wrap-function@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz" + integrity sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ== + dependencies: + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.0" + "@babel/types" "^7.25.0" "@babel/helpers@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.24.7.tgz#aa2ccda29f62185acb5d42fb4a3a1b1082107416" + resolved "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.24.7.tgz" integrity sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg== dependencies: "@babel/template" "^7.24.7" @@ -151,7 +232,7 @@ "@babel/highlight@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + resolved "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.24.7.tgz" integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== dependencies: "@babel/helper-validator-identifier" "^7.24.7" @@ -159,400 +240,2398 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" - integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== +"@babel/parser@^7.1.0", "@babel/parser@^7.13.16", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.7", "@babel/parser@^7.25.0", "@babel/parser@^7.25.3": + version "7.25.3" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz" + integrity sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw== + dependencies: + "@babel/types" "^7.25.2" -"@babel/plugin-transform-react-jsx-self@^7.24.5": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz#66bff0248ea0b549972e733516ffad577477bdab" - integrity sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.3": + version "7.25.3" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz" + integrity sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA== dependencies: - "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.3" + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz" + integrity sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz" + integrity sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" -"@babel/plugin-transform-react-jsx-source@^7.24.1": +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz#1198aab2548ad19582013815c938d3ebd8291ee3" - integrity sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ== + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== 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" -"@babel/template@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" - integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz" + integrity sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw== dependencies: - "@babel/code-frame" "^7.24.7" - "@babel/parser" "^7.24.7" - "@babel/types" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.0" -"@babel/traverse@^7.24.7": - version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5" - integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA== +"@babel/plugin-proposal-async-generator-functions@^7.0.0": + version "7.20.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz" + integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA== dependencies: - "@babel/code-frame" "^7.24.7" - "@babel/generator" "^7.24.7" - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-function-name" "^7.24.7" - "@babel/helper-hoist-variables" "^7.24.7" - "@babel/helper-split-export-declaration" "^7.24.7" - "@babel/parser" "^7.24.7" - "@babel/types" "^7.24.7" - debug "^4.3.1" - globals "^11.1.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-remap-async-to-generator" "^7.18.9" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7": +"@babel/plugin-proposal-export-default-from@^7.0.0": version "7.24.7" - resolved "https://registry.npmmirror.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" - integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.24.7.tgz" + integrity sha512-CcmFwUJ3tKhLjPdt4NP+SHMshebytF8ZTYOv5ZDpkzq2sin80Wb5vJrGt8fhPrORQCfoSa0LAxC/DW+GAC5+Hw== dependencies: - "@babel/helper-string-parser" "^7.24.7" - "@babel/helper-validator-identifier" "^7.24.7" - to-fast-properties "^2.0.0" - -"@esbuild/aix-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-export-default-from" "^7.24.7" -"@esbuild/android-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== +"@babel/plugin-proposal-logical-assignment-operators@^7.18.0": + version "7.20.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz" + integrity sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@esbuild/android-arm@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@esbuild/android-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== +"@babel/plugin-proposal-numeric-separator@^7.0.0": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@esbuild/darwin-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== +"@babel/plugin-proposal-object-rest-spread@^7.20.0": + version "7.20.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz" + integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.7" + +"@babel/plugin-proposal-optional-catch-binding@^7.0.0": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@esbuild/darwin-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== +"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.20.0": + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz" + integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" -"@esbuild/freebsd-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" -"@esbuild/freebsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" -"@esbuild/linux-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== +"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" -"@esbuild/linux-arm@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== +"@babel/plugin-syntax-export-default-from@^7.0.0", "@babel/plugin-syntax-export-default-from@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.24.7.tgz" + integrity sha512-bTPz4/635WQ9WhwsyPdxUJDVpsi/X9BMmy/8Rf/UAlOO4jSql4CxUCjWI5PiM+jG+c4LVPTScoTw80geFj9+Bw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" -"@esbuild/linux-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" -"@esbuild/linux-loong64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== +"@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz" + integrity sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" -"@esbuild/linux-mips64el@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== +"@babel/plugin-syntax-import-assertions@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" -"@esbuild/linux-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" -"@esbuild/linux-riscv64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" -"@esbuild/linux-s390x@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" -"@esbuild/linux-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== +"@babel/plugin-syntax-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" -"@esbuild/netbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" -"@esbuild/openbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== +"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" -"@esbuild/sunos-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" -"@esbuild/win32-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" -"@esbuild/win32-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" -"@esbuild/win32-x64@0.21.5": - version "0.21.5" - resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== +"@babel/plugin-syntax-optional-chaining@^7.0.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" + "@babel/helper-plugin-utils" "^7.14.5" -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== +"@babel/plugin-syntax-typescript@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz" + integrity sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": - version "1.4.15" - resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== +"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" + "@babel/helper-plugin-utils" "^7.24.7" -"@remix-run/router@1.17.1": - version "1.17.1" - resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.17.1.tgz#bf93997beb81863fde042ebd05013a2618471362" - integrity sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q== +"@babel/plugin-transform-async-generator-functions@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz" + integrity sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q== + 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" -"@rollup/plugin-inject@^5.0.5": - version "5.0.5" - resolved "https://registry.npmmirror.com/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz#616f3a73fe075765f91c5bec90176608bed277a3" - integrity sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg== +"@babel/plugin-transform-async-to-generator@^7.20.0", "@babel/plugin-transform-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== dependencies: - "@rollup/pluginutils" "^5.0.1" - estree-walker "^2.0.2" - magic-string "^0.30.3" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" -"@rollup/pluginutils@^5.0.1": - version "5.1.0" - resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" - integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== +"@babel/plugin-transform-block-scoped-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== dependencies: - "@types/estree" "^1.0.0" - estree-walker "^2.0.2" - picomatch "^2.3.1" + "@babel/helper-plugin-utils" "^7.24.7" -"@rollup/rollup-android-arm-eabi@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27" - integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ== +"@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz" + integrity sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" -"@rollup/rollup-android-arm64@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203" - integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA== +"@babel/plugin-transform-class-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz" + integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@rollup/rollup-darwin-arm64@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096" - integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w== +"@babel/plugin-transform-class-static-block@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== + 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" -"@rollup/rollup-darwin-x64@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c" - integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA== +"@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz" + integrity sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw== + 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" -"@rollup/rollup-linux-arm-gnueabihf@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8" - integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA== +"@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" -"@rollup/rollup-linux-arm-musleabihf@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549" - integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A== +"@babel/plugin-transform-destructuring@^7.20.0", "@babel/plugin-transform-destructuring@^7.24.8": + version "7.24.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz" + integrity sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" -"@rollup/rollup-linux-arm64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577" - integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw== +"@babel/plugin-transform-dotall-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@rollup/rollup-linux-arm64-musl@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c" - integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ== +"@babel/plugin-transform-duplicate-keys@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" -"@rollup/rollup-linux-powerpc64le-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf" - integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA== +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz" + integrity sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.0" + "@babel/helper-plugin-utils" "^7.24.8" -"@rollup/rollup-linux-riscv64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9" - integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg== +"@babel/plugin-transform-dynamic-import@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@rollup/rollup-linux-s390x-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec" - integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg== +"@babel/plugin-transform-exponentiation-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@rollup/rollup-linux-x64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942" - integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w== +"@babel/plugin-transform-export-namespace-from@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@rollup/rollup-linux-x64-musl@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d" - integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg== +"@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.24.7": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.2.tgz" + integrity sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/plugin-syntax-flow" "^7.24.7" -"@rollup/rollup-win32-arm64-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf" - integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA== +"@babel/plugin-transform-for-of@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@rollup/rollup-win32-ia32-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54" - integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg== +"@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.25.1": + version "7.25.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz" + integrity sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA== + dependencies: + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.1" -"@rollup/rollup-win32-x64-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4" - integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g== +"@babel/plugin-transform-json-strings@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" -"@types/babel__core@^7.20.5": - version "7.20.5" - resolved "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== +"@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.25.2": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz" + integrity sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw== dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" + "@babel/helper-plugin-utils" "^7.24.8" -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.npmmirror.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== +"@babel/plugin-transform-logical-assignment-operators@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== dependencies: - "@babel/types" "^7.0.0" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.npmmirror.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== +"@babel/plugin-transform-member-expression-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@types/babel__traverse@*": - version "7.20.6" - resolved "https://registry.npmmirror.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" - integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== +"@babel/plugin-transform-modules-amd@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== dependencies: - "@babel/types" "^7.20.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@types/estree@1.0.5", "@types/estree@^1.0.0": +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.24.7", "@babel/plugin-transform-modules-commonjs@^7.24.8": + version "7.24.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz" + integrity sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA== + dependencies: + "@babel/helper-module-transforms" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-simple-access" "^7.24.7" + +"@babel/plugin-transform-modules-systemjs@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz" + integrity sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw== + 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" + +"@babel/plugin-transform-modules-umd@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.0.0", "@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-new-target@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== + 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" + +"@babel/plugin-transform-object-super@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + +"@babel/plugin-transform-optional-catch-binding@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.24.7", "@babel/plugin-transform-optional-chaining@^7.24.8": + version "7.24.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz" + integrity sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw== + 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" + +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-methods@^7.22.5", "@babel/plugin-transform-private-methods@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz" + integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-property-in-object@^7.22.11", "@babel/plugin-transform-private-property-in-object@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== + 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" + +"@babel/plugin-transform-property-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz" + integrity sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-jsx-self@^7.0.0", "@babel/plugin-transform-react-jsx-self@^7.24.5": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz" + integrity sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-jsx-source@^7.0.0", "@babel/plugin-transform-react-jsx-source@^7.24.1": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz" + integrity sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz" + integrity sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/types" "^7.25.2" + +"@babel/plugin-transform-regenerator@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-runtime@^7.0.0": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz" + integrity sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.1" + babel-plugin-polyfill-regenerator "^0.6.1" + semver "^6.3.1" + +"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + +"@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-template-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-typeof-symbol@^7.24.8": + version "7.24.8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz" + integrity sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-typescript@^7.24.7", "@babel/plugin-transform-typescript@^7.5.0": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz" + integrity sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.25.0" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-syntax-typescript" "^7.24.7" + +"@babel/plugin-transform-unicode-escapes@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-property-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-sets-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz" + integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/preset-env@^7.1.6": + version "7.25.3" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz" + integrity sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g== + 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" + +"@babel/preset-flow@^7.13.13": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz" + integrity sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-transform-flow-strip-types" "^7.24.7" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-typescript@^7.13.0": + version "7.24.7" + resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz" + integrity sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.7" + "@babel/plugin-transform-typescript" "^7.24.7" + +"@babel/register@^7.13.16": + version "7.24.6" + resolved "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz" + integrity sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w== + dependencies: + clone-deep "^4.0.1" + find-cache-dir "^2.0.0" + make-dir "^2.1.0" + pirates "^4.0.6" + source-map-support "^0.5.16" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.19.4", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.8.4": + version "7.25.0" + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.0.0", "@babel/template@^7.24.7", "@babel/template@^7.25.0": + version "7.25.0" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz" + integrity sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/traverse@^7.20.0", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.3": + version "7.25.3" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz" + integrity sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ== + 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" + +"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.4.4": + version "7.25.2" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz" + integrity sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q== + dependencies: + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + +"@coinbase/wallet-sdk@4.0.4": + version "4.0.4" + dependencies: + buffer "^6.0.3" + clsx "^1.2.1" + eventemitter3 "^5.0.1" + keccak "^3.0.3" + preact "^10.16.0" + sha.js "^2.4.11" + +"@emotion/hash@^0.9.0": + version "0.9.2" + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@ethereumjs/common@^3.2.0": + version "3.2.0" + dependencies: + "@ethereumjs/util" "^8.1.0" + crc-32 "^1.2.0" + +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + +"@ethereumjs/tx@^4.1.2", "@ethereumjs/tx@^4.2.0": + version "4.2.0" + dependencies: + "@ethereumjs/common" "^3.2.0" + "@ethereumjs/rlp" "^4.0.1" + "@ethereumjs/util" "^8.1.0" + ethereum-cryptography "^2.0.0" + +"@ethereumjs/util@^8.1.0": + version "8.1.0" + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": + version "9.3.0" + resolved "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== + +"@hapi/topo@^5.1.0": + version "5.1.0" + resolved "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@isaacs/ttlcache@^1.4.1": + version "1.4.1" + resolved "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz" + integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA== + +"@jest/create-cache-key-function@^29.6.3": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz" + integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== + dependencies: + "@jest/types" "^29.6.3" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + 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" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + 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" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.2.1.tgz" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": + version "1.4.15" + resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@lit-labs/ssr-dom-shim@^1.0.0", "@lit-labs/ssr-dom-shim@^1.1.0": + version "1.2.0" + +"@lit/reactive-element@^1.3.0", "@lit/reactive-element@^1.6.0": + version "1.6.3" + dependencies: + "@lit-labs/ssr-dom-shim" "^1.0.0" + +"@metamask/eth-json-rpc-provider@^1.0.0": + version "1.0.1" + dependencies: + "@metamask/json-rpc-engine" "^7.0.0" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^5.0.1" + +"@metamask/json-rpc-engine@^7.0.0": + version "7.3.3" + dependencies: + "@metamask/rpc-errors" "^6.2.1" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^8.3.0" + +"@metamask/json-rpc-engine@^8.0.1", "@metamask/json-rpc-engine@^8.0.2": + version "8.0.2" + dependencies: + "@metamask/rpc-errors" "^6.2.1" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^8.3.0" + +"@metamask/json-rpc-middleware-stream@^7.0.1": + version "7.0.2" + dependencies: + "@metamask/json-rpc-engine" "^8.0.2" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^8.3.0" + readable-stream "^3.6.2" + +"@metamask/object-multiplex@^2.0.0": + version "2.0.0" + dependencies: + once "^1.4.0" + readable-stream "^3.6.2" + +"@metamask/onboarding@^1.0.1": + version "1.0.1" + dependencies: + bowser "^2.9.0" + +"@metamask/providers@16.1.0": + version "16.1.0" + dependencies: + "@metamask/json-rpc-engine" "^8.0.1" + "@metamask/json-rpc-middleware-stream" "^7.0.1" + "@metamask/object-multiplex" "^2.0.0" + "@metamask/rpc-errors" "^6.2.1" + "@metamask/safe-event-emitter" "^3.1.1" + "@metamask/utils" "^8.3.0" + detect-browser "^5.2.0" + extension-port-stream "^3.0.0" + fast-deep-equal "^3.1.3" + is-stream "^2.0.0" + readable-stream "^3.6.2" + webextension-polyfill "^0.10.0" + +"@metamask/rpc-errors@^6.2.1": + version "6.3.1" + dependencies: + "@metamask/utils" "^9.0.0" + fast-safe-stringify "^2.0.6" + +"@metamask/safe-event-emitter@^2.0.0": + version "2.0.0" + +"@metamask/safe-event-emitter@^3.0.0", "@metamask/safe-event-emitter@^3.1.1": + version "3.1.1" + +"@metamask/sdk-communication-layer@0.27.0": + version "0.27.0" + dependencies: + bufferutil "^4.0.8" + date-fns "^2.29.3" + debug "^4.3.4" + utf-8-validate "^5.0.2" + uuid "^8.3.2" + +"@metamask/sdk-install-modal-web@0.26.5": + version "0.26.5" + dependencies: + qr-code-styling "^1.6.0-rc.1" + +"@metamask/sdk@0.27.0": + version "0.27.0" + dependencies: + "@metamask/onboarding" "^1.0.1" + "@metamask/providers" "16.1.0" + "@metamask/sdk-communication-layer" "0.27.0" + "@metamask/sdk-install-modal-web" "0.26.5" + "@types/dom-screen-wake-lock" "^1.0.0" + bowser "^2.9.0" + cross-fetch "^4.0.0" + debug "^4.3.4" + eciesjs "^0.3.15" + eth-rpc-errors "^4.0.3" + eventemitter2 "^6.4.7" + i18next "23.11.5" + i18next-browser-languagedetector "7.1.0" + obj-multiplex "^1.0.0" + pump "^3.0.0" + qrcode-terminal-nooctal "^0.12.1" + react-native-webview "^11.26.0" + readable-stream "^3.6.2" + rollup-plugin-visualizer "^5.9.2" + socket.io-client "^4.5.1" + util "^0.12.4" + uuid "^8.3.2" + +"@metamask/superstruct@^3.0.0", "@metamask/superstruct@^3.1.0": + version "3.1.0" + +"@metamask/utils@^5.0.1": + version "5.0.2" + dependencies: + "@ethereumjs/tx" "^4.1.2" + "@types/debug" "^4.1.7" + debug "^4.3.4" + semver "^7.3.8" + superstruct "^1.0.3" + +"@metamask/utils@^8.3.0": + version "8.5.0" + dependencies: + "@ethereumjs/tx" "^4.2.0" + "@metamask/superstruct" "^3.0.0" + "@noble/hashes" "^1.3.1" + "@scure/base" "^1.1.3" + "@types/debug" "^4.1.7" + debug "^4.3.4" + pony-cause "^2.1.10" + semver "^7.5.4" + uuid "^9.0.1" + +"@metamask/utils@^9.0.0": + version "9.1.0" + dependencies: + "@ethereumjs/tx" "^4.2.0" + "@metamask/superstruct" "^3.1.0" + "@noble/hashes" "^1.3.1" + "@scure/base" "^1.1.3" + "@types/debug" "^4.1.7" + debug "^4.3.4" + pony-cause "^2.1.10" + semver "^7.5.4" + uuid "^9.0.1" + +"@motionone/animation@^10.15.1", "@motionone/animation@^10.18.0": + version "10.18.0" + dependencies: + "@motionone/easing" "^10.18.0" + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/dom@^10.16.2", "@motionone/dom@^10.16.4": + version "10.18.0" + dependencies: + "@motionone/animation" "^10.18.0" + "@motionone/generators" "^10.18.0" + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/easing@^10.18.0": + version "10.18.0" + dependencies: + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/generators@^10.18.0": + version "10.18.0" + dependencies: + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/svelte@^10.16.2": + version "10.16.4" + dependencies: + "@motionone/dom" "^10.16.4" + tslib "^2.3.1" + +"@motionone/types@^10.15.1", "@motionone/types@^10.17.1": + version "10.17.1" + +"@motionone/utils@^10.15.1", "@motionone/utils@^10.18.0": + version "10.18.0" + dependencies: + "@motionone/types" "^10.17.1" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/vue@^10.16.2": + version "10.16.4" + dependencies: + "@motionone/dom" "^10.16.4" + tslib "^2.3.1" + +"@noble/curves@^1.4.0", "@noble/curves@~1.4.0", "@noble/curves@1.4.2": + version "1.4.2" + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/curves@1.2.0": + version "1.2.0" + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.4.0": + version "1.4.0" + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0", "@noble/hashes@~1.4.0", "@noble/hashes@1.4.0": + version "1.4.0" + +"@noble/hashes@1.3.2": + version "1.3.2" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + version "2.0.5" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@parcel/watcher-darwin-arm64@2.4.1": + version "2.4.1" + +"@parcel/watcher-wasm@^2.4.1": + version "2.4.1" + dependencies: + is-glob "^4.0.3" + micromatch "^4.0.5" + napi-wasm "^1.1.0" + +"@parcel/watcher@^2.4.1": + version "2.4.1" + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.4.1" + "@parcel/watcher-darwin-arm64" "2.4.1" + "@parcel/watcher-darwin-x64" "2.4.1" + "@parcel/watcher-freebsd-x64" "2.4.1" + "@parcel/watcher-linux-arm-glibc" "2.4.1" + "@parcel/watcher-linux-arm64-glibc" "2.4.1" + "@parcel/watcher-linux-arm64-musl" "2.4.1" + "@parcel/watcher-linux-x64-glibc" "2.4.1" + "@parcel/watcher-linux-x64-musl" "2.4.1" + "@parcel/watcher-win32-arm64" "2.4.1" + "@parcel/watcher-win32-ia32" "2.4.1" + "@parcel/watcher-win32-x64" "2.4.1" + +"@rainbow-me/rainbowkit@^2.1.3": + version "2.1.3" + resolved "https://registry.npmjs.org/@rainbow-me/rainbowkit/-/rainbowkit-2.1.3.tgz" + integrity sha512-teeB0HVQR75xSOUqMWCI0m6JJ/TvYXmbDSMr252/oElkV2UF0m/FFKGW04MBtQOg6wo9WK3nD5HVNEola4p7yA== + dependencies: + "@vanilla-extract/css" "1.14.0" + "@vanilla-extract/dynamic" "2.1.0" + "@vanilla-extract/sprinkles" "1.6.1" + clsx "2.1.0" + qrcode "1.5.3" + react-remove-scroll "2.5.7" + ua-parser-js "^1.0.37" + +"@react-native-community/cli-clean@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-13.6.9.tgz" + integrity sha512-7Dj5+4p9JggxuVNOjPbduZBAP1SUgNhLKVw5noBUzT/3ZpUZkDM+RCSwyoyg8xKWoE4OrdUAXwAFlMcFDPKykA== + dependencies: + "@react-native-community/cli-tools" "13.6.9" + chalk "^4.1.2" + execa "^5.0.0" + fast-glob "^3.3.2" + +"@react-native-community/cli-config@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-13.6.9.tgz" + integrity sha512-rFfVBcNojcMm+KKHE/xqpqXg8HoKl4EC7bFHUrahMJ+y/tZll55+oX/PGG37rzB8QzP2UbMQ19DYQKC1G7kXeg== + dependencies: + "@react-native-community/cli-tools" "13.6.9" + chalk "^4.1.2" + cosmiconfig "^5.1.0" + deepmerge "^4.3.0" + fast-glob "^3.3.2" + joi "^17.2.1" + +"@react-native-community/cli-debugger-ui@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-13.6.9.tgz" + integrity sha512-TkN7IdFmGPPvTpAo3nCAH9uwGCPxWBEAwpqEZDrq0NWllI7Tdie8vDpGdrcuCcKalmhq6OYnkXzeBah7O1Ztpw== + dependencies: + serve-static "^1.13.1" + +"@react-native-community/cli-doctor@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-13.6.9.tgz" + integrity sha512-5quFaLdWFQB+677GXh5dGU9I5eg2z6Vg4jOX9vKnc9IffwyIFAyJfCZHrxLSRPDGNXD7biDQUdoezXYGwb6P/A== + dependencies: + "@react-native-community/cli-config" "13.6.9" + "@react-native-community/cli-platform-android" "13.6.9" + "@react-native-community/cli-platform-apple" "13.6.9" + "@react-native-community/cli-platform-ios" "13.6.9" + "@react-native-community/cli-tools" "13.6.9" + chalk "^4.1.2" + command-exists "^1.2.8" + deepmerge "^4.3.0" + envinfo "^7.10.0" + execa "^5.0.0" + hermes-profile-transformer "^0.0.6" + node-stream-zip "^1.9.1" + ora "^5.4.1" + semver "^7.5.2" + strip-ansi "^5.2.0" + wcwidth "^1.0.1" + yaml "^2.2.1" + +"@react-native-community/cli-hermes@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-13.6.9.tgz" + integrity sha512-GvwiwgvFw4Ws+krg2+gYj8sR3g05evmNjAHkKIKMkDTJjZ8EdyxbkifRUs1ZCq3TMZy2oeblZBXCJVOH4W7ZbA== + dependencies: + "@react-native-community/cli-platform-android" "13.6.9" + "@react-native-community/cli-tools" "13.6.9" + chalk "^4.1.2" + hermes-profile-transformer "^0.0.6" + +"@react-native-community/cli-platform-android@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-13.6.9.tgz" + integrity sha512-9KsYGdr08QhdvT3Ht7e8phQB3gDX9Fs427NJe0xnoBh+PDPTI2BD5ks5ttsH8CzEw8/P6H8tJCHq6hf2nxd9cw== + dependencies: + "@react-native-community/cli-tools" "13.6.9" + chalk "^4.1.2" + execa "^5.0.0" + fast-glob "^3.3.2" + fast-xml-parser "^4.2.4" + logkitty "^0.7.1" + +"@react-native-community/cli-platform-apple@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.9.tgz" + integrity sha512-KoeIHfhxMhKXZPXmhQdl6EE+jGKWwoO9jUVWgBvibpVmsNjo7woaG/tfJMEWfWF3najX1EkQAoJWpCDBMYWtlA== + dependencies: + "@react-native-community/cli-tools" "13.6.9" + chalk "^4.1.2" + execa "^5.0.0" + fast-glob "^3.3.2" + fast-xml-parser "^4.0.12" + ora "^5.4.1" + +"@react-native-community/cli-platform-ios@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-13.6.9.tgz" + integrity sha512-CiUcHlGs8vE0CAB4oi1f+dzniqfGuhWPNrDvae2nm8dewlahTBwIcK5CawyGezjcJoeQhjBflh9vloska+nlnw== + dependencies: + "@react-native-community/cli-platform-apple" "13.6.9" + +"@react-native-community/cli-server-api@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-13.6.9.tgz" + integrity sha512-W8FSlCPWymO+tlQfM3E0JmM8Oei5HZsIk5S0COOl0MRi8h0NmHI4WSTF2GCfbFZkcr2VI/fRsocoN8Au4EZAug== + dependencies: + "@react-native-community/cli-debugger-ui" "13.6.9" + "@react-native-community/cli-tools" "13.6.9" + compression "^1.7.1" + connect "^3.6.5" + errorhandler "^1.5.1" + nocache "^3.0.1" + pretty-format "^26.6.2" + serve-static "^1.13.1" + ws "^6.2.2" + +"@react-native-community/cli-tools@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-13.6.9.tgz" + integrity sha512-OXaSjoN0mZVw3nrAwcY1PC0uMfyTd9fz7Cy06dh+EJc+h0wikABsVRzV8cIOPrVV+PPEEXE0DBrH20T2puZzgQ== + dependencies: + appdirsjs "^1.2.4" + chalk "^4.1.2" + execa "^5.0.0" + find-up "^5.0.0" + mime "^2.4.1" + node-fetch "^2.6.0" + open "^6.2.0" + ora "^5.4.1" + semver "^7.5.2" + shell-quote "^1.7.3" + sudo-prompt "^9.0.0" + +"@react-native-community/cli-types@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-13.6.9.tgz" + integrity sha512-RLxDppvRxXfs3hxceW/mShi+6o5yS+kFPnPqZTaMKKR5aSg7LwDpLQW4K2D22irEG8e6RKDkZUeH9aL3vO2O0w== + dependencies: + joi "^17.2.1" + +"@react-native-community/cli@13.6.9": + version "13.6.9" + resolved "https://registry.npmjs.org/@react-native-community/cli/-/cli-13.6.9.tgz" + integrity sha512-hFJL4cgLPxncJJd/epQ4dHnMg5Jy/7Q56jFvA3MHViuKpzzfTCJCB+pGY54maZbtym53UJON9WTGpM3S81UfjQ== + dependencies: + "@react-native-community/cli-clean" "13.6.9" + "@react-native-community/cli-config" "13.6.9" + "@react-native-community/cli-debugger-ui" "13.6.9" + "@react-native-community/cli-doctor" "13.6.9" + "@react-native-community/cli-hermes" "13.6.9" + "@react-native-community/cli-server-api" "13.6.9" + "@react-native-community/cli-tools" "13.6.9" + "@react-native-community/cli-types" "13.6.9" + chalk "^4.1.2" + commander "^9.4.1" + deepmerge "^4.3.0" + execa "^5.0.0" + find-up "^4.1.0" + fs-extra "^8.1.0" + graceful-fs "^4.1.3" + prompts "^2.4.2" + semver "^7.5.2" + +"@react-native/assets-registry@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.74.86.tgz" + integrity sha512-rNWSa1MTqG3Z7ZfACIDlED+T63tNlt0Lr/ruvxFJL5IX6DRC6sIrb2SrbLrlXgz7C0FbhO0ub9zfHXISgrJOsQ== + +"@react-native/babel-plugin-codegen@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.74.86.tgz" + integrity sha512-fO7exk0pdsOSsK3fvDz4YKe5nMeAMrsIGi525pft/L+dedjdeiWYmEoQVc9NElxwwNCldwRY6eNMw6IhKyjzLA== + dependencies: + "@react-native/codegen" "0.74.86" + +"@react-native/babel-preset@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.74.86.tgz" + integrity sha512-6A+1NVAHugbBLFNU4iaYrq2lx8P7pINyqoyTtVAqd375PShRmLwu6GvuF3b/4avC97s6LmBljVTJ1xVHukA42g== + dependencies: + "@babel/core" "^7.20.0" + "@babel/plugin-proposal-async-generator-functions" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.18.0" + "@babel/plugin-proposal-export-default-from" "^7.0.0" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0" + "@babel/plugin-proposal-numeric-separator" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.20.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.20.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.18.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-syntax-optional-chaining" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-async-to-generator" "^7.20.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.20.0" + "@babel/plugin-transform-flow-strip-types" "^7.20.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-private-methods" "^7.22.5" + "@babel/plugin-transform-private-property-in-object" "^7.22.11" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-sticky-regex" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" + "@babel/plugin-transform-unicode-regex" "^7.0.0" + "@babel/template" "^7.0.0" + "@react-native/babel-plugin-codegen" "0.74.86" + babel-plugin-transform-flow-enums "^0.0.2" + react-refresh "^0.14.0" + +"@react-native/codegen@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.74.86.tgz" + integrity sha512-BOwABta9035GJ/zLMkxQfgPMr47u1/1HqNIMk10FqmTe0jmROOxKEAeP4FbeS5L1voO4ug3dqr+mcuHrG+HNhA== + dependencies: + "@babel/parser" "^7.20.0" + glob "^7.1.1" + hermes-parser "0.19.1" + invariant "^2.2.4" + jscodeshift "^0.14.0" + mkdirp "^0.5.1" + nullthrows "^1.1.1" + +"@react-native/community-cli-plugin@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.74.86.tgz" + integrity sha512-q0fPDe6vx1vT5PdE3AiL+DNm0q7opzySiGle8B64bAKsa0ClIoRXAzZqolceiMHbSoCIhUbZxYtNGavrjuPyKw== + dependencies: + "@react-native-community/cli-server-api" "13.6.9" + "@react-native-community/cli-tools" "13.6.9" + "@react-native/dev-middleware" "0.74.86" + "@react-native/metro-babel-transformer" "0.74.86" + chalk "^4.0.0" + execa "^5.1.1" + metro "^0.80.3" + metro-config "^0.80.3" + metro-core "^0.80.3" + node-fetch "^2.2.0" + querystring "^0.2.1" + readline "^1.3.0" + +"@react-native/debugger-frontend@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.74.86.tgz" + integrity sha512-Spq1kFX4qvPmT4HuTwpi1ALFtojlJ6s4GpWU2OnpevC/z7ks36lhD3J0rd0D9U5bkxtTYLcg31fPv7nGFC7XZg== + +"@react-native/dev-middleware@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.74.86.tgz" + integrity sha512-sc0tYxYt6dkUbNFI1IANzKO67M41BhjbJ6k/CHoFi/tGoNmHzg9IUZ89V4g3H8hn/VW9dETnPOFna1VO0sWrXg== + dependencies: + "@isaacs/ttlcache" "^1.4.1" + "@react-native/debugger-frontend" "0.74.86" + "@rnx-kit/chromium-edge-launcher" "^1.0.0" + chrome-launcher "^0.15.2" + connect "^3.6.5" + debug "^2.2.0" + node-fetch "^2.2.0" + nullthrows "^1.1.1" + open "^7.0.3" + selfsigned "^2.4.1" + serve-static "^1.13.1" + temp-dir "^2.0.0" + ws "^6.2.2" + +"@react-native/gradle-plugin@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.74.86.tgz" + integrity sha512-aoYeX7mjf3Efwc5t8AdcwC42oicMRKauGMZimvXY3xqfYV97G4foAYXrxQYZsMaxecFStdYMiXWyMFO/UFmEpA== + +"@react-native/js-polyfills@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.74.86.tgz" + integrity sha512-Yrsj4a1rTkk618LUJJxOWFnyAZR3sHmXJwcj4qupkJs+ou3aDkixfXgVVrvQP39iBptaQvCpo7PSqs+LjSNYbA== + +"@react-native/metro-babel-transformer@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.74.86.tgz" + integrity sha512-/9qN5zcnTHGDkC4jWibnoGmRnzDXiurl5wmkvspgnsdrJINN6eGpK8sdIn6nrHFOuPlp3Metqw3HkxbuAfNUXw== + dependencies: + "@babel/core" "^7.20.0" + "@react-native/babel-preset" "0.74.86" + hermes-parser "0.19.1" + nullthrows "^1.1.1" + +"@react-native/normalize-colors@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.86.tgz" + integrity sha512-GGA+nhwrQ1umwnkv7tuGbGIk0oBTeNbG4cUxNQX/CbYW0R98RCNxSbXjfw1XnXZd3lCSFLDxzw154V4hum2pNQ== + +"@react-native/virtualized-lists@0.74.86": + version "0.74.86" + resolved "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.74.86.tgz" + integrity sha512-f5wZpQvlGeWcyfK3Low0tOft9ounAaVQHpa4fiHjh9x3d2EPLwoaQe7sxS0q8/5pMISjddbF9S3ofpNuDxxoeA== + dependencies: + invariant "^2.2.4" + nullthrows "^1.1.1" + +"@remix-run/router@1.17.1": + version "1.17.1" + resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.17.1.tgz" + integrity sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q== + +"@rnx-kit/chromium-edge-launcher@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz" + integrity sha512-lzD84av1ZQhYUS+jsGqJiCMaJO2dn9u+RTT9n9q6D3SaKVwWqv+7AoRKqBu19bkwyE+iFRl1ymr40QS90jVFYg== + dependencies: + "@types/node" "^18.0.0" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + mkdirp "^1.0.4" + rimraf "^3.0.2" + +"@rollup/plugin-inject@^5.0.5": + version "5.0.5" + resolved "https://registry.npmmirror.com/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz" + integrity sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg== + dependencies: + "@rollup/pluginutils" "^5.0.1" + estree-walker "^2.0.2" + magic-string "^0.30.3" + +"@rollup/pluginutils@^5.0.1": + version "5.1.0" + resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz" + integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + +"@rollup/rollup-darwin-arm64@4.18.0": + version "4.18.0" + resolved "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz" + integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w== + +"@safe-global/safe-apps-provider@0.18.3": + version "0.18.3" + dependencies: + "@safe-global/safe-apps-sdk" "^9.1.0" + events "^3.3.0" + +"@safe-global/safe-apps-sdk@^9.1.0", "@safe-global/safe-apps-sdk@9.1.0": + version "9.1.0" + dependencies: + "@safe-global/safe-gateway-typescript-sdk" "^3.5.3" + viem "^2.1.1" + +"@safe-global/safe-gateway-typescript-sdk@^3.5.3": + version "3.22.1" + +"@scure/base@^1.1.3", "@scure/base@~1.1.6": + version "1.1.7" + +"@scure/bip32@1.4.0": + version "1.4.0" + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@scure/bip39@1.3.0": + version "1.3.0" + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@socket.io/component-emitter@~3.1.0": + version "3.1.2" + +"@stablelib/aead@^1.0.1": + version "1.0.1" + +"@stablelib/binary@^1.0.1": + version "1.0.1" + dependencies: + "@stablelib/int" "^1.0.1" + +"@stablelib/bytes@^1.0.1": + version "1.0.1" + +"@stablelib/chacha@^1.0.1": + version "1.0.1" + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/chacha20poly1305@1.0.1": + version "1.0.1" + dependencies: + "@stablelib/aead" "^1.0.1" + "@stablelib/binary" "^1.0.1" + "@stablelib/chacha" "^1.0.1" + "@stablelib/constant-time" "^1.0.1" + "@stablelib/poly1305" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/constant-time@^1.0.1": + version "1.0.1" + +"@stablelib/ed25519@^1.0.2": + version "1.0.3" + dependencies: + "@stablelib/random" "^1.0.2" + "@stablelib/sha512" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/hash@^1.0.1": + version "1.0.1" + +"@stablelib/hkdf@1.0.1": + version "1.0.1" + dependencies: + "@stablelib/hash" "^1.0.1" + "@stablelib/hmac" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/hmac@^1.0.1": + version "1.0.1" + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/int@^1.0.1": + version "1.0.1" + +"@stablelib/keyagreement@^1.0.1": + version "1.0.1" + dependencies: + "@stablelib/bytes" "^1.0.1" + +"@stablelib/poly1305@^1.0.1": + version "1.0.1" + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/random@^1.0.1", "@stablelib/random@^1.0.2", "@stablelib/random@1.0.2": + version "1.0.2" + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/sha256@1.0.1": + version "1.0.1" + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/sha512@^1.0.1": + version "1.0.1" + dependencies: + "@stablelib/binary" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + +"@stablelib/wipe@^1.0.1": + version "1.0.1" + +"@stablelib/x25519@1.0.3": + version "1.0.3" + dependencies: + "@stablelib/keyagreement" "^1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/wipe" "^1.0.1" + +"@tanstack/query-core@>=5.0.0", "@tanstack/query-core@5.51.16": + version "5.51.16" + +"@tanstack/react-query@^5.51.16", "@tanstack/react-query@>=5.0.0": + version "5.51.16" + resolved "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.16.tgz" + integrity sha512-NZnpJ30zkwaA2ZPhxJLs/qoMbd0yNAj6yyb3JTADJx9HjSdtvnNzOY1bDa3bU1B9CZTBBb7W9E1PpWlNXdgESg== + dependencies: + "@tanstack/query-core" "5.51.16" + +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.npmmirror.com/@types/babel__generator/-/babel__generator-7.6.8.tgz" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.npmmirror.com/@types/babel__template/-/babel__template-7.4.4.tgz" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.20.6" + resolved "https://registry.npmmirror.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== + dependencies: + "@babel/types" "^7.20.7" + +"@types/debug@^4.1.7": + version "4.1.12" + dependencies: + "@types/ms" "*" + +"@types/dom-screen-wake-lock@^1.0.0": + version "1.0.3" + +"@types/estree@^1.0.0", "@types/estree@1.0.5": version "1.0.5" - resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/events@^3.0.3": version "3.0.3" - resolved "https://registry.npmmirror.com/@types/events/-/events-3.0.3.tgz#a8ef894305af28d1fc6d2dfdfc98e899591ea529" + resolved "https://registry.npmmirror.com/@types/events/-/events-3.0.3.tgz" integrity sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g== -"@types/node@^20.14.9": +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.6" + resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/ms@*": + version "0.7.34" + +"@types/node-forge@^1.3.0": + version "1.3.11" + resolved "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz" + integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@^18.0.0 || >=20.0.0", "@types/node@^20.14.9": version "20.14.9" - resolved "https://registry.npmmirror.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" + resolved "https://registry.npmmirror.com/@types/node/-/node-20.14.9.tgz" integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== dependencies: undici-types "~5.26.4" +"@types/node@^18.0.0": + version "18.19.42" + resolved "https://registry.npmjs.org/@types/node/-/node-18.19.42.tgz" + integrity sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg== + dependencies: + undici-types "~5.26.4" + +"@types/node@18.15.13": + version "18.15.13" + "@types/prop-types@*": version "15.7.12" - resolved "https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" + resolved "https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.12.tgz" integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== "@types/react-dom@^18.3.0": version "18.3.0" - resolved "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" + resolved "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.3.0.tgz" integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== dependencies: - "@types/react" "*" + "@types/react" "*" + +"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.2.6", "@types/react@^18.3.3", "@types/react@>=16.8": + version "18.3.3" + resolved "https://registry.npmmirror.com/@types/react/-/react-18.3.3.tgz" + integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + +"@types/secp256k1@^4.0.6": + version "4.0.6" + dependencies: + "@types/node" "*" + +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/trusted-types@^2.0.2": + version "2.0.7" + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^15.0.0": + version "15.0.19" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz" + integrity sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA== + dependencies: + "@types/yargs-parser" "*" + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + +"@vanilla-extract/css@^1.0.0", "@vanilla-extract/css@1.14.0": + version "1.14.0" + dependencies: + "@emotion/hash" "^0.9.0" + "@vanilla-extract/private" "^1.0.3" + chalk "^4.1.1" + css-what "^6.1.0" + cssesc "^3.0.0" + csstype "^3.0.7" + deep-object-diff "^1.1.9" + deepmerge "^4.2.2" + media-query-parser "^2.0.2" + modern-ahocorasick "^1.0.0" + outdent "^0.8.0" + +"@vanilla-extract/dynamic@2.1.0": + version "2.1.0" + dependencies: + "@vanilla-extract/private" "^1.0.3" + +"@vanilla-extract/private@^1.0.3": + version "1.0.5" + +"@vanilla-extract/sprinkles@1.6.1": + version "1.6.1" + +"@vitejs/plugin-react@^4.3.1": + version "4.3.1" + resolved "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz" + integrity sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg== + dependencies: + "@babel/core" "^7.24.5" + "@babel/plugin-transform-react-jsx-self" "^7.24.5" + "@babel/plugin-transform-react-jsx-source" "^7.24.1" + "@types/babel__core" "^7.20.5" + react-refresh "^0.14.2" + +"@wagmi/connectors@5.1.2": + version "5.1.2" + dependencies: + "@coinbase/wallet-sdk" "4.0.4" + "@metamask/sdk" "0.27.0" + "@safe-global/safe-apps-provider" "0.18.3" + "@safe-global/safe-apps-sdk" "9.1.0" + "@walletconnect/ethereum-provider" "2.14.0" + "@walletconnect/modal" "2.6.2" + cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3" + +"@wagmi/core@2.13.1": + version "2.13.1" + dependencies: + eventemitter3 "5.0.1" + mipd "0.0.7" + zustand "4.4.1" + +"@walletconnect/core@2.14.0": + version "2.14.0" + dependencies: + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/jsonrpc-ws-connection" "1.0.14" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + "@walletconnect/relay-api" "1.0.10" + "@walletconnect/relay-auth" "1.0.4" + "@walletconnect/safe-json" "1.0.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.14.0" + "@walletconnect/utils" "2.14.0" + events "3.3.0" + isomorphic-unfetch "3.1.0" + lodash.isequal "4.5.0" + uint8arrays "3.1.0" + +"@walletconnect/environment@^1.0.1": + version "1.0.1" + dependencies: + tslib "1.14.1" + +"@walletconnect/ethereum-provider@2.14.0": + version "2.14.0" + dependencies: + "@walletconnect/jsonrpc-http-connection" "1.0.8" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/modal" "2.6.2" + "@walletconnect/sign-client" "2.14.0" + "@walletconnect/types" "2.14.0" + "@walletconnect/universal-provider" "2.14.0" + "@walletconnect/utils" "2.14.0" + events "3.3.0" + +"@walletconnect/events@^1.0.1", "@walletconnect/events@1.0.1": + version "1.0.1" + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/heartbeat@1.2.2": + version "1.2.2" + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/time" "^1.0.2" + events "^3.3.0" + +"@walletconnect/jsonrpc-http-connection@1.0.8": + version "1.0.8" + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.1" + cross-fetch "^3.1.4" + events "^3.3.0" + +"@walletconnect/jsonrpc-provider@1.0.14": + version "1.0.14" + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.8" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + +"@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3", "@walletconnect/jsonrpc-types@1.0.4": + version "1.0.4" + dependencies: + events "^3.3.0" + keyvaluestorage-interface "^1.0.0" + +"@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.8", "@walletconnect/jsonrpc-utils@1.0.8": + version "1.0.8" + dependencies: + "@walletconnect/environment" "^1.0.1" + "@walletconnect/jsonrpc-types" "^1.0.3" + tslib "1.14.1" + +"@walletconnect/jsonrpc-ws-connection@1.0.14": + version "1.0.14" + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + ws "^7.5.1" + +"@walletconnect/keyvaluestorage@1.1.1": + version "1.1.1" + dependencies: + "@walletconnect/safe-json" "^1.0.1" + idb-keyval "^6.2.1" + unstorage "^1.9.0" + +"@walletconnect/logger@2.1.2": + version "2.1.2" + dependencies: + "@walletconnect/safe-json" "^1.0.2" + pino "7.11.0" + +"@walletconnect/modal-core@2.6.2": + version "2.6.2" + dependencies: + valtio "1.11.2" + +"@walletconnect/modal-ui@2.6.2": + version "2.6.2" + dependencies: + "@walletconnect/modal-core" "2.6.2" + lit "2.8.0" + motion "10.16.2" + qrcode "1.5.3" + +"@walletconnect/modal@2.6.2": + version "2.6.2" + dependencies: + "@walletconnect/modal-core" "2.6.2" + "@walletconnect/modal-ui" "2.6.2" + +"@walletconnect/relay-api@1.0.10": + version "1.0.10" + dependencies: + "@walletconnect/jsonrpc-types" "^1.0.2" + +"@walletconnect/relay-auth@1.0.4": + version "1.0.4" + dependencies: + "@stablelib/ed25519" "^1.0.2" + "@stablelib/random" "^1.0.1" + "@walletconnect/safe-json" "^1.0.1" + "@walletconnect/time" "^1.0.2" + tslib "1.14.1" + uint8arrays "^3.0.0" + +"@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2", "@walletconnect/safe-json@1.0.2": + version "1.0.2" + dependencies: + tslib "1.14.1" + +"@walletconnect/sign-client@2.14.0": + version "2.14.0" + dependencies: + "@walletconnect/core" "2.14.0" + "@walletconnect/events" "1.0.1" + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "2.1.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.14.0" + "@walletconnect/utils" "2.14.0" + events "3.3.0" + +"@walletconnect/time@^1.0.2", "@walletconnect/time@1.0.2": + version "1.0.2" + dependencies: + tslib "1.14.1" + +"@walletconnect/types@2.14.0": + version "2.14.0" + dependencies: + "@walletconnect/events" "1.0.1" + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + events "3.3.0" + +"@walletconnect/universal-provider@2.14.0": + version "2.14.0" + dependencies: + "@walletconnect/jsonrpc-http-connection" "1.0.8" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "2.1.2" + "@walletconnect/sign-client" "2.14.0" + "@walletconnect/types" "2.14.0" + "@walletconnect/utils" "2.14.0" + events "3.3.0" + +"@walletconnect/utils@2.14.0": + version "2.14.0" + dependencies: + "@stablelib/chacha20poly1305" "1.0.1" + "@stablelib/hkdf" "1.0.1" + "@stablelib/random" "1.0.2" + "@stablelib/sha256" "1.0.1" + "@stablelib/x25519" "1.0.3" + "@walletconnect/relay-api" "1.0.10" + "@walletconnect/safe-json" "1.0.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.14.0" + "@walletconnect/window-getters" "1.0.1" + "@walletconnect/window-metadata" "1.0.1" + detect-browser "5.3.0" + query-string "7.1.3" + uint8arrays "3.1.0" + +"@walletconnect/window-getters@^1.0.1", "@walletconnect/window-getters@1.0.1": + version "1.0.1" + dependencies: + tslib "1.14.1" + +"@walletconnect/window-metadata@1.0.1": + version "1.0.1" + dependencies: + "@walletconnect/window-getters" "^1.0.1" + tslib "1.14.1" + +abitype@1.0.5: + version "1.0.5" + +abort-controller@^3.0.0: + version "3.0.0" + dependencies: + event-target-shim "^5.0.0" + +accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.8" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" -"@types/react@*", "@types/react@^18.3.3": - version "18.3.3" - resolved "https://registry.npmmirror.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" - integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== +acorn@^8.11.3, acorn@^8.8.2: + version "8.12.1" + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + +anser@^1.4.9: + version "1.4.10" + resolved "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz" + integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== + +ansi-fragments@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz" + integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w== dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" + colorette "^1.0.7" + slice-ansi "^2.0.0" + strip-ansi "^5.0.0" -"@vitejs/plugin-react@^4.3.1": - version "4.3.1" - resolved "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz#d0be6594051ded8957df555ff07a991fb618b48e" - integrity sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg== +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-regex@^5.0.0, ansi-regex@^5.0.1: + version "5.0.1" + +ansi-styles@^3.2.0: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: - "@babel/core" "^7.24.5" - "@babel/plugin-transform-react-jsx-self" "^7.24.5" - "@babel/plugin-transform-react-jsx-source" "^7.24.1" - "@types/babel__core" "^7.20.5" - react-refresh "^0.14.2" + color-convert "^1.9.0" ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3, anymatch@^3.1.3, anymatch@~3.1.2: + version "3.1.3" + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +appdirsjs@^1.2.4: + version "1.2.7" + resolved "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz" + integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + asn1.js@^4.10.1: version "4.10.1" - resolved "https://registry.npmmirror.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + resolved "https://registry.npmmirror.com/asn1.js/-/asn1.js-4.10.1.tgz" integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== dependencies: bn.js "^4.0.0" @@ -561,7 +2640,7 @@ asn1.js@^4.10.1: assert@^2.0.0: version "2.1.0" - resolved "https://registry.npmmirror.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" + resolved "https://registry.npmmirror.com/assert/-/assert-2.1.0.tgz" integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== dependencies: call-bind "^1.0.2" @@ -570,43 +2649,142 @@ assert@^2.0.0: object.assign "^4.1.4" util "^0.12.5" +ast-types@0.15.2: + version "0.15.2" + resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz" + integrity sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg== + dependencies: + tslib "^2.0.1" + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async-mutex@^0.2.6: + version "0.2.6" + dependencies: + tslib "^2.0.0" + +atomic-sleep@^1.0.0: + version "1.0.0" + available-typed-arrays@^1.0.7: version "1.0.7" - resolved "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + resolved "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz" integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== dependencies: possible-typed-array-names "^1.0.0" -base64-js@^1.3.1: +babel-core@^7.0.0-bridge.0: + version "7.0.0-bridge.0" + resolved "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz" + integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== + +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.4" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz" + integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.1" + core-js-compat "^3.36.1" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + +babel-plugin-transform-flow-enums@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz" + integrity sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ== + dependencies: + "@babel/plugin-syntax-flow" "^7.12.1" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" - resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +binary-extensions@^2.0.0: + version "2.3.0" + +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" - resolved "https://registry.npmmirror.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + resolved "https://registry.npmmirror.com/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.2.1: +bn.js@^5.0.0: + version "5.2.1" + resolved "https://registry.npmmirror.com/bn.js/-/bn.js-5.2.1.tgz" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +bn.js@^5.2.1: version "5.2.1" - resolved "https://registry.npmmirror.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + resolved "https://registry.npmmirror.com/bn.js/-/bn.js-5.2.1.tgz" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +bowser@^2.9.0: + version "2.11.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + dependencies: + fill-range "^7.1.1" + brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" - resolved "https://registry.npmmirror.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + resolved "https://registry.npmmirror.com/brorand/-/brorand-1.1.0.tgz" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== browser-resolve@^2.0.0: version "2.0.0" - resolved "https://registry.npmmirror.com/browser-resolve/-/browser-resolve-2.0.0.tgz#99b7304cb392f8d73dba741bb2d7da28c6d7842b" + resolved "https://registry.npmmirror.com/browser-resolve/-/browser-resolve-2.0.0.tgz" integrity sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ== dependencies: resolve "^1.17.0" browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" - resolved "https://registry.npmmirror.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + resolved "https://registry.npmmirror.com/browserify-aes/-/browserify-aes-1.2.0.tgz" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" @@ -618,7 +2796,7 @@ browserify-aes@^1.0.4, browserify-aes@^1.2.0: browserify-cipher@^1.0.0: version "1.0.1" - resolved "https://registry.npmmirror.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + resolved "https://registry.npmmirror.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz" integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" @@ -627,7 +2805,7 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" - resolved "https://registry.npmmirror.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + resolved "https://registry.npmmirror.com/browserify-des/-/browserify-des-1.0.2.tgz" integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" @@ -637,7 +2815,7 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" - resolved "https://registry.npmmirror.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + resolved "https://registry.npmmirror.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: bn.js "^5.0.0" @@ -645,7 +2823,7 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: browserify-sign@^4.0.0: version "4.2.3" - resolved "https://registry.npmmirror.com/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" + resolved "https://registry.npmmirror.com/browserify-sign/-/browserify-sign-4.2.3.tgz" integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== dependencies: bn.js "^5.2.1" @@ -661,14 +2839,14 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" - resolved "https://registry.npmmirror.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + resolved "https://registry.npmmirror.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz" integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" -browserslist@^4.22.2: +browserslist@^4.23.0, browserslist@^4.23.1, "browserslist@>= 4.21.0": version "4.23.1" - resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96" + resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.23.1.tgz" integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw== dependencies: caniuse-lite "^1.0.30001629" @@ -676,27 +2854,63 @@ browserslist@^4.22.2: node-releases "^2.0.14" update-browserslist-db "^1.0.16" +bser@2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + buffer-xor@^1.0.3: version "1.0.3" - resolved "https://registry.npmmirror.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + resolved "https://registry.npmmirror.com/buffer-xor/-/buffer-xor-1.0.3.tgz" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buffer@^5.7.1: version "5.7.1" - resolved "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + resolved "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bufferutil@^4.0.1, bufferutil@^4.0.8: + version "4.0.8" + dependencies: + node-gyp-build "^4.3.0" + builtin-status-codes@^3.0.0: version "3.0.0" - resolved "https://registry.npmmirror.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + resolved "https://registry.npmmirror.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz" integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.7: version "1.0.7" - resolved "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + resolved "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz" integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: es-define-property "^1.0.0" @@ -705,63 +2919,299 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.7: get-intrinsic "^1.2.4" set-function-length "^1.2.1" +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + +camelcase@^5.0.0: + version "5.3.1" + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + caniuse-lite@^1.0.30001629: version "1.0.30001640" - resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz#32c467d4bf1f1a0faa63fc793c2ba81169e7652f" + resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz" integrity sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA== +"cbw-sdk@npm:@coinbase/wallet-sdk@3.9.3": + version "3.9.3" + dependencies: + bn.js "^5.2.1" + buffer "^6.0.3" + clsx "^1.2.1" + eth-block-tracker "^7.1.0" + eth-json-rpc-filters "^6.0.0" + eventemitter3 "^5.0.1" + keccak "^3.0.3" + preact "^10.16.0" + sha.js "^2.4.11" + chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: + version "4.1.2" + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^3.6.0: + version "3.6.0" + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-launcher@^0.15.2: + version "0.15.2" + resolved "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz" + integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" - resolved "https://registry.npmmirror.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + resolved "https://registry.npmmirror.com/cipher-base/-/cipher-base-1.0.4.tgz" integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" +citty@^0.1.5, citty@^0.1.6: + version "0.1.6" + dependencies: + consola "^3.2.3" + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.9.2" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +clipboardy@^4.0.0: + version "4.0.0" + dependencies: + execa "^8.0.1" + is-wsl "^3.1.0" + is64bit "^2.0.0" + +cliui@^6.0.0: + version "6.0.0" + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +clsx@^1.2.1: + version "1.2.1" + +clsx@2.1.0: + version "2.1.0" + color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +colorette@^1.0.7: + version "1.4.0" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^9.4.1: + version "9.5.0" + resolved "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.1: + version "1.7.4" + resolved "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +confbox@^0.1.7: + version "0.1.7" + +connect@^3.6.5: + version "3.7.0" + resolved "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +consola@^3.2.3: + version "3.2.3" + console-browserify@^1.1.0: version "1.2.0" - resolved "https://registry.npmmirror.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + resolved "https://registry.npmmirror.com/console-browserify/-/console-browserify-1.2.0.tgz" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== constants-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npmmirror.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + resolved "https://registry.npmmirror.com/constants-browserify/-/constants-browserify-1.0.0.tgz" integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== convert-source-map@^2.0.0: version "2.0.0" - resolved "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + resolved "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie-es@^1.1.0: + version "1.2.2" + +core-js-compat@^3.36.1, core-js-compat@^3.37.1: + version "3.37.1" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz" + integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== + dependencies: + browserslist "^4.23.0" + core-util-is@~1.0.0: version "1.0.3" - resolved "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + resolved "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: + version "5.2.1" + resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +crc-32@^1.2.0: + version "1.2.2" + create-ecdh@^4.0.0: version "4.0.4" - resolved "https://registry.npmmirror.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + resolved "https://registry.npmmirror.com/create-ecdh/-/create-ecdh-4.0.4.tgz" integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" @@ -769,7 +3219,7 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" - resolved "https://registry.npmmirror.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + resolved "https://registry.npmmirror.com/create-hash/-/create-hash-1.2.0.tgz" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" @@ -780,7 +3230,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" - resolved "https://registry.npmmirror.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + resolved "https://registry.npmmirror.com/create-hmac/-/create-hmac-1.1.7.tgz" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" @@ -792,12 +3242,32 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: create-require@^1.1.1: version "1.1.1" - resolved "https://registry.npmmirror.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + resolved "https://registry.npmmirror.com/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^3.1.4: + version "3.1.8" + dependencies: + node-fetch "^2.6.12" + +cross-fetch@^4.0.0: + version "4.0.0" + dependencies: + node-fetch "^2.6.12" + +cross-spawn@^7.0.3: + version "7.0.3" + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crossws@^0.2.0, crossws@^0.2.4: + version "0.2.4" + crypto-browserify@^3.11.0: version "3.12.0" - resolved "https://registry.npmmirror.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + resolved "https://registry.npmmirror.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz" integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" @@ -812,66 +3282,183 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" -csstype@^3.0.2: +css-what@^6.1.0: + version "6.1.0" + +cssesc@^3.0.0: + version "3.0.0" + +csstype@^3.0.2, csstype@^3.0.7: version "3.1.3" - resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== -debug@^4.1.0, debug@^4.3.1: +date-fns@^2.29.3: + version "2.30.0" + dependencies: + "@babel/runtime" "^7.21.0" + +dayjs@^1.8.15: + version "1.11.12" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz" + integrity sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg== + +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^2.6.9: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.1.0: version "4.3.5" - resolved "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + resolved "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz" integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== dependencies: ms "2.1.2" +debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: + version "4.3.6" + dependencies: + ms "2.1.2" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decamelize@^1.2.0: + version "1.2.0" + +decode-uri-component@^0.2.2: + version "0.2.2" + +deep-object-diff@^1.1.9: + version "1.1.9" + +deepmerge@^4.2.2, deepmerge@^4.3.0: + version "4.3.1" + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" - resolved "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + resolved "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz" integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== dependencies: es-define-property "^1.0.0" es-errors "^1.3.0" gopd "^1.0.1" +define-lazy-prop@^2.0.0: + version "2.0.0" + define-properties@^1.1.3, define-properties@^1.2.1: version "1.2.1" - resolved "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + resolved "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.1.tgz" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" +defu@^6.1.4: + version "6.1.4" + +denodeify@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz" + integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + des.js@^1.0.0: version "1.1.0" - resolved "https://registry.npmmirror.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + resolved "https://registry.npmmirror.com/des.js/-/des.js-1.1.0.tgz" integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" +destr@^2.0.3: + version "2.0.3" + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-browser@^5.2.0, detect-browser@5.3.0: + version "5.3.0" + +detect-libc@^1.0.3: + version "1.0.3" + +detect-node-es@^1.1.0: + version "1.1.0" + diffie-hellman@^5.0.0: version "5.0.3" - resolved "https://registry.npmmirror.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + resolved "https://registry.npmmirror.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz" integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" miller-rabin "^4.0.0" randombytes "^2.0.0" +dijkstrajs@^1.0.1: + version "1.0.3" + domain-browser@^4.22.0: version "4.23.0" - resolved "https://registry.npmmirror.com/domain-browser/-/domain-browser-4.23.0.tgz#427ebb91efcb070f05cffdfb8a4e9a6c25f8c94b" + resolved "https://registry.npmmirror.com/domain-browser/-/domain-browser-4.23.0.tgz" integrity sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA== +duplexify@^4.1.2: + version "4.1.3" + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.2" + +eciesjs@^0.3.15, eciesjs@^0.3.16: + version "0.3.19" + dependencies: + "@types/secp256k1" "^4.0.6" + futoin-hkdf "^1.5.3" + secp256k1 "^5.0.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + electron-to-chromium@^1.4.796: version "1.4.816" - resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz#3624649d1e7fde5cdbadf59d31a524245d8ee85f" + resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz" integrity sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw== elliptic@^6.5.3, elliptic@^6.5.5: version "6.5.5" - resolved "https://registry.npmmirror.com/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded" + resolved "https://registry.npmmirror.com/elliptic/-/elliptic-6.5.5.tgz" integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw== dependencies: bn.js "^4.11.9" @@ -882,21 +3469,87 @@ elliptic@^6.5.3, elliptic@^6.5.5: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +elliptic@^6.5.4: + version "6.5.6" + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + +encode-utf8@^1.0.3: + version "1.0.3" + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.1.0, end-of-stream@^1.4.0, end-of-stream@^1.4.1: + version "1.4.4" + dependencies: + once "^1.4.0" + +engine.io-client@~6.5.2: + version "6.5.4" + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + engine.io-parser "~5.2.1" + ws "~8.17.1" + xmlhttprequest-ssl "~2.0.0" + +engine.io-parser@~5.2.1: + version "5.2.3" + +envinfo@^7.10.0: + version "7.13.0" + resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz" + integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + +errorhandler@^1.5.1: + version "1.5.1" + resolved "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz" + integrity sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A== + dependencies: + accepts "~1.3.7" + escape-html "~1.0.3" + es-define-property@^1.0.0: version "1.0.0" - resolved "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + resolved "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz" integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== dependencies: get-intrinsic "^1.2.4" es-errors@^1.3.0: version "1.3.0" - resolved "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + resolved "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== esbuild@^0.21.3: version "0.21.5" - resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz" integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== optionalDependencies: "@esbuild/aix-ppc64" "0.21.5" @@ -923,67 +3576,322 @@ esbuild@^0.21.3: "@esbuild/win32-ia32" "0.21.5" "@esbuild/win32-x64" "0.21.5" -escalade@^3.1.2: +escalade@^3.1.1, escalade@^3.1.2: version "3.1.2" - resolved "https://registry.npmmirror.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + resolved "https://registry.npmmirror.com/escalade/-/escalade-3.1.2.tgz" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escape-string-regexp@^2.0.0, escape-string-regexp@2.0.0: + version "2.0.0" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +esprima@^4.0.0, esprima@~4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + estree-walker@^2.0.2: version "2.0.2" - resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== -events@^3.0.0: +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eth-block-tracker@^7.1.0: + version "7.1.0" + dependencies: + "@metamask/eth-json-rpc-provider" "^1.0.0" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^5.0.1" + json-rpc-random-id "^1.0.1" + pify "^3.0.0" + +eth-json-rpc-filters@^6.0.0: + version "6.0.1" + dependencies: + "@metamask/safe-event-emitter" "^3.0.0" + async-mutex "^0.2.6" + eth-query "^2.1.2" + json-rpc-engine "^6.1.0" + pify "^5.0.0" + +eth-query@^2.1.2: + version "2.1.2" + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-rpc-errors@^4.0.2, eth-rpc-errors@^4.0.3: + version "4.0.3" + dependencies: + fast-safe-stringify "^2.0.6" + +ethereum-cryptography@^2.0.0: + version "2.2.1" + dependencies: + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + +ethers@^6.13.2: + version "6.13.2" + resolved "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz" + integrity sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.17.1" + +event-target-shim@^5.0.0, event-target-shim@^5.0.1: + version "5.0.1" + +eventemitter2@^6.4.7: + version "6.4.9" + +eventemitter3@^5.0.1, eventemitter3@5.0.1: + version "5.0.1" + +events@^3.0.0, events@^3.3.0, events@3.3.0: version "3.3.0" - resolved "https://registry.npmmirror.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + resolved "https://registry.npmmirror.com/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" - resolved "https://registry.npmmirror.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + resolved "https://registry.npmmirror.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" safe-buffer "^5.1.1" +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + 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" + +execa@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + 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" + +execa@^8.0.1: + version "8.0.1" + dependencies: + cross-spawn "^7.0.3" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" + +extension-port-stream@^3.0.0: + version "3.0.0" + dependencies: + readable-stream "^3.6.2 || ^4.4.2" + webextension-polyfill ">=0.10.0 <1.0" + +fast-deep-equal@^3.1.3: + version "3.1.3" + +fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + 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" + +fast-redact@^3.0.0: + version "3.5.0" + +fast-safe-stringify@^2.0.6: + version "2.1.1" + +fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4: + version "4.4.1" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz" + integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== + dependencies: + strnum "^1.0.5" + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fill-range@^7.1.1: + version "7.1.1" + dependencies: + to-regex-range "^5.0.1" + +filter-obj@^1.1.0: + version "1.1.0" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-cache-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.1.0: + version "4.1.0" + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-up@^5.0.0: version "5.0.0" - resolved "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" path-exists "^4.0.0" +flow-enums-runtime@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz" + integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw== + +flow-parser@0.*: + version "0.242.1" + resolved "https://registry.npmjs.org/flow-parser/-/flow-parser-0.242.1.tgz" + integrity sha512-E3ml21Q1S5cMAyPbtYslkvI6yZO5oCS/S2EoteeFH8Kx9iKOv/YOJ+dGd/yMf+H3YKfhMKjnOpyNwrO7NdddWA== + for-each@^0.3.3: version "0.3.3" - resolved "https://registry.npmmirror.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + resolved "https://registry.npmmirror.com/for-each/-/for-each-0.3.3.tgz" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" -fsevents@~2.3.2, fsevents@~2.3.3: +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" - resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +futoin-hkdf@^1.5.3: + version "1.5.3" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: version "1.2.4" - resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz" integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: es-errors "^1.3.0" @@ -992,50 +3900,103 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: has-symbols "^1.0.3" hasown "^2.0.0" +get-nonce@^1.0.0: + version "1.0.1" + +get-port-please@^3.1.2: + version "3.1.2" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-stream@^8.0.1: + version "8.0.1" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + dependencies: + is-glob "^4.0.1" + +glob@^7.1.1, glob@^7.1.3: + version "7.2.3" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + 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" + globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== gopd@^1.0.1: version "1.0.1" - resolved "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + resolved "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz" integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== dependencies: get-intrinsic "^1.1.3" +graceful-fs@^4.1.11, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +h3@^1.10.2, h3@^1.11.1: + version "1.12.0" + dependencies: + cookie-es "^1.1.0" + crossws "^0.2.4" + defu "^6.1.4" + destr "^2.0.3" + iron-webcrypto "^1.1.1" + ohash "^1.1.3" + radix3 "^1.1.2" + ufo "^1.5.3" + uncrypto "^0.1.3" + unenv "^1.9.0" + has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== +has-flag@^4.0.0: + version "4.0.0" + has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" - resolved "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + resolved "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: es-define-property "^1.0.0" has-proto@^1.0.1: version "1.0.3" - resolved "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + resolved "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz" integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: version "1.0.2" - resolved "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + resolved "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz" integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: has-symbols "^1.0.3" hash-base@^3.0.0: version "3.1.0" - resolved "https://registry.npmmirror.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + resolved "https://registry.npmmirror.com/hash-base/-/hash-base-3.1.0.tgz" integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: inherits "^2.0.4" @@ -1044,7 +4005,7 @@ hash-base@^3.0.0: hash-base@~3.0: version "3.0.4" - resolved "https://registry.npmmirror.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + resolved "https://registry.npmmirror.com/hash-base/-/hash-base-3.0.4.tgz" integrity sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow== dependencies: inherits "^2.0.1" @@ -1052,7 +4013,7 @@ hash-base@~3.0: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" - resolved "https://registry.npmmirror.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + resolved "https://registry.npmmirror.com/hash.js/-/hash.js-1.1.7.tgz" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" @@ -1060,175 +4021,1054 @@ hash.js@^1.0.0, hash.js@^1.0.3: hasown@^2.0.0, hasown@^2.0.2: version "2.0.2" - resolved "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + resolved "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" +hermes-estree@0.19.1: + version "0.19.1" + resolved "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.19.1.tgz" + integrity sha512-daLGV3Q2MKk8w4evNMKwS8zBE/rcpA800nu1Q5kM08IKijoSnPe9Uo1iIxzPKRkn95IxxsgBMPeYHt3VG4ej2g== + +hermes-estree@0.20.1: + version "0.20.1" + resolved "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz" + integrity sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg== + +hermes-parser@0.19.1: + version "0.19.1" + resolved "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.19.1.tgz" + integrity sha512-Vp+bXzxYJWrpEuJ/vXxUsLnt0+y4q9zyi4zUlkLqD8FKv4LjIfOvP69R/9Lty3dCyKh0E2BU7Eypqr63/rKT/A== + dependencies: + hermes-estree "0.19.1" + +hermes-parser@0.20.1: + version "0.20.1" + resolved "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz" + integrity sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA== + dependencies: + hermes-estree "0.20.1" + +hermes-profile-transformer@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz" + integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== + dependencies: + source-map "^0.7.3" + +hey-listen@^1.0.8: + version "1.0.8" + hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.npmmirror.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + resolved "https://registry.npmmirror.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz" integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== dependencies: hash.js "^1.0.3" minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-shutdown@^1.2.2: + version "1.2.2" + https-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npmmirror.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + resolved "https://registry.npmmirror.com/https-browserify/-/https-browserify-1.0.0.tgz" integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== -ieee754@^1.1.13: +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +human-signals@^5.0.0: + version "5.0.0" + +i18next-browser-languagedetector@7.1.0: + version "7.1.0" + dependencies: + "@babel/runtime" "^7.19.4" + +i18next@23.11.5: + version "23.11.5" + dependencies: + "@babel/runtime" "^7.23.2" + +idb-keyval@^6.2.1: + version "6.2.1" + +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" - resolved "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + resolved "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: +image-size@^1.0.2: + version "1.1.1" + resolved "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz" + integrity sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ== + dependencies: + queue "6.0.2" + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4, inherits@2, inherits@2.0.4: version "2.0.4" - resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +invariant@^2.2.4, invariant@2.2.4: + version "2.2.4" + dependencies: + loose-envify "^1.0.0" + +iron-webcrypto@^1.1.1: + version "1.2.1" + is-arguments@^1.0.4: version "1.1.1" - resolved "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + resolved "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== dependencies: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-binary-path@~2.1.0: + version "2.1.0" + dependencies: + binary-extensions "^2.0.0" + is-callable@^1.1.3: version "1.2.7" - resolved "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + resolved "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.7.tgz" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-core-module@^2.13.0: version "2.14.0" - resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.14.0.tgz" integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== dependencies: hasown "^2.0.2" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + +is-docker@^3.0.0: + version "3.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + is-generator-function@^1.0.7: version "1.0.10" - resolved "https://registry.npmmirror.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + resolved "https://registry.npmmirror.com/is-generator-function/-/is-generator-function-1.0.10.tgz" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== dependencies: has-tostringtag "^1.0.0" +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + dependencies: + is-extglob "^2.1.1" + +is-inside-container@^1.0.0: + version "1.0.0" + dependencies: + is-docker "^3.0.0" + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-nan@^1.3.2: version "1.3.2" - resolved "https://registry.npmmirror.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + resolved "https://registry.npmmirror.com/is-nan/-/is-nan-1.3.2.tgz" integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== dependencies: call-bind "^1.0.0" define-properties "^1.1.3" +is-number@^7.0.0: + version "7.0.0" + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-stream@^2.0.0: + version "2.0.1" + +is-stream@^3.0.0: + version "3.0.0" + is-typed-array@^1.1.3: version "1.1.13" - resolved "https://registry.npmmirror.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + resolved "https://registry.npmmirror.com/is-typed-array/-/is-typed-array-1.1.13.tgz" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== dependencies: which-typed-array "^1.1.14" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz" + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + +is-wsl@^2.1.1, is-wsl@^2.2.0: + version "2.2.0" + dependencies: + is-docker "^2.0.0" + +is-wsl@^3.1.0: + version "3.1.0" + dependencies: + is-inside-container "^1.0.0" + +is64bit@^2.0.0: + version "2.0.0" + dependencies: + system-architecture "^0.1.0" + isarray@~1.0.0: version "1.0.0" - resolved "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== +isexe@^2.0.0: + version "2.0.0" + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + isomorphic-timers-promises@^1.0.1: version "1.0.1" - resolved "https://registry.npmmirror.com/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz#e4137c24dbc54892de8abae3a4b5c1ffff381598" + resolved "https://registry.npmmirror.com/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz" integrity sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ== +isomorphic-unfetch@3.1.0: + version "3.1.0" + dependencies: + node-fetch "^2.6.1" + unfetch "^4.2.0" + +isows@1.0.4: + version "1.0.4" + +jest-environment-node@^29.6.3: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + 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" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + 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" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + 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" + +jest-validate@^29.6.3: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + 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" + +jest-worker@^29.6.3: + version "29.7.0" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jiti@^1.21.0: + version "1.21.6" + +joi@^17.2.1: + version "17.13.3" + resolved "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz" + integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== + dependencies: + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" + "@sideway/formula" "^3.0.1" + "@sideway/pinpoint" "^2.0.0" + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsc-android@^250231.0.0: + version "250231.0.0" + resolved "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz" + integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw== + +jsc-safe-url@^0.2.2: + version "0.2.4" + resolved "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz" + integrity sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q== + +jscodeshift@^0.14.0: + version "0.14.0" + resolved "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz" + integrity sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA== + dependencies: + "@babel/core" "^7.13.16" + "@babel/parser" "^7.13.16" + "@babel/plugin-proposal-class-properties" "^7.13.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8" + "@babel/plugin-proposal-optional-chaining" "^7.13.12" + "@babel/plugin-transform-modules-commonjs" "^7.13.8" + "@babel/preset-flow" "^7.13.13" + "@babel/preset-typescript" "^7.13.0" + "@babel/register" "^7.13.16" + babel-core "^7.0.0-bridge.0" + chalk "^4.1.2" + flow-parser "0.*" + graceful-fs "^4.2.4" + micromatch "^4.0.4" + neo-async "^2.5.0" + node-dir "^0.1.17" + recast "^0.21.0" + temp "^0.8.4" + write-file-atomic "^2.3.0" + jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-rpc-engine@^6.1.0: + version "6.1.0" + dependencies: + "@metamask/safe-event-emitter" "^2.0.0" + eth-rpc-errors "^4.0.2" + +json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: + version "1.0.1" + json5@^2.2.3: version "2.2.3" - resolved "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + resolved "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +keccak@^3.0.3: + version "3.0.4" + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyvaluestorage-interface@^1.0.0: + version "1.0.0" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +lighthouse-logger@^1.0.0: + version "1.4.2" + resolved "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz" + integrity sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g== + dependencies: + debug "^2.6.9" + marky "^1.2.2" + +listhen@^1.7.2: + version "1.7.2" + dependencies: + "@parcel/watcher" "^2.4.1" + "@parcel/watcher-wasm" "^2.4.1" + citty "^0.1.6" + clipboardy "^4.0.0" + consola "^3.2.3" + crossws "^0.2.0" + defu "^6.1.4" + get-port-please "^3.1.2" + h3 "^1.10.2" + http-shutdown "^1.2.2" + jiti "^1.21.0" + mlly "^1.6.1" + node-forge "^1.3.1" + pathe "^1.1.2" + std-env "^3.7.0" + ufo "^1.4.0" + untun "^0.1.3" + uqr "^0.1.2" + +lit-element@^3.3.0: + version "3.3.3" + dependencies: + "@lit-labs/ssr-dom-shim" "^1.1.0" + "@lit/reactive-element" "^1.3.0" + lit-html "^2.8.0" + +lit-html@^2.8.0: + version "2.8.0" + dependencies: + "@types/trusted-types" "^2.0.2" + +lit@2.8.0: + version "2.8.0" + dependencies: + "@lit/reactive-element" "^1.6.0" + lit-element "^3.3.0" + lit-html "^2.8.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" -loose-envify@^1.1.0: +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.isequal@4.5.0: + version "4.5.0" + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +logkitty@^0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz" + integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ== + dependencies: + ansi-fragments "^0.2.1" + dayjs "^1.8.15" + yargs "^15.1.0" + +loose-envify@^1.0.0, loose-envify@^1.1.0: version "1.4.0" - resolved "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^10.2.0: + version "10.4.3" + lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" magic-string@^0.30.3: version "0.30.10" - resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e" + resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.10.tgz" integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ== dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" +make-dir@^2.0.0, make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +marky@^1.2.2: + version "1.2.5" + resolved "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz" + integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== + md5.js@^1.3.4: version "1.3.5" - resolved "https://registry.npmmirror.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + resolved "https://registry.npmmirror.com/md5.js/-/md5.js-1.3.5.tgz" integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-query-parser@^2.0.2: + version "2.0.2" + dependencies: + "@babel/runtime" "^7.12.5" + +memoize-one@^5.0.0: + version "5.2.1" + resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + +merge-stream@^2.0.0: + version "2.0.0" + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +metro-babel-transformer@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.9.tgz" + integrity sha512-d76BSm64KZam1nifRZlNJmtwIgAeZhZG3fi3K+EmPOlrR8rDtBxQHDSN3fSGeNB9CirdTyabTMQCkCup6BXFSQ== + dependencies: + "@babel/core" "^7.20.0" + hermes-parser "0.20.1" + nullthrows "^1.1.1" + +metro-cache-key@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.9.tgz" + integrity sha512-hRcYGhEiWIdM87hU0fBlcGr+tHDEAT+7LYNCW89p5JhErFt/QaAkVx4fb5bW3YtXGv5BTV7AspWPERoIb99CXg== + +metro-cache@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.9.tgz" + integrity sha512-ujEdSI43QwI+Dj2xuNax8LMo8UgKuXJEdxJkzGPU6iIx42nYa1byQ+aADv/iPh5sh5a//h5FopraW5voXSgm2w== + dependencies: + metro-core "0.80.9" + rimraf "^3.0.2" + +metro-config@^0.80.3, metro-config@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-config/-/metro-config-0.80.9.tgz" + integrity sha512-28wW7CqS3eJrunRGnsibWldqgwRP9ywBEf7kg+uzUHkSFJNKPM1K3UNSngHmH0EZjomizqQA2Zi6/y6VdZMolg== + dependencies: + connect "^3.6.5" + cosmiconfig "^5.0.5" + jest-validate "^29.6.3" + metro "0.80.9" + metro-cache "0.80.9" + metro-core "0.80.9" + metro-runtime "0.80.9" + +metro-core@^0.80.3, metro-core@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-core/-/metro-core-0.80.9.tgz" + integrity sha512-tbltWQn+XTdULkGdzHIxlxk4SdnKxttvQQV3wpqqFbHDteR4gwCyTR2RyYJvxgU7HELfHtrVbqgqAdlPByUSbg== + dependencies: + lodash.throttle "^4.1.1" + metro-resolver "0.80.9" + +metro-file-map@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.9.tgz" + integrity sha512-sBUjVtQMHagItJH/wGU9sn3k2u0nrCl0CdR4SFMO1tksXLKbkigyQx4cbpcyPVOAmGTVuy3jyvBlELaGCAhplQ== + dependencies: + anymatch "^3.0.3" + debug "^2.2.0" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + invariant "^2.2.4" + jest-worker "^29.6.3" + micromatch "^4.0.4" + node-abort-controller "^3.1.1" + nullthrows "^1.1.1" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +metro-minify-terser@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.9.tgz" + integrity sha512-FEeCeFbkvvPuhjixZ1FYrXtO0araTpV6UbcnGgDUpH7s7eR5FG/PiJz3TsuuPP/HwCK19cZtQydcA2QrCw446A== + dependencies: + terser "^5.15.0" + +metro-resolver@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.9.tgz" + integrity sha512-wAPIjkN59BQN6gocVsAvvpZ1+LQkkqUaswlT++cJafE/e54GoVkMNCmrR4BsgQHr9DknZ5Um/nKueeN7kaEz9w== + +metro-runtime@^0.80.3, metro-runtime@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.9.tgz" + integrity sha512-8PTVIgrVcyU+X/rVCy/9yxNlvXsBCk5JwwkbAm/Dm+Abo6NBGtNjWF0M1Xo/NWCb4phamNWcD7cHdR91HhbJvg== + dependencies: + "@babel/runtime" "^7.0.0" + +metro-source-map@^0.80.3, metro-source-map@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.9.tgz" + integrity sha512-RMn+XS4VTJIwMPOUSj61xlxgBvPeY4G6s5uIn6kt6HB6A/k9ekhr65UkkDD7WzHYs3a9o869qU8tvOZvqeQzgw== + dependencies: + "@babel/traverse" "^7.20.0" + "@babel/types" "^7.20.0" + invariant "^2.2.4" + metro-symbolicate "0.80.9" + nullthrows "^1.1.1" + ob1 "0.80.9" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-symbolicate@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.9.tgz" + integrity sha512-Ykae12rdqSs98hg41RKEToojuIW85wNdmSe/eHUgMkzbvCFNVgcC0w3dKZEhSsqQOXapXRlLtHkaHLil0UD/EA== + dependencies: + invariant "^2.2.4" + metro-source-map "0.80.9" + nullthrows "^1.1.1" + source-map "^0.5.6" + through2 "^2.0.1" + vlq "^1.0.0" + +metro-transform-plugins@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.9.tgz" + integrity sha512-UlDk/uc8UdfLNJhPbF3tvwajyuuygBcyp+yBuS/q0z3QSuN/EbLllY3rK8OTD9n4h00qZ/qgxGv/lMFJkwP4vg== + dependencies: + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.20.0" + nullthrows "^1.1.1" + +metro-transform-worker@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.9.tgz" + integrity sha512-c/IrzMUVnI0hSVVit4TXzt3A1GiUltGVlzCmLJWxNrBGHGrJhvgePj38+GXl1Xf4Fd4vx6qLUkKMQ3ux73bFLQ== + dependencies: + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/parser" "^7.20.0" + "@babel/types" "^7.20.0" + metro "0.80.9" + metro-babel-transformer "0.80.9" + metro-cache "0.80.9" + metro-cache-key "0.80.9" + metro-minify-terser "0.80.9" + metro-source-map "0.80.9" + metro-transform-plugins "0.80.9" + nullthrows "^1.1.1" + +metro@^0.80.3, metro@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/metro/-/metro-0.80.9.tgz" + integrity sha512-Bc57Xf3GO2Xe4UWQsBj/oW6YfLPABEu8jfDVDiNmJvoQW4CO34oDPuYKe4KlXzXhcuNsqOtSxpbjCRRVjhhREg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/parser" "^7.20.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.20.0" + "@babel/types" "^7.20.0" + accepts "^1.3.7" + chalk "^4.0.0" + ci-info "^2.0.0" + connect "^3.6.5" + debug "^2.2.0" + denodeify "^1.2.1" + error-stack-parser "^2.0.6" + graceful-fs "^4.2.4" + hermes-parser "0.20.1" + image-size "^1.0.2" + invariant "^2.2.4" + jest-worker "^29.6.3" + jsc-safe-url "^0.2.2" + lodash.throttle "^4.1.1" + metro-babel-transformer "0.80.9" + metro-cache "0.80.9" + metro-cache-key "0.80.9" + metro-config "0.80.9" + metro-core "0.80.9" + metro-file-map "0.80.9" + metro-resolver "0.80.9" + metro-runtime "0.80.9" + metro-source-map "0.80.9" + metro-symbolicate "0.80.9" + metro-transform-plugins "0.80.9" + metro-transform-worker "0.80.9" + mime-types "^2.1.27" + node-fetch "^2.2.0" + nullthrows "^1.1.1" + rimraf "^3.0.2" + serialize-error "^2.1.0" + source-map "^0.5.6" + strip-ansi "^6.0.0" + throat "^5.0.0" + ws "^7.5.1" + yargs "^17.6.2" + +micro-ftch@^0.3.1: + version "0.3.1" + +micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.7" + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" miller-rabin@^4.0.0: version "4.0.1" - resolved "https://registry.npmmirror.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + resolved "https://registry.npmmirror.com/miller-rabin/-/miller-rabin-4.0.1.tgz" integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" brorand "^1.0.1" +"mime-db@>= 1.43.0 < 2": + version "1.53.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz" + integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@^2.4.1: + version "2.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mime@^3.0.0: + version "3.0.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.npmmirror.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + resolved "https://registry.npmmirror.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.npmmirror.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + resolved "https://registry.npmmirror.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== +minimatch@^3.0.2, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mipd@0.0.7: + version "0.0.7" + +mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mlly@^1.6.1, mlly@^1.7.1: + version "1.7.1" + dependencies: + acorn "^8.11.3" + pathe "^1.1.2" + pkg-types "^1.1.1" + ufo "^1.5.3" + +modern-ahocorasick@^1.0.0: + version "1.0.1" + +motion@10.16.2: + version "10.16.2" + dependencies: + "@motionone/animation" "^10.15.1" + "@motionone/dom" "^10.16.2" + "@motionone/svelte" "^10.16.2" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + "@motionone/vue" "^10.16.2" + +mri@^1.2.0: + version "1.2.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + ms@2.1.2: version "2.1.2" - resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multiformats@^9.4.2: + version "9.9.0" + nanoid@^3.3.7: version "3.3.7" - resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== +napi-wasm@^1.1.0: + version "1.1.0" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.5.0: + version "2.6.2" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nocache@^3.0.1: + version "3.0.4" + resolved "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz" + integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw== + +node-abort-controller@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz" + integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== + +node-addon-api@^2.0.0: + version "2.0.2" + +node-addon-api@^5.0.0: + version "5.1.0" + +node-addon-api@^7.0.0: + version "7.1.1" + +node-dir@^0.1.17: + version "0.1.17" + resolved "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz" + integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== + dependencies: + minimatch "^3.0.2" + +node-fetch-native@^1.6.2, node-fetch-native@^1.6.3, node-fetch-native@^1.6.4: + version "1.6.4" + +node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12: + version "2.7.0" + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1, node-forge@^1.3.1: + version "1.3.1" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.8.1" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + node-releases@^2.0.14: version "2.0.14" - resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== node-stdlib-browser@^1.2.0: version "1.2.0" - resolved "https://registry.npmmirror.com/node-stdlib-browser/-/node-stdlib-browser-1.2.0.tgz#5ddcfdf4063b88fb282979a1aa6ddab9728d5e4c" + resolved "https://registry.npmmirror.com/node-stdlib-browser/-/node-stdlib-browser-1.2.0.tgz" integrity sha512-VSjFxUhRhkyed8AtLwSCkMrJRfQ3e2lGtG3sP6FEgaLKBBbxM/dLfjRe1+iLhjvyLFW3tBQ8+c0pcOtXGbAZJg== dependencies: assert "^2.0.0" @@ -1259,14 +5099,56 @@ node-stdlib-browser@^1.2.0: util "^0.12.4" vm-browserify "^1.0.1" +node-stream-zip@^1.9.1: + version "1.15.0" + resolved "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz" + integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npm-run-path@^5.1.0: + version "5.3.0" + dependencies: + path-key "^4.0.0" + +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +ob1@0.80.9: + version "0.80.9" + resolved "https://registry.npmjs.org/ob1/-/ob1-0.80.9.tgz" + integrity sha512-v9yOxowkZbxWhKOaaTyLjIm1aLy4ebMNcSn4NYJKOAI/Qv+SkfEfszpLr2GIxsccmb2Y2HA9qtsqiIJ80ucpVA== + +obj-multiplex@^1.0.0: + version "1.0.0" + dependencies: + end-of-stream "^1.4.0" + once "^1.4.0" + readable-stream "^2.3.3" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + object-inspect@^1.13.1: version "1.13.2" - resolved "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + resolved "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.2.tgz" integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== object-is@^1.1.5: version "1.1.6" - resolved "https://registry.npmmirror.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + resolved "https://registry.npmmirror.com/object-is/-/object-is-1.1.6.tgz" integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== dependencies: call-bind "^1.0.7" @@ -1274,12 +5156,12 @@ object-is@^1.1.5: object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.4: version "4.1.5" - resolved "https://registry.npmmirror.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + resolved "https://registry.npmmirror.com/object.assign/-/object.assign-4.1.5.tgz" integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== dependencies: call-bind "^1.0.5" @@ -1287,33 +5169,149 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" +ofetch@^1.3.3: + version "1.3.4" + dependencies: + destr "^2.0.3" + node-fetch-native "^1.6.3" + ufo "^1.5.3" + +ohash@^1.1.3: + version "1.1.3" + +on-exit-leak-free@^0.2.0: + version "0.2.0" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + dependencies: + mimic-fn "^4.0.0" + +open@^6.2.0: + version "6.4.0" + resolved "https://registry.npmjs.org/open/-/open-6.4.0.tgz" + integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== + dependencies: + is-wsl "^1.1.0" + +open@^7.0.3: + version "7.4.2" + resolved "https://registry.npmjs.org/open/-/open-7.4.2.tgz" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +open@^8.4.0: + version "8.4.2" + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + os-browserify@^0.3.0: version "0.3.0" - resolved "https://registry.npmmirror.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + resolved "https://registry.npmmirror.com/os-browserify/-/os-browserify-0.3.0.tgz" integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== +outdent@^0.8.0: + version "0.8.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + dependencies: + p-try "^2.0.0" + p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" +p-try@^2.0.0: + version "2.2.0" + pako@~1.0.5: version "1.0.11" - resolved "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + resolved "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== parse-asn1@^5.0.0, parse-asn1@^5.1.7: version "5.1.7" - resolved "https://registry.npmmirror.com/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" + resolved "https://registry.npmmirror.com/parse-asn1/-/parse-asn1-5.1.7.tgz" integrity sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg== dependencies: asn1.js "^4.10.1" @@ -1323,24 +5321,56 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.7: pbkdf2 "^3.1.2" safe-buffer "^5.2.1" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + path-browserify@^1.0.1: version "1.0.1" - resolved "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + resolved "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + +path-key@^4.0.0: + version "4.0.0" + path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +pathe@^1.1.1, pathe@^1.1.2: + version "1.1.2" + pbkdf2@^3.0.3, pbkdf2@^3.1.2: version "3.1.2" - resolved "https://registry.npmmirror.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + resolved "https://registry.npmmirror.com/pbkdf2/-/pbkdf2-3.1.2.tgz" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== dependencies: create-hash "^1.1.2" @@ -1351,48 +5381,151 @@ pbkdf2@^3.0.3, pbkdf2@^3.1.2: picocolors@^1.0.0, picocolors@^1.0.1: version "1.0.1" - resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz" integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pify@^3.0.0: + version "3.0.0" + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pify@^5.0.0: + version "5.0.0" + +pino-abstract-transport@v0.5.0: + version "0.5.0" + dependencies: + duplexify "^4.1.2" + split2 "^4.0.0" + +pino-std-serializers@^4.0.0: + version "4.0.0" + +pino@7.11.0: + version "7.11.0" + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.0.0" + on-exit-leak-free "^0.2.0" + pino-abstract-transport v0.5.0 + pino-std-serializers "^4.0.0" + process-warning "^1.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.1.0" + safe-stable-stringify "^2.1.0" + sonic-boom "^2.2.1" + thread-stream "^0.15.1" + +pirates@^4.0.6: + version "4.0.6" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + pkg-dir@^5.0.0: version "5.0.0" - resolved "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" + resolved "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-5.0.0.tgz" integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== dependencies: find-up "^5.0.0" +pkg-types@^1.1.1: + version "1.1.3" + dependencies: + confbox "^0.1.7" + mlly "^1.7.1" + pathe "^1.1.2" + +pngjs@^5.0.0: + version "5.0.0" + +pony-cause@^2.1.10: + version "2.1.11" + possible-typed-array-names@^1.0.0: version "1.0.0" - resolved "https://registry.npmmirror.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + resolved "https://registry.npmmirror.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== postcss@^8.4.39: version "8.4.39" - resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.39.tgz#aa3c94998b61d3a9c259efa51db4b392e1bde0e3" + resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.39.tgz" integrity sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw== dependencies: nanoid "^3.3.7" picocolors "^1.0.1" source-map-js "^1.2.0" +preact@^10.16.0: + version "10.23.1" + +pretty-format@^26.5.2, pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + resolved "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-warning@^1.0.0: + version "1.0.0" + process@^0.11.10: version "0.11.10" - resolved "https://registry.npmmirror.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + resolved "https://registry.npmmirror.com/process/-/process-0.11.10.tgz" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== +promise@^8.3.0: + version "8.3.0" + resolved "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz" + integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== + dependencies: + asap "~2.0.6" + +prompts@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +proxy-compare@2.5.1: + version "2.5.1" + public-encrypt@^4.0.0: version "4.0.3" - resolved "https://registry.npmmirror.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + resolved "https://registry.npmmirror.com/public-encrypt/-/public-encrypt-4.0.3.tgz" integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" @@ -1402,54 +5535,197 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" +pump@^3.0.0: + version "3.0.0" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^1.4.1: version "1.4.1" - resolved "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + resolved "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz" integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== +qr-code-styling@^1.6.0-rc.1: + version "1.6.0-rc.1" + dependencies: + qrcode-generator "^1.4.3" + +qrcode-generator@^1.4.3: + version "1.4.4" + +qrcode-terminal-nooctal@^0.12.1: + version "0.12.1" + +qrcode@1.5.3: + version "1.5.3" + dependencies: + dijkstrajs "^1.0.1" + encode-utf8 "^1.0.3" + pngjs "^5.0.0" + yargs "^15.3.1" + qs@^6.11.2: version "6.12.2" - resolved "https://registry.npmmirror.com/qs/-/qs-6.12.2.tgz#5443b587f3bf73ac68968de491e5b25bafe04478" + resolved "https://registry.npmmirror.com/qs/-/qs-6.12.2.tgz" integrity sha512-x+NLUpx9SYrcwXtX7ob1gnkSems4i/mGZX5SlYxwIau6RrUSODO89TR/XDGGpn5RPWSYIB+aSfuSlV5+CmbTBg== dependencies: side-channel "^1.0.6" +query-string@7.1.3: + version "7.1.3" + dependencies: + decode-uri-component "^0.2.2" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + querystring-es3@^0.2.1: version "0.2.1" - resolved "https://registry.npmmirror.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + resolved "https://registry.npmmirror.com/querystring-es3/-/querystring-es3-0.2.1.tgz" integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== +querystring@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz" + integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +queue@6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz" + integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== + dependencies: + inherits "~2.0.3" + +quick-format-unescaped@^4.0.3: + version "4.0.4" + +radix3@^1.1.2: + version "1.1.2" + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" - resolved "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" - resolved "https://registry.npmmirror.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + resolved "https://registry.npmmirror.com/randomfill/-/randomfill-1.0.4.tgz" integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" safe-buffer "^5.1.0" -react-dom@^18.3.1: +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +react-devtools-core@^5.0.0: + version "5.3.1" + resolved "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.1.tgz" + integrity sha512-7FSb9meX0btdBQLwdFOwt6bGqvRPabmVMMslv8fgoSPqXyuGpgQe36kx8gR86XPw7aV1yVouTp6fyZ0EH+NfUw== + dependencies: + shell-quote "^1.6.1" + ws "^7" + +react-dom@^18.2.0, react-dom@^18.3.1, react-dom@>=16.8, react-dom@>=18: version "18.3.1" - resolved "https://registry.npmmirror.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + resolved "https://registry.npmmirror.com/react-dom/-/react-dom-18.3.1.tgz" integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" scheduler "^0.23.2" -react-refresh@^0.14.2: +"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@^18.0.0: + version "18.3.1" + resolved "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +react-native-webview@^11.26.0: + version "11.26.1" + dependencies: + escape-string-regexp "2.0.0" + invariant "2.2.4" + +react-native@*: + version "0.74.4" + resolved "https://registry.npmjs.org/react-native/-/react-native-0.74.4.tgz" + integrity sha512-Cox7h0UkFPY+79DsInn2BAhnmGiqKBHKoYHoPAPW8oQCPyna8jvS0hfUmHBWm/MOHSXi4NYPKd5plpD50B3B2Q== + dependencies: + "@jest/create-cache-key-function" "^29.6.3" + "@react-native-community/cli" "13.6.9" + "@react-native-community/cli-platform-android" "13.6.9" + "@react-native-community/cli-platform-ios" "13.6.9" + "@react-native/assets-registry" "0.74.86" + "@react-native/codegen" "0.74.86" + "@react-native/community-cli-plugin" "0.74.86" + "@react-native/gradle-plugin" "0.74.86" + "@react-native/js-polyfills" "0.74.86" + "@react-native/normalize-colors" "0.74.86" + "@react-native/virtualized-lists" "0.74.86" + abort-controller "^3.0.0" + anser "^1.4.9" + ansi-regex "^5.0.0" + base64-js "^1.5.1" + chalk "^4.0.0" + event-target-shim "^5.0.1" + flow-enums-runtime "^0.0.6" + invariant "^2.2.4" + jest-environment-node "^29.6.3" + jsc-android "^250231.0.0" + memoize-one "^5.0.0" + metro-runtime "^0.80.3" + metro-source-map "^0.80.3" + mkdirp "^0.5.1" + nullthrows "^1.1.1" + pretty-format "^26.5.2" + promise "^8.3.0" + react-devtools-core "^5.0.0" + react-refresh "^0.14.0" + react-shallow-renderer "^16.15.0" + regenerator-runtime "^0.13.2" + scheduler "0.24.0-canary-efb381bbf-20230505" + stacktrace-parser "^0.1.10" + whatwg-fetch "^3.0.0" + ws "^6.2.2" + yargs "^17.6.2" + +react-refresh@^0.14.0, react-refresh@^0.14.2: version "0.14.2" - resolved "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" + resolved "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.14.2.tgz" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== +react-remove-scroll-bar@^2.3.4: + version "2.3.6" + dependencies: + react-style-singleton "^2.2.1" + tslib "^2.0.0" + +react-remove-scroll@2.5.7: + version "2.5.7" + dependencies: + react-remove-scroll-bar "^2.3.4" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" + react-router-dom@^6.24.1: version "6.24.1" - resolved "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.24.1.tgz#b1a22f7d6c5a1bfce30732bd370713f991ab4de4" + resolved "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.24.1.tgz" integrity sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg== dependencies: "@remix-run/router" "1.17.1" @@ -1457,60 +5733,223 @@ react-router-dom@^6.24.1: react-router@6.24.1: version "6.24.1" - resolved "https://registry.npmmirror.com/react-router/-/react-router-6.24.1.tgz#5a3bbba0000afba68d42915456ca4c806f37a7de" + resolved "https://registry.npmmirror.com/react-router/-/react-router-6.24.1.tgz" integrity sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg== dependencies: "@remix-run/router" "1.17.1" -react@^18.3.1: +react-shallow-renderer@^16.15.0: + version "16.15.0" + resolved "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz" + integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA== + dependencies: + object-assign "^4.1.1" + react-is "^16.12.0 || ^17.0.0 || ^18.0.0" + +react-style-singleton@^2.2.1: + version "2.2.1" + dependencies: + get-nonce "^1.0.0" + invariant "^2.2.4" + tslib "^2.0.0" + +react@*, "react@^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18.0.0, react@^18.2.0, react@^18.3.1, react@>=16.8, react@>=18, react@18.2.0: version "18.3.1" - resolved "https://registry.npmmirror.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + resolved "https://registry.npmmirror.com/react/-/react-18.3.1.tgz" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: - loose-envify "^1.1.0" + loose-envify "^1.1.0" + +readable-stream@^2.3.3: + version "2.3.8" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^2.3.8: + version "2.3.8" + resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0, readable-stream@^3.6.2: + version "3.6.2" + resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +"readable-stream@^3.6.2 || ^4.4.2": + version "4.5.2" + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + +readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + dependencies: + picomatch "^2.2.1" + +readline@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz" + integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== + +real-require@^0.1.0: + version "0.1.0" + +recast@^0.21.0: + version "0.21.5" + resolved "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz" + integrity sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg== + dependencies: + ast-types "0.15.2" + esprima "~4.0.0" + source-map "~0.6.1" + tslib "^2.0.1" + +regenerate-unicode-properties@^10.1.0: + version "10.1.1" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== + dependencies: + regenerate "^1.4.2" -readable-stream@^2.3.8: - version "2.3.8" - resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.2: + version "0.13.11" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regenerator-runtime@^0.14.0: + version "0.14.1" + +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" + "@babel/runtime" "^7.8.4" -readable-stream@^3.5.0, readable-stream@^3.6.0: - version "3.6.2" - resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" + "@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" + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +require-directory@^2.1.1: + version "2.1.1" + +require-main-filename@^2.0.0: + version "2.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== -resolve@^1.17.0: +resolve@^1.14.2, resolve@^1.17.0: version "1.22.8" - resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" - resolved "https://registry.npmmirror.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + resolved "https://registry.npmmirror.com/ripemd160/-/ripemd160-2.0.2.tgz" integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" inherits "^2.0.1" -rollup@^4.13.0: +rollup-plugin-visualizer@^5.9.2: + version "5.12.0" + dependencies: + open "^8.4.0" + picomatch "^2.3.1" + source-map "^0.7.4" + yargs "^17.5.1" + +rollup@^1.20.0||^2.0.0||^3.0.0||^4.0.0, rollup@^4.13.0, "rollup@2.x || 3.x || 4.x": version "4.18.0" - resolved "https://registry.npmmirror.com/rollup/-/rollup-4.18.0.tgz#497f60f0c5308e4602cf41136339fbf87d5f5dda" + resolved "https://registry.npmmirror.com/rollup/-/rollup-4.18.0.tgz" integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg== dependencies: "@types/estree" "1.0.5" @@ -1533,31 +5972,113 @@ rollup@^4.13.0: "@rollup/rollup-win32-x64-msvc" "4.18.0" fsevents "~2.3.2" +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-stable-stringify@^2.1.0: + version "2.4.3" + scheduler@^0.23.2: version "0.23.2" - resolved "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + resolved "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.2.tgz" integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" +scheduler@0.24.0-canary-efb381bbf-20230505: + version "0.24.0-canary-efb381bbf-20230505" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz" + integrity sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA== + dependencies: + loose-envify "^1.1.0" + +secp256k1@^5.0.0: + version "5.0.0" + dependencies: + elliptic "^6.5.4" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" + +selfsigned@^2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== + dependencies: + "@types/node-forge" "^1.3.0" + node-forge "^1" + +semver@^5.6.0: + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + semver@^6.3.1: version "6.3.1" - resolved "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^7.3.8, semver@^7.5.2, semver@^7.5.4: + version "7.6.3" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz" + integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw== + +serve-static@^1.13.1: + version "1.15.0" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + set-function-length@^1.2.1: version "1.2.2" - resolved "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + resolved "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== dependencies: define-data-property "^1.1.4" @@ -1569,20 +6090,45 @@ set-function-length@^1.2.1: setimmediate@^1.0.4: version "1.0.5" - resolved "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + resolved "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz" integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== -sha.js@^2.4.0, sha.js@^2.4.8: +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: version "2.4.11" - resolved "https://registry.npmmirror.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + resolved "https://registry.npmmirror.com/sha.js/-/sha.js-2.4.11.tgz" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" safe-buffer "^5.0.1" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + +shell-quote@^1.6.1, shell-quote@^1.7.3: + version "1.8.1" + resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + side-channel@^1.0.6: version "1.0.6" - resolved "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + resolved "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz" integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: call-bind "^1.0.7" @@ -1590,14 +6136,134 @@ side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.1.0: + version "4.1.0" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +socket.io-client@^4.5.1: + version "4.7.5" + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.2" + engine.io-client "~6.5.2" + socket.io-parser "~4.2.4" + +socket.io-parser@~4.2.4: + version "4.2.4" + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + +sonic-boom@^2.2.1: + version "2.8.0" + dependencies: + atomic-sleep "^1.0.0" + source-map-js@^1.2.0: version "1.2.0" - resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.0.tgz" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== +source-map-support@^0.5.16, source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3, source-map@^0.7.4: + version "0.7.4" + +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split-on-first@^1.0.0: + version "1.1.0" + +split2@^4.0.0: + version "4.2.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +std-env@^3.7.0: + version "3.7.0" + stream-browserify@^3.0.0: version "3.0.0" - resolved "https://registry.npmmirror.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + resolved "https://registry.npmmirror.com/stream-browserify/-/stream-browserify-3.0.0.tgz" integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== dependencies: inherits "~2.0.4" @@ -1605,7 +6271,7 @@ stream-browserify@^3.0.0: stream-http@^3.2.0: version "3.2.0" - resolved "https://registry.npmmirror.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5" + resolved "https://registry.npmmirror.com/stream-http/-/stream-http-3.2.0.tgz" integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A== dependencies: builtin-status-codes "^3.0.0" @@ -1613,83 +6279,338 @@ stream-http@^3.2.0: readable-stream "^3.6.0" xtend "^4.0.2" -string_decoder@^1.0.0, string_decoder@^1.1.1: +stream-shift@^1.0.2: + version "1.0.3" + +strict-uri-encode@^2.0.0: + version "2.0.0" + +string_decoder@^1.0.0, string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" - resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + dependencies: + ansi-regex "^5.0.1" + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-final-newline@^3.0.0: + version "3.0.0" + +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + +sudo-prompt@^9.0.0: + version "9.2.1" + resolved "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz" + integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw== + +superstruct@^1.0.3: + version "1.0.4" + supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.2.0" + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +system-architecture@^0.1.0: + version "0.1.0" + +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + +temp@^0.8.4: + version "0.8.4" + resolved "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz" + integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== + dependencies: + rimraf "~2.6.2" + +terser@^5.15.0, terser@^5.4.0: + version "5.31.3" + resolved "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz" + integrity sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +thread-stream@^0.15.1: + version "0.15.2" + dependencies: + real-require "^0.1.0" + +throat@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz" + integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== + +through2@^2.0.1: + version "2.0.5" + resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + timers-browserify@^2.0.4: version "2.0.12" - resolved "https://registry.npmmirror.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + resolved "https://registry.npmmirror.com/timers-browserify/-/timers-browserify-2.0.12.tgz" integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== dependencies: setimmediate "^1.0.4" +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== +to-regex-range@^5.0.1: + version "5.0.1" + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.1: + version "2.6.3" + +tslib@1.14.1: + version "1.14.1" + +tslib@2.4.0: + version "2.4.0" + tty-browserify@0.0.1: version "0.0.1" - resolved "https://registry.npmmirror.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + resolved "https://registry.npmmirror.com/tty-browserify/-/tty-browserify-0.0.1.tgz" integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== -typescript@^5.5.2: +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +typescript@^5.5.2, typescript@>=5.0.4: version "5.5.3" - resolved "https://registry.npmmirror.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa" + resolved "https://registry.npmmirror.com/typescript/-/typescript-5.5.3.tgz" integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ== +ua-parser-js@^1.0.37: + version "1.0.38" + +ufo@^1.4.0, ufo@^1.5.3: + version "1.5.4" + +uint8arrays@^3.0.0: + version "3.1.1" + dependencies: + multiformats "^9.4.2" + +uint8arrays@3.1.0: + version "3.1.0" + dependencies: + multiformats "^9.4.2" + +uncrypto@^0.1.3: + version "0.1.3" + undici-types@~5.26.4: version "5.26.5" - resolved "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + resolved "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.11.1: + version "6.11.1" + +unenv@^1.9.0: + version "1.10.0" + dependencies: + consola "^3.2.3" + defu "^6.1.4" + mime "^3.0.0" + node-fetch-native "^1.6.4" + pathe "^1.1.2" + +unfetch@^4.2.0: + version "4.2.0" + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unstorage@^1.9.0: + version "1.10.2" + dependencies: + anymatch "^3.1.3" + chokidar "^3.6.0" + destr "^2.0.3" + h3 "^1.11.1" + listhen "^1.7.2" + lru-cache "^10.2.0" + mri "^1.2.0" + node-fetch-native "^1.6.2" + ofetch "^1.3.3" + ufo "^1.4.0" + +untun@^0.1.3: + version "0.1.3" + dependencies: + citty "^0.1.5" + consola "^3.2.3" + pathe "^1.1.1" + update-browserslist-db@^1.0.16: version "1.1.0" - resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz" integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== dependencies: escalade "^3.1.2" picocolors "^1.0.1" +uqr@^0.1.2: + version "0.1.2" + url@^0.11.0: version "0.11.3" - resolved "https://registry.npmmirror.com/url/-/url-0.11.3.tgz#6f495f4b935de40ce4a0a52faee8954244f3d3ad" + resolved "https://registry.npmmirror.com/url/-/url-0.11.3.tgz" integrity sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw== dependencies: punycode "^1.4.1" qs "^6.11.2" +use-callback-ref@^1.3.0: + version "1.3.2" + dependencies: + tslib "^2.0.0" + +use-sidecar@^1.1.2: + version "1.1.2" + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +use-sync-external-store@1.2.0: + version "1.2.0" + +utf-8-validate@^5.0.2, utf-8-validate@>=5.0.2: + version "5.0.10" + dependencies: + node-gyp-build "^4.3.0" + util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util@^0.12.4, util@^0.12.5: version "0.12.5" - resolved "https://registry.npmmirror.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + resolved "https://registry.npmmirror.com/util/-/util-0.12.5.tgz" integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== dependencies: inherits "^2.0.3" @@ -1698,17 +6619,54 @@ util@^0.12.4, util@^0.12.5: is-typed-array "^1.1.3" which-typed-array "^1.1.2" +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^8.3.2: + version "8.3.2" + +uuid@^9.0.1: + version "9.0.1" + +valtio@1.11.2: + version "1.11.2" + dependencies: + proxy-compare "2.5.1" + use-sync-external-store "1.2.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +viem@^2.1.1, viem@^2.18.7, viem@2.x: + version "2.18.7" + resolved "https://registry.npmjs.org/viem/-/viem-2.18.7.tgz" + integrity sha512-0Xy5ypk+n4lYthsvC96jsZE97quKoq1t53RrbhKElmq84Dt705uUjQDgH0/LqAV02Oe6341M3jPTU9JLbs2K2Q== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.4.0" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + abitype "1.0.5" + isows "1.0.4" + webauthn-p256 "0.0.5" + ws "8.17.1" + vite-plugin-node-polyfills@^0.22.0: version "0.22.0" - resolved "https://registry.npmmirror.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz#d0afcf82eb985fc02244620d7cec1ddd1c6e0864" + resolved "https://registry.npmmirror.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz" integrity sha512-F+G3LjiGbG8QpbH9bZ//GSBr9i1InSTkaulfUHFa9jkLqVGORFBoqc2A/Yu5Mmh1kNAbiAeKeK+6aaQUf3x0JA== dependencies: "@rollup/plugin-inject" "^5.0.5" node-stdlib-browser "^1.2.0" -vite@^5.3.1: +"vite@^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "vite@^4.2.0 || ^5.0.0", vite@^5.3.1: version "5.3.3" - resolved "https://registry.npmmirror.com/vite/-/vite-5.3.3.tgz#5265b1f0a825b3b6564c2d07524777c83e3c04c2" + resolved "https://registry.npmmirror.com/vite/-/vite-5.3.3.tgz" integrity sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A== dependencies: esbuild "^0.21.3" @@ -1717,14 +6675,71 @@ vite@^5.3.1: optionalDependencies: fsevents "~2.3.3" +vlq@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz" + integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== + vm-browserify@^1.0.1: version "1.1.2" - resolved "https://registry.npmmirror.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + resolved "https://registry.npmmirror.com/vm-browserify/-/vm-browserify-1.1.2.tgz" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +wagmi@^2.12.2, wagmi@^2.9.0: + version "2.12.2" + resolved "https://registry.npmjs.org/wagmi/-/wagmi-2.12.2.tgz" + integrity sha512-gIZdAgmHJjENdOdkD/Zpu85NR16k/uMB3H/yGBz1q9bDAE8oguuBxRUEhuMt6jAC95RB96+7hMVfL9kBtHnu+g== + dependencies: + "@wagmi/connectors" "5.1.2" + "@wagmi/core" "2.13.1" + use-sync-external-store "1.2.0" + +walker@^1.0.7: + version "1.0.8" + resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +webauthn-p256@0.0.5: + version "0.0.5" + dependencies: + "@noble/curves" "^1.4.0" + "@noble/hashes" "^1.4.0" + +webextension-polyfill@^0.10.0: + version "0.10.0" + +"webextension-polyfill@>=0.10.0 <1.0": + version "0.12.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + +whatwg-fetch@^3.0.0: + version "3.6.20" + resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz" + integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== + +whatwg-url@^5.0.0: + version "5.0.0" + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-module@^2.0.0: + version "2.0.1" + which-typed-array@^1.1.14, which-typed-array@^1.1.2: version "1.1.15" - resolved "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + resolved "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.15.tgz" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== dependencies: available-typed-arrays "^1.0.7" @@ -1733,17 +6748,141 @@ which-typed-array@^1.1.14, which-typed-array@^1.1.2: gopd "^1.0.1" has-tostringtag "^1.0.2" -xtend@^4.0.2: +which@^2.0.1: + version "2.0.2" + dependencies: + isexe "^2.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + +write-file-atomic@^2.3.0: + version "2.4.3" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +ws@*, ws@~8.17.1, ws@8.17.1: + version "8.17.1" + +ws@^6.2.2: + version "6.2.3" + resolved "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz" + integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA== + dependencies: + async-limiter "~1.0.0" + +ws@^7: + version "7.5.10" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +ws@^7.5.1: + version "7.5.10" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +xmlhttprequest-ssl@~2.0.0: + version "2.0.0" + +xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" - resolved "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + resolved "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +y18n@^4.0.0: + version "4.0.3" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^3.0.2: version "3.1.1" - resolved "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + resolved "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yaml@^2.2.1: + version "2.5.0" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz" + integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw== + +yargs-parser@^18.1.2: + version "18.1.3" + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^15.1.0, yargs@^15.3.1: + version "15.4.1" + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.5.1: + version "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" + +yargs@^17.6.2: + version "17.7.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + 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" + yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zustand@4.4.1: + version "4.4.1" + dependencies: + use-sync-external-store "1.2.0" From a3a3e0ef9b718fe4182d98fcaf968882cd602379 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 2 Aug 2024 10:56:54 +0800 Subject: [PATCH 61/85] chore: Add tool-call models --- src/openagent/conf/llm_provider.py | 9 +++++---- src/openagent/ui/profile.py | 17 +++++++++++------ src/openagent/workflows/supervisor_chain.py | 10 ++++++---- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/openagent/conf/llm_provider.py b/src/openagent/conf/llm_provider.py index 69fff49b..7bf37244 100644 --- a/src/openagent/conf/llm_provider.py +++ b/src/openagent/conf/llm_provider.py @@ -10,15 +10,16 @@ from openagent.conf.env import settings +TOOL_CALL_MODELS = ["llama3.1", "mistral-nemo", "mistral", "mistral-large", "mixtral", "command-r-plus", + "deepseek-coder-v2", "llama3-groq-tool-use", "firefunction-v2"] + @memoize def get_available_ollama_providers(): try: ollama_list = ollama.list() - models_ = list(map(lambda x: x["name"], ollama_list["models"])) - all_ = ["llama3.1:latest", "mistral:latest", "deepseek-coder-v2"] - - available_models = list(filter(lambda x: x in all_, models_)) + models_ = list(map(lambda x: x["name"].split(":")[0], ollama_list["models"])) + available_models = list(filter(lambda x: x in TOOL_CALL_MODELS, models_)) return available_models except Exception as e: logger.warning(f"Failed to get available ollama providers: {e}") diff --git a/src/openagent/ui/profile.py b/src/openagent/ui/profile.py index a11917ff..2013810b 100644 --- a/src/openagent/ui/profile.py +++ b/src/openagent/ui/profile.py @@ -1,5 +1,7 @@ import chainlit as cl +from openagent.conf.llm_provider import TOOL_CALL_MODELS + provider_key_to_profile_info = { "gpt-3.5-turbo": { "name": "GPT-3.5", @@ -21,18 +23,21 @@ "markdown_description": "The underlying LLM model is **Gemini 1.5 Flash**.", "icon": "https://custom.typingmind.com/assets/models/gemini.png", }, - "llama3.1:latest": { - "name": "LLAMA 3.1", - "markdown_description": "The underlying LLM model is **LLAMA 3.1**.", - "icon": "https://custom.typingmind.com/assets/models/llama.png", - }, + } +for model in TOOL_CALL_MODELS: + provider_key_to_profile_info[model] = { + "name": model, + "markdown_description": f"The underlying LLM model is **{model}**.", + "icon": "https://ollama.com/public/ollama.png", + } def provider_to_profile(provider_key): profile_info = provider_key_to_profile_info.get(provider_key) if profile_info: - return cl.ChatProfile(name=profile_info["name"], markdown_description=profile_info["markdown_description"], icon=profile_info["icon"]) + return cl.ChatProfile(name=profile_info["name"], markdown_description=profile_info["markdown_description"], + icon=profile_info["icon"]) return None diff --git a/src/openagent/workflows/supervisor_chain.py b/src/openagent/workflows/supervisor_chain.py index 6ceffc96..ea21dca4 100644 --- a/src/openagent/workflows/supervisor_chain.py +++ b/src/openagent/workflows/supervisor_chain.py @@ -2,6 +2,7 @@ from langchain_core.output_parsers import JsonOutputToolsParser from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.tools import tool +from langchain_google_vertexai import ChatVertexAI from loguru import logger from openagent.conf.llm_provider import get_current_llm @@ -53,9 +54,10 @@ def extract_next(x): next__ = "fallback_agent" return {"next": next__} + tool_choice = None if (isinstance(llm, ChatVertexAI) and llm.model_name == "gemini-1.5-flash") else "route" return ( - prompt - | llm.bind_tools(tools=[route], tool_choice="route" if llm.model_name != "gemini-1.5-flash" else None) - | JsonOutputToolsParser() - | extract_next + prompt + | llm.bind_tools(tools=[route], tool_choice=tool_choice) + | JsonOutputToolsParser() + | extract_next ) From 7f20ecb2630efedc1b59d7c51418a2e6c615d26b Mon Sep 17 00:00:00 2001 From: FrankLi123 Date: Fri, 2 Aug 2024 11:03:23 +0800 Subject: [PATCH 62/85] fix: fix issues in test cases and some expert logics --- src/openagent/experts/defi_expert.py | 27 +- src/openagent/experts/transfer_expert.py | 2 - src/openagent/ui/app.py | 3 +- src/poetry.lock | 233 ++++++++++-------- src/pyproject.toml | 2 + .../agent_trajectory/asset_management.py | 16 ++ src/tests/agent_trajectory/feed_explore.py | 2 +- src/widget/src/components/TransferWidget.tsx | 6 +- 8 files changed, 176 insertions(+), 115 deletions(-) diff --git a/src/openagent/experts/defi_expert.py b/src/openagent/experts/defi_expert.py index a5cd41ef..d609387a 100644 --- a/src/openagent/experts/defi_expert.py +++ b/src/openagent/experts/defi_expert.py @@ -10,7 +10,7 @@ # Define the defi activities and common DeFi networks SUPPORTED_NETWORKS = ["arbitrum", "avax", "base", "binance-smart-chain", "ethereum", "gnosis", "linea", "optimism", "polygon"] -DEFI_ACTIVITIES = ["swap", "liquidity", "staking"] +DEFI_ACTIVITIES = ["swap", "liquidity", "staking", "all"] # Define the schema for input parameters class ParamSchema(BaseModel): @@ -26,7 +26,7 @@ class DeFiExpert(BaseTool): A tool for fetching and analyzing DeFi activities across various networks. """ name = "DeFiExecutor" - description = "Use this tool to get the user's DeFi activities (swaps, liquidity provision, staking) across various networks." + description = "Use this tool to get the user's DeFi activities (swaps, liquidity provision, staking, all) across various networks." args_schema: Type[ParamSchema] = ParamSchema async def _run( @@ -76,15 +76,26 @@ async def fetch_defi_feeds(self, address: str, network: Optional[str] = None, ac filters = ActivityFilter(network=[network] if network else None) pagination = PaginationOptions(limit=10, action_limit=10) - # Dynamically select the appropriate fetch method in the SDK based on activity type - fetch_method = getattr(client, f"fetch_exchange_{activity_type.lower()}_activities") - activities = fetch_method(account=address, filters=filters, pagination=pagination) + # Handle 'all' activity type + if activity_type == "all": + activities = [] + for act_type in ["swap", "liquidity", "staking"]: + fetch_method = getattr(client, f"fetch_exchange_{act_type}_activities") + act_results = fetch_method(account=address, filters=filters, pagination=pagination) + activities.extend(act_results.data) + else: + fetch_method = getattr(client, f"fetch_exchange_{activity_type}_activities") + activities_result = fetch_method(account=address, filters=filters, pagination=pagination) + activities = activities_result.data # Check if any activities were found - if not activities.data: - return f"No {activity_type} activities found for {address}{' on ' + network if network else ''}." + if not activities: + return f"No {'DeFi' if activity_type == 'all' else activity_type} activities found for {address}{' on ' + network if network else ''}." - result = FEED_PROMPT.format(activities_data=activities.dict(), activity_type=activity_type) + # Format the result + activities_data = [activity.model_dump() for activity in activities] + result = FEED_PROMPT.format(activities_data=activities_data, + activity_type="DeFi" if activity_type == "all" else activity_type) return result except Exception as e: diff --git a/src/openagent/experts/transfer_expert.py b/src/openagent/experts/transfer_expert.py index c3f3567e..b7731318 100644 --- a/src/openagent/experts/transfer_expert.py +++ b/src/openagent/experts/transfer_expert.py @@ -16,7 +16,6 @@ class Transfer(BaseModel): token: str token_address: str chain_id: str - chain_name: str amount: str logoURI: str # noqa decimals: int @@ -117,7 +116,6 @@ async def fetch_transfer(to_address: str, token: str, chain_name: str, amount: s token=get_token_data_by_key(token_info, "symbol"), token_address=get_token_data_by_key(token_info, "address"), chain_id=chain_id, - chain_name=chain_name, amount=res.get("amount", "1"), logoURI=get_token_data_by_key(token_info, "logoURI"), decimals=get_token_data_by_key(token_info, "decimals"), diff --git a/src/openagent/ui/app.py b/src/openagent/ui/app.py index 06696fbc..2ee70532 100644 --- a/src/openagent/ui/app.py +++ b/src/openagent/ui/app.py @@ -143,9 +143,8 @@ async def handle_tool_end(event, msg): token = transfer_dict["token"] to_address = transfer_dict["to_address"] amount = transfer_dict["amount"] - chain_name = transfer_dict.get("chain_name", "ethereum") - url = f"/widget/transfer?token={token}" f"&amount={amount}&toAddress={to_address}&chainName={chain_name}" + url = f"/widget/transfer?token={token}&amount={amount}&toAddress={to_address}" iframe_html = f"""