From ac43c73df044fd1bde4d88091515b760c6af0d2e Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Sun, 11 Jan 2026 22:39:43 +0800 Subject: [PATCH 01/69] fix pillow --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index aa7e6dc93..b1585b442 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ tiktoken~=0.9.0 html2text~=2024.2.26 gymnasium~=1.1.1 -pillow~=11.1.0 +pillow>=10.4,<11 browsergym~=0.13.3 uvicorn~=0.34.0 unidiff~=0.7.5 From 5bdb362aa7e9e29db71c6605965ed2b952d0b363 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Sun, 11 Jan 2026 22:57:13 +0800 Subject: [PATCH 02/69] =?UTF-8?q?=E8=AF=B7=E4=BF=AE=E6=94=B9=20OpenManus?= =?UTF-8?q?=20=E4=B8=AD=E7=9A=84=20main.py=20/=20cli.py=EF=BC=88=E4=BB=A5?= =?UTF-8?q?=E5=AE=9E=E9=99=85=E5=85=A5=E5=8F=A3=E6=96=87=E4=BB=B6=E4=B8=BA?= =?UTF-8?q?=E5=87=86=EF=BC=89=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 禁止在入口文件中直接实例化或运行任何 Agent 2. 如果存在 run_task / run_agent / main_execute 之类逻辑,请注释或移除 3. 入口文件只保留启动服务或占位逻辑 4. 不引入新功能,不改变任何 Agent 行为 5. 代码必须仍可 import,不要求可执行 请只修改入口相关文件,不要改 agent、tool、memory 代码。 --- main.py | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/main.py b/main.py index 259c735be..a03a85256 100644 --- a/main.py +++ b/main.py @@ -1,35 +1,26 @@ import argparse import asyncio -from app.agent.manus import Manus from app.logger import logger async def main(): - # Parse command line arguments - parser = argparse.ArgumentParser(description="Run Manus agent with a prompt") - parser.add_argument( - "--prompt", type=str, required=False, help="Input prompt for the agent" + """Placeholder entry point. + + The CLI no longer instantiates or runs agents directly. Use the library + APIs or dedicated launcher scripts to start agents or services. + """ + + parser = argparse.ArgumentParser( + description="OpenManus entry point (agent execution disabled)" + ) + parser.add_argument("--prompt", type=str, required=False, help="No-op placeholder") + _ = parser.parse_args() + + logger.info( + "OpenManus CLI placeholder: agent execution is intentionally disabled in" + " this entry script." ) - args = parser.parse_args() - - # Create and initialize Manus agent - agent = await Manus.create() - try: - # Use command line prompt if provided, otherwise ask for input - prompt = args.prompt if args.prompt else input("Enter your prompt: ") - if not prompt.strip(): - logger.warning("Empty prompt provided.") - return - - logger.warning("Processing your request...") - await agent.run(prompt) - logger.info("Request processing completed.") - except KeyboardInterrupt: - logger.warning("Operation interrupted.") - finally: - # Ensure agent resources are cleaned up before exiting - await agent.cleanup() if __name__ == "__main__": From 51c39c56cb84b1d3716b0ceb2fd6a1fb80557e44 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Sun, 11 Jan 2026 23:00:32 +0800 Subject: [PATCH 03/69] =?UTF-8?q?=20=E8=AF=B7=E6=96=B0=E5=A2=9E=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E6=96=87=E4=BB=B6=20core/task.py=EF=BC=8C=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E4=B8=80=E4=B8=AA=20Task=20=E7=B1=BB=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 要求: 1. Task 必须包含: - id(字符串) - status(CREATED / RUNNING / DONE / FAILED / INTERRUPTED) - interrupt_flag(bool) - event_queue(线程安全或 asyncio 兼容) 2. 提供方法: - emit(type: str, data: Any) - interrupt() - is_interrupted() 3. 不依赖 FastAPI / WebSocket 4. 不修改任何已有代码 5. Task 设计要尽量通用,后续可被 agent / tool 使用 只新增文件,不改已有文件。 --- core/task.py | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 core/task.py diff --git a/core/task.py b/core/task.py new file mode 100644 index 000000000..163d15de1 --- /dev/null +++ b/core/task.py @@ -0,0 +1,76 @@ +from __future__ import annotations + +import asyncio +import queue +import threading +from dataclasses import dataclass, field +from enum import Enum +from typing import Any, Optional, Union + + +class TaskStatus(str, Enum): + CREATED = "CREATED" + RUNNING = "RUNNING" + DONE = "DONE" + FAILED = "FAILED" + INTERRUPTED = "INTERRUPTED" + + +EventQueue = Union[asyncio.Queue, queue.Queue] + + +@dataclass +class Task: + """Generic task container for agents/tools.""" + + id: str + status: TaskStatus = TaskStatus.CREATED + interrupt_flag: bool = False + event_queue: EventQueue = field(default_factory=asyncio.Queue) + _loop: Optional[asyncio.AbstractEventLoop] = field( + default=None, repr=False, compare=False + ) + + def __post_init__(self) -> None: + # Capture the running loop if we are created inside one; helps thread-safe emits. + if isinstance(self.event_queue, asyncio.Queue) and self._loop is None: + try: + self._loop = asyncio.get_running_loop() + except RuntimeError: + self._loop = None + + def emit(self, type: str, data: Any) -> None: + """Push an event into the queue.""" + event = {"type": type, "data": data} + + if isinstance(self.event_queue, asyncio.Queue): + loop = self._loop + if loop is None or not loop.is_running(): + try: + loop = asyncio.get_running_loop() + except RuntimeError: + loop = None + + if loop and loop.is_running(): + # Schedule thread-safe put when an event loop is available. + loop.call_soon_threadsafe(self.event_queue.put_nowait, event) + else: + # Fallback for cases without a running loop. + self.event_queue.put_nowait(event) + elif isinstance(self.event_queue, queue.Queue): + self.event_queue.put_nowait(event) + else: + raise TypeError("event_queue must be an asyncio.Queue or queue.Queue instance") + + def interrupt(self) -> None: + """Mark task as interrupted.""" + self.interrupt_flag = True + if self.status not in (TaskStatus.DONE, TaskStatus.FAILED): + self.status = TaskStatus.INTERRUPTED + + def is_interrupted(self) -> bool: + """Return whether the task has been interrupted.""" + return self.interrupt_flag + + +__all__ = ["Task", "TaskStatus", "EventQueue"] From 6a21f503817cb1599f23ceb76e54fbf31a565b53 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Sun, 11 Jan 2026 23:03:16 +0800 Subject: [PATCH 04/69] =?UTF-8?q?=E8=AF=B7=E6=96=B0=E5=A2=9E=20core/task?= =?UTF-8?q?=5Fregistry.py=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/task_registry.py | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 core/task_registry.py diff --git a/core/task_registry.py b/core/task_registry.py new file mode 100644 index 000000000..b2513888d --- /dev/null +++ b/core/task_registry.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import threading +import uuid +from typing import Dict, Optional + +from core.task import Task + + +class TaskRegistry: + """In-memory registry for Task objects. + + Designed to be framework-agnostic so it can back future HTTP or WebSocket + layers without introducing those dependencies here. + """ + + def __init__(self) -> None: + self._tasks: Dict[str, Task] = {} + self._lock = threading.RLock() + + def create_task(self, task_id: Optional[str] = None, **task_kwargs) -> Task: + """Create and register a new task. + + task_id: Optional explicit id; if omitted, a UUID4 string is used. + task_kwargs: Forwarded to Task constructor (e.g., custom event_queue). + """ + with self._lock: + tid = task_id or str(uuid.uuid4()) + if tid in self._tasks: + raise ValueError(f"Task with id '{tid}' already exists") + + task = Task(id=tid, **task_kwargs) + self._tasks[tid] = task + return task + + def get_task(self, task_id: str) -> Optional[Task]: + """Retrieve a task by id.""" + with self._lock: + return self._tasks.get(task_id) + + def interrupt_task(self, task_id: str) -> Optional[Task]: + """Interrupt a task if it exists; returns the task or None.""" + with self._lock: + task = self._tasks.get(task_id) + if task is None: + return None + task.interrupt() + return task + + +__all__ = ["TaskRegistry"] From 45119885607b513e92f03fcf6bfa5f4205b2c513 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Sun, 11 Jan 2026 23:16:20 +0800 Subject: [PATCH 05/69] =?UTF-8?q?=E8=AF=B7=E4=BF=AE=E6=94=B9=E6=89=80?= =?UTF-8?q?=E6=9C=89=20Agent=20=E7=9A=84=20run=20/=20execute=20=E5=85=A5?= =?UTF-8?q?=E5=8F=A3=E6=96=B9=E6=B3=95=EF=BC=88=E5=A6=82=20orchestrator=20?= =?UTF-8?q?/=20planner=20/=20executor=EF=BC=89=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 要求: 1. 所有 Agent 的入口方法签名改为: run(task: Task, input: Any) 2. Agent 内部不得直接 print / logging 作为输出 3. 所有“对外可见”的信息必须通过: task.emit(event_type, data) 4. 在每个主要执行步骤前,检查: if task.is_interrupted(): raise TaskInterrupted 5. 不改变 Agent 的决策逻辑,不优化 prompt,不新增能力 请只修改 Agent 相关文件。 --- app/agent/base.py | 90 +++++++++++++---------- app/agent/browser.py | 11 ++- app/agent/manus.py | 16 ++-- app/agent/mcp.py | 41 ++++++----- app/agent/react.py | 18 +++-- app/agent/sandbox_agent.py | 21 ++---- app/agent/toolcall.py | 147 ++++++++++++++++++++++--------------- 7 files changed, 191 insertions(+), 153 deletions(-) diff --git a/app/agent/base.py b/app/agent/base.py index 65f660073..a848ade8d 100644 --- a/app/agent/base.py +++ b/app/agent/base.py @@ -1,13 +1,17 @@ from abc import ABC, abstractmethod from contextlib import asynccontextmanager -from typing import List, Optional +from typing import Any, List, Optional from pydantic import BaseModel, Field, model_validator from app.llm import LLM -from app.logger import logger from app.sandbox.client import SANDBOX_CLIENT from app.schema import ROLE_TYPE, AgentState, Memory, Message +from core.task import Task + + +class TaskInterrupted(Exception): + """Raised when a task is interrupted.""" class BaseAgent(BaseModel, ABC): @@ -113,59 +117,69 @@ def update_memory( kwargs = {"base64_image": base64_image, **(kwargs if role == "tool" else {})} self.memory.add_message(message_map[role](content, **kwargs)) - async def run(self, request: Optional[str] = None) -> str: - """Execute the agent's main loop asynchronously. - - Args: - request: Optional initial user request to process. - - Returns: - A string summarizing the execution results. + async def run(self, task: Task, input: Any) -> str: + """Execute the agent's main loop asynchronously.""" + if task.is_interrupted(): + raise TaskInterrupted() - Raises: - RuntimeError: If the agent is not in IDLE state at start. - """ if self.state != AgentState.IDLE: raise RuntimeError(f"Cannot run agent from state: {self.state}") - if request: - self.update_memory("user", request) + if input is not None: + self.update_memory("user", str(input)) results: List[str] = [] - async with self.state_context(AgentState.RUNNING): - while ( - self.current_step < self.max_steps and self.state != AgentState.FINISHED - ): - self.current_step += 1 - logger.info(f"Executing step {self.current_step}/{self.max_steps}") - step_result = await self.step() - - # Check for stuck state - if self.is_stuck(): - self.handle_stuck_state() - - results.append(f"Step {self.current_step}: {step_result}") - - if self.current_step >= self.max_steps: - self.current_step = 0 - self.state = AgentState.IDLE - results.append(f"Terminated: Reached max steps ({self.max_steps})") - await SANDBOX_CLIENT.cleanup() - return "\n".join(results) if results else "No steps executed" + try: + async with self.state_context(AgentState.RUNNING): + while ( + self.current_step < self.max_steps + and self.state != AgentState.FINISHED + ): + if task.is_interrupted(): + raise TaskInterrupted() + + self.current_step += 1 + task.emit( + "step_start", + {"step": self.current_step, "max_steps": self.max_steps}, + ) + step_result = await self.step(task) + + if self.is_stuck(): + self.handle_stuck_state(task) + + results.append(f"Step {self.current_step}: {step_result}") + task.emit( + "step_result", + {"step": self.current_step, "result": step_result}, + ) + + if self.current_step >= self.max_steps: + self.current_step = 0 + self.state = AgentState.IDLE + termination_msg = f"Terminated: Reached max steps ({self.max_steps})" + results.append(termination_msg) + task.emit("terminated", {"reason": termination_msg}) + return "\n".join(results) if results else "No steps executed" + finally: + await SANDBOX_CLIENT.cleanup() @abstractmethod - async def step(self) -> str: + async def step(self, task: Task) -> str: """Execute a single step in the agent's workflow. Must be implemented by subclasses to define specific behavior. """ - def handle_stuck_state(self): + def handle_stuck_state(self, task: Task): """Handle stuck state by adding a prompt to change strategy""" stuck_prompt = "\ Observed duplicate responses. Consider new strategies and avoid repeating ineffective paths already attempted." self.next_step_prompt = f"{stuck_prompt}\n{self.next_step_prompt}" - logger.warning(f"Agent detected stuck state. Added prompt: {stuck_prompt}") + task.emit( + "stuck_detected", + {"message": "Agent detected stuck state. Strategy prompt injected."}, + ) def is_stuck(self) -> bool: """Check if the agent is stuck in a loop by detecting duplicate content""" diff --git a/app/agent/browser.py b/app/agent/browser.py index 3f25c4539..acf1fd0ce 100644 --- a/app/agent/browser.py +++ b/app/agent/browser.py @@ -4,7 +4,7 @@ from pydantic import Field, model_validator from app.agent.toolcall import ToolCallAgent -from app.logger import logger +from app.agent.base import Task, TaskInterrupted from app.prompt.browser import NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.schema import Message, ToolChoice from app.tool import BrowserUseTool, Terminate, ToolCollection @@ -28,12 +28,10 @@ async def get_browser_state(self) -> Optional[dict]: SandboxBrowserTool().name ) if not browser_tool or not hasattr(browser_tool, "get_current_state"): - logger.warning("BrowserUseTool not found or doesn't have get_current_state") return None try: result = await browser_tool.get_current_state() if result.error: - logger.debug(f"Browser state error: {result.error}") return None if hasattr(result, "base64_image") and result.base64_image: self._current_base64_image = result.base64_image @@ -41,7 +39,6 @@ async def get_browser_state(self) -> Optional[dict]: self._current_base64_image = None return json.loads(result.output) except Exception as e: - logger.debug(f"Failed to get browser state: {str(e)}") return None async def format_next_step_prompt(self) -> str: @@ -117,12 +114,14 @@ def initialize_helper(self) -> "BrowserAgent": self.browser_context_helper = BrowserContextHelper(self) return self - async def think(self) -> bool: + async def think(self, task: Task) -> bool: """Process current state and decide next actions using tools, with browser state info added""" + if task.is_interrupted(): + raise TaskInterrupted() self.next_step_prompt = ( await self.browser_context_helper.format_next_step_prompt() ) - return await super().think() + return await super().think(task) async def cleanup(self): """Clean up browser agent resources by calling parent cleanup.""" diff --git a/app/agent/manus.py b/app/agent/manus.py index df40edbba..cb4bc0190 100644 --- a/app/agent/manus.py +++ b/app/agent/manus.py @@ -4,8 +4,8 @@ from app.agent.browser import BrowserContextHelper from app.agent.toolcall import ToolCallAgent +from app.agent.base import Task, TaskInterrupted from app.config import config -from app.logger import logger from app.prompt.manus import NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.tool import Terminate, ToolCollection from app.tool.ask_human import AskHuman @@ -71,9 +71,6 @@ async def initialize_mcp_servers(self) -> None: if server_config.type == "sse": if server_config.url: await self.connect_mcp_server(server_config.url, server_id) - logger.info( - f"Connected to MCP server {server_id} at {server_config.url}" - ) elif server_config.type == "stdio": if server_config.command: await self.connect_mcp_server( @@ -82,11 +79,8 @@ async def initialize_mcp_servers(self) -> None: use_stdio=True, stdio_args=server_config.args, ) - logger.info( - f"Connected to MCP server {server_id} using command {server_config.command}" - ) except Exception as e: - logger.error(f"Failed to connect to MCP server {server_id}: {e}") + _ = e async def connect_mcp_server( self, @@ -137,8 +131,10 @@ async def cleanup(self): await self.disconnect_mcp_server() self._initialized = False - async def think(self) -> bool: + async def think(self, task: Task) -> bool: """Process current state and decide next actions with appropriate context.""" + if task.is_interrupted(): + raise TaskInterrupted() if not self._initialized: await self.initialize_mcp_servers() self._initialized = True @@ -157,7 +153,7 @@ async def think(self) -> bool: await self.browser_context_helper.format_next_step_prompt() ) - result = await super().think() + result = await super().think(task) # Restore original prompt self.next_step_prompt = original_prompt diff --git a/app/agent/mcp.py b/app/agent/mcp.py index 9c6da6aaa..90f6d3772 100644 --- a/app/agent/mcp.py +++ b/app/agent/mcp.py @@ -3,7 +3,7 @@ from pydantic import Field from app.agent.toolcall import ToolCallAgent -from app.logger import logger +from app.agent.base import Task, TaskInterrupted from app.prompt.mcp import MULTIMEDIA_RESPONSE_PROMPT, NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.schema import AgentState, Message from app.tool.base import ToolResult @@ -84,7 +84,7 @@ async def initialize( ) ) - async def _refresh_tools(self) -> Tuple[List[str], List[str]]: + async def _refresh_tools(self, task: Task) -> Tuple[List[str], List[str]]: """Refresh the list of available tools from the MCP server. Returns: @@ -113,48 +113,56 @@ async def _refresh_tools(self) -> Tuple[List[str], List[str]]: # Update stored schemas self.tool_schemas = current_tools - # Log and notify about changes if added_tools: - logger.info(f"Added MCP tools: {added_tools}") + task.emit("tools_added", {"tools": added_tools}) self.memory.add_message( Message.system_message(f"New tools available: {', '.join(added_tools)}") ) if removed_tools: - logger.info(f"Removed MCP tools: {removed_tools}") + task.emit("tools_removed", {"tools": removed_tools}) self.memory.add_message( Message.system_message( f"Tools no longer available: {', '.join(removed_tools)}" ) ) if changed_tools: - logger.info(f"Changed MCP tools: {changed_tools}") + task.emit("tools_changed", {"tools": changed_tools}) return added_tools, removed_tools - async def think(self) -> bool: + async def think(self, task: Task) -> bool: """Process current state and decide next action.""" + if task.is_interrupted(): + raise TaskInterrupted() + # Check MCP session and tools availability if not self.mcp_clients.sessions or not self.mcp_clients.tool_map: - logger.info("MCP service is no longer available, ending interaction") + task.emit( + "info", {"message": "MCP service is no longer available, ending run."} + ) self.state = AgentState.FINISHED return False # Refresh tools periodically if self.current_step % self._refresh_tools_interval == 0: - await self._refresh_tools() + await self._refresh_tools(task) # All tools removed indicates shutdown if not self.mcp_clients.tool_map: - logger.info("MCP service has shut down, ending interaction") + task.emit( + "info", {"message": "MCP service has shut down, ending run."} + ) self.state = AgentState.FINISHED return False # Use the parent class's think method - return await super().think() + return await super().think(task) - async def _handle_special_tool(self, name: str, result: Any, **kwargs) -> None: + async def _handle_special_tool( + self, task: Task, name: str, result: Any, **kwargs + ) -> None: """Handle special tool execution and state changes""" # First process with parent handler - await super()._handle_special_tool(name, result, **kwargs) + await super()._handle_special_tool(task=task, name=name, result=result, **kwargs) # Handle multimedia responses if isinstance(result, ToolResult) and result.base64_image: @@ -173,13 +181,12 @@ async def cleanup(self) -> None: """Clean up MCP connection when done.""" if self.mcp_clients.sessions: await self.mcp_clients.disconnect() - logger.info("MCP connection closed") + # No external logging; silent cleanup - async def run(self, request: Optional[str] = None) -> str: + async def run(self, task: Task, input: Optional[str] = None) -> str: """Run the agent with cleanup when done.""" try: - result = await super().run(request) + result = await super().run(task, input) return result finally: - # Ensure cleanup happens even if there's an error await self.cleanup() diff --git a/app/agent/react.py b/app/agent/react.py index 7f9482082..58dd948ee 100644 --- a/app/agent/react.py +++ b/app/agent/react.py @@ -3,7 +3,7 @@ from pydantic import Field -from app.agent.base import BaseAgent +from app.agent.base import BaseAgent, Task, TaskInterrupted from app.llm import LLM from app.schema import AgentState, Memory @@ -23,16 +23,22 @@ class ReActAgent(BaseAgent, ABC): current_step: int = 0 @abstractmethod - async def think(self) -> bool: + async def think(self, task: Task) -> bool: """Process current state and decide next action""" @abstractmethod - async def act(self) -> str: + async def act(self, task: Task) -> str: """Execute decided actions""" - async def step(self) -> str: + async def step(self, task: Task) -> str: """Execute a single step: think and act.""" - should_act = await self.think() + if task.is_interrupted(): + raise TaskInterrupted() + + should_act = await self.think(task) + if task.is_interrupted(): + raise TaskInterrupted() + if not should_act: return "Thinking complete - no action needed" - return await self.act() + return await self.act(task) diff --git a/app/agent/sandbox_agent.py b/app/agent/sandbox_agent.py index 58612d20f..edde7199f 100644 --- a/app/agent/sandbox_agent.py +++ b/app/agent/sandbox_agent.py @@ -4,10 +4,10 @@ from app.agent.browser import BrowserContextHelper from app.agent.toolcall import ToolCallAgent +from app.agent.base import Task, TaskInterrupted from app.config import config from app.daytona.sandbox import create_sandbox, delete_sandbox from app.daytona.tool_base import SandboxToolsBase -from app.logger import logger from app.prompt.manus import NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.tool import Terminate, ToolCollection from app.tool.ask_human import AskHuman @@ -95,8 +95,6 @@ async def initialize_sandbox_tools( "vnc": vnc_url, "website": website_url, } - logger.info(f"VNC URL: {vnc_url}") - logger.info(f"Website URL: {website_url}") SandboxToolsBase._urls_printed = True sb_tools = [ SandboxBrowserTool(sandbox), @@ -107,7 +105,6 @@ async def initialize_sandbox_tools( self.available_tools.add_tools(*sb_tools) except Exception as e: - logger.error(f"Error initializing sandbox tools: {e}") raise async def initialize_mcp_servers(self) -> None: @@ -117,9 +114,6 @@ async def initialize_mcp_servers(self) -> None: if server_config.type == "sse": if server_config.url: await self.connect_mcp_server(server_config.url, server_id) - logger.info( - f"Connected to MCP server {server_id} at {server_config.url}" - ) elif server_config.type == "stdio": if server_config.command: await self.connect_mcp_server( @@ -128,11 +122,8 @@ async def initialize_mcp_servers(self) -> None: use_stdio=True, stdio_args=server_config.args, ) - logger.info( - f"Connected to MCP server {server_id} using command {server_config.command}" - ) except Exception as e: - logger.error(f"Failed to connect to MCP server {server_id}: {e}") + _ = e async def connect_mcp_server( self, @@ -178,11 +169,9 @@ async def delete_sandbox(self, sandbox_id: str) -> None: """Delete a sandbox by ID.""" try: await delete_sandbox(sandbox_id) - logger.info(f"Sandbox {sandbox_id} deleted successfully") if sandbox_id in self.sandbox_link: del self.sandbox_link[sandbox_id] except Exception as e: - logger.error(f"Error deleting sandbox {sandbox_id}: {e}") raise e async def cleanup(self): @@ -195,8 +184,10 @@ async def cleanup(self): await self.delete_sandbox(self.sandbox.id if self.sandbox else "unknown") self._initialized = False - async def think(self) -> bool: + async def think(self, task: Task) -> bool: """Process current state and decide next actions with appropriate context.""" + if task.is_interrupted(): + raise TaskInterrupted() if not self._initialized: await self.initialize_mcp_servers() self._initialized = True @@ -215,7 +206,7 @@ async def think(self) -> bool: await self.browser_context_helper.format_next_step_prompt() ) - result = await super().think() + result = await super().think(task) # Restore original prompt self.next_step_prompt = original_prompt diff --git a/app/agent/toolcall.py b/app/agent/toolcall.py index 65f31d988..04dac8beb 100644 --- a/app/agent/toolcall.py +++ b/app/agent/toolcall.py @@ -5,8 +5,8 @@ from pydantic import Field from app.agent.react import ReActAgent +from app.agent.base import Task, TaskInterrupted from app.exceptions import TokenLimitExceeded -from app.logger import logger from app.prompt.toolcall import NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.schema import TOOL_CHOICE_TYPE, AgentState, Message, ToolCall, ToolChoice from app.tool import CreateChatCompletion, Terminate, ToolCollection @@ -16,7 +16,7 @@ class ToolCallAgent(ReActAgent): - """Base agent class for handling tool/function calls with enhanced abstraction""" + """Base agent class for handling tool/function calls with enhanced abstraction.""" name: str = "toolcall" description: str = "an agent that can execute tool calls." @@ -36,14 +36,19 @@ class ToolCallAgent(ReActAgent): max_steps: int = 30 max_observe: Optional[Union[int, bool]] = None - async def think(self) -> bool: - """Process current state and decide next actions using tools""" + async def think(self, task: Task) -> bool: + """Process current state and decide next actions using tools.""" + if task.is_interrupted(): + raise TaskInterrupted() + if self.next_step_prompt: user_msg = Message.user_message(self.next_step_prompt) self.messages += [user_msg] try: - # Get response with tool options + if task.is_interrupted(): + raise TaskInterrupted() + response = await self.llm.ask_tool( messages=self.messages, system_msgs=( @@ -57,11 +62,14 @@ async def think(self) -> bool: except ValueError: raise except Exception as e: - # Check if this is a RetryError containing TokenLimitExceeded if hasattr(e, "__cause__") and isinstance(e.__cause__, TokenLimitExceeded): token_limit_error = e.__cause__ - logger.error( - f"🚨 Token limit error (from RetryError): {token_limit_error}" + task.emit( + "error", + { + "message": "Token limit reached during tool thinking", + "detail": str(token_limit_error), + }, ) self.memory.add_message( Message.assistant_message( @@ -77,33 +85,34 @@ async def think(self) -> bool: ) content = response.content if response and response.content else "" - # Log response info - logger.info(f"✨ {self.name}'s thoughts: {content}") - logger.info( - f"🛠️ {self.name} selected {len(tool_calls) if tool_calls else 0} tools to use" + task.emit( + "thought", + { + "agent": self.name, + "content": content, + "tool_count": len(tool_calls) if tool_calls else 0, + "tools": [call.function.name for call in tool_calls] if tool_calls else [], + "arguments": tool_calls[0].function.arguments if tool_calls else None, + }, ) - if tool_calls: - logger.info( - f"🧰 Tools being prepared: {[call.function.name for call in tool_calls]}" - ) - logger.info(f"🔧 Tool arguments: {tool_calls[0].function.arguments}") try: if response is None: raise RuntimeError("No response received from the LLM") - # Handle different tool_choices modes if self.tool_choices == ToolChoice.NONE: if tool_calls: - logger.warning( - f"🤔 Hmm, {self.name} tried to use tools when they weren't available!" + task.emit( + "warning", + { + "message": f"{self.name} tried to use tools when none were available" + }, ) if content: self.memory.add_message(Message.assistant_message(content)) return True return False - # Create and add assistant message assistant_msg = ( Message.from_tool_calls(content=content, tool_calls=self.tool_calls) if self.tool_calls @@ -114,13 +123,18 @@ async def think(self) -> bool: if self.tool_choices == ToolChoice.REQUIRED and not self.tool_calls: return True # Will be handled in act() - # For 'auto' mode, continue with content if no commands but content exists if self.tool_choices == ToolChoice.AUTO and not self.tool_calls: return bool(content) return bool(self.tool_calls) except Exception as e: - logger.error(f"🚨 Oops! The {self.name}'s thinking process hit a snag: {e}") + task.emit( + "error", + { + "message": f"The {self.name}'s thinking process hit a snag", + "detail": str(e), + }, + ) self.memory.add_message( Message.assistant_message( f"Error encountered while processing: {str(e)}" @@ -128,30 +142,38 @@ async def think(self) -> bool: ) return False - async def act(self) -> str: - """Execute tool calls and handle their results""" + async def act(self, task: Task) -> str: + """Execute tool calls and handle their results.""" + if task.is_interrupted(): + raise TaskInterrupted() + if not self.tool_calls: if self.tool_choices == ToolChoice.REQUIRED: raise ValueError(TOOL_CALL_REQUIRED) - # Return last message content if no tool calls return self.messages[-1].content or "No content or commands to execute" results = [] for command in self.tool_calls: - # Reset base64_image for each tool call + if task.is_interrupted(): + raise TaskInterrupted() + self._current_base64_image = None - result = await self.execute_tool(command) + result = await self.execute_tool(command, task) if self.max_observe: result = result[: self.max_observe] - logger.info( - f"🎯 Tool '{command.function.name}' completed its mission! Result: {result}" + task.emit( + "tool_result", + { + "tool": command.function.name, + "result": result, + "tool_call_id": command.id, + }, ) - # Add tool response to memory tool_msg = Message.tool_message( content=result, tool_call_id=command.id, @@ -163,8 +185,11 @@ async def act(self) -> str: return "\n\n".join(results) - async def execute_tool(self, command: ToolCall) -> str: - """Execute a single tool call with robust error handling""" + async def execute_tool(self, command: ToolCall, task: Task) -> str: + """Execute a single tool call with robust error handling.""" + if task.is_interrupted(): + raise TaskInterrupted() + if not command or not command.function or not command.function.name: return "Error: Invalid command format" @@ -173,22 +198,15 @@ async def execute_tool(self, command: ToolCall) -> str: return f"Error: Unknown tool '{name}'" try: - # Parse arguments args = json.loads(command.function.arguments or "{}") - # Execute the tool - logger.info(f"🔧 Activating tool: '{name}'...") result = await self.available_tools.execute(name=name, tool_input=args) - # Handle special tools - await self._handle_special_tool(name=name, result=result) + await self._handle_special_tool(task=task, name=name, result=result) - # Check if result is a ToolResult with base64_image if hasattr(result, "base64_image") and result.base64_image: - # Store the base64_image for later use in tool_message self._current_base64_image = result.base64_image - # Format result for display (standard case) observation = ( f"Observed output of cmd `{name}` executed:\n{str(result)}" if result @@ -198,53 +216,60 @@ async def execute_tool(self, command: ToolCall) -> str: return observation except json.JSONDecodeError: error_msg = f"Error parsing arguments for {name}: Invalid JSON format" - logger.error( - f"📝 Oops! The arguments for '{name}' don't make sense - invalid JSON, arguments:{command.function.arguments}" + task.emit( + "error", + { + "message": f"Invalid JSON arguments for tool '{name}'", + "detail": command.function.arguments, + }, ) return f"Error: {error_msg}" except Exception as e: - error_msg = f"⚠️ Tool '{name}' encountered a problem: {str(e)}" - logger.exception(error_msg) + error_msg = f"Tool '{name}' encountered a problem: {str(e)}" + task.emit( + "error", + {"message": "Tool execution failed", "tool": name, "detail": str(e)}, + ) return f"Error: {error_msg}" - async def _handle_special_tool(self, name: str, result: Any, **kwargs): - """Handle special tool execution and state changes""" + async def _handle_special_tool( + self, task: Task, name: str, result: Any, **kwargs + ): + """Handle special tool execution and state changes.""" if not self._is_special_tool(name): return if self._should_finish_execution(name=name, result=result, **kwargs): - # Set agent state to finished - logger.info(f"🏁 Special tool '{name}' has completed the task!") + task.emit( + "finish_signal", + {"tool": name, "message": "Special tool signaled completion."}, + ) self.state = AgentState.FINISHED @staticmethod def _should_finish_execution(**kwargs) -> bool: - """Determine if tool execution should finish the agent""" + """Determine if tool execution should finish the agent.""" return True def _is_special_tool(self, name: str) -> bool: - """Check if tool name is in special tools list""" + """Check if tool name is in special tools list.""" return name.lower() in [n.lower() for n in self.special_tool_names] async def cleanup(self): """Clean up resources used by the agent's tools.""" - logger.info(f"🧹 Cleaning up resources for agent '{self.name}'...") - for tool_name, tool_instance in self.available_tools.tool_map.items(): + for tool_instance in self.available_tools.tool_map.values(): if hasattr(tool_instance, "cleanup") and asyncio.iscoroutinefunction( tool_instance.cleanup ): try: - logger.debug(f"🧼 Cleaning up tool: {tool_name}") await tool_instance.cleanup() - except Exception as e: - logger.error( - f"🚨 Error cleaning up tool '{tool_name}': {e}", exc_info=True - ) - logger.info(f"✨ Cleanup complete for agent '{self.name}'.") + except Exception: + # Ignore cleanup errors to avoid masking main flow + pass - async def run(self, request: Optional[str] = None) -> str: + async def run(self, task: Task, input: Optional[str] = None) -> str: """Run the agent with cleanup when done.""" try: - return await super().run(request) + return await super().run(task, input) finally: await self.cleanup() From b1562fbb1af3539590ddb84a7959429b1218caeb Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Sun, 11 Jan 2026 23:21:13 +0800 Subject: [PATCH 06/69] =?UTF-8?q?=E8=AF=B7=E4=BF=AE=E6=94=B9=20Planner=20A?= =?UTF-8?q?gent=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Planner 的输出必须是结构化 plan(如 list[dict] 或 dataclass) 2. 生成 plan 的过程中,通过 task.emit(plan.step, step) 3. Planner 不执行任何 tool 4. Planner 完成时 emit(plan.done) 不要修改 Executor,不引入新模型调用。 --- app/agent/__init__.py | 2 + app/agent/planner.py | 123 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 app/agent/planner.py diff --git a/app/agent/__init__.py b/app/agent/__init__.py index f7df2b9ba..89d8a3f58 100644 --- a/app/agent/__init__.py +++ b/app/agent/__init__.py @@ -2,6 +2,7 @@ from app.agent.browser import BrowserAgent from app.agent.mcp import MCPAgent from app.agent.react import ReActAgent +from app.agent.planner import PlannerAgent from app.agent.swe import SWEAgent from app.agent.toolcall import ToolCallAgent @@ -13,4 +14,5 @@ "SWEAgent", "ToolCallAgent", "MCPAgent", + "PlannerAgent", ] diff --git a/app/agent/planner.py b/app/agent/planner.py new file mode 100644 index 000000000..9014e7ed2 --- /dev/null +++ b/app/agent/planner.py @@ -0,0 +1,123 @@ +import json +from typing import Any, Dict, List, Optional + +from pydantic import Field + +from app.agent.base import BaseAgent, Task, TaskInterrupted +from app.schema import Message +from app.prompt.planning import PLANNING_SYSTEM_PROMPT + + +class PlannerAgent(BaseAgent): + """Lightweight planner that produces a structured plan without executing tools.""" + + name: str = "planner" + description: str = ( + "Generates structured plans (list[dict]) and emits plan events via task." + ) + + system_prompt: str = PLANNING_SYSTEM_PROMPT + next_step_prompt: Optional[str] = None + + max_steps: int = 1 + current_step: int = 0 + + plan_fields: List[str] = Field( + default_factory=lambda: ["id", "title", "action", "expected_result"] + ) + + async def run(self, task: Task, input: Any) -> List[Dict[str, Any]]: + if task.is_interrupted(): + raise TaskInterrupted() + + request = "" if input is None else str(input).strip() + plan = await self._generate_plan(task, request) + + for idx, step in enumerate(plan): + task.emit("plan.step", {"index": idx, "step": step}) + + task.emit("plan.done", {"steps": len(plan), "plan": plan}) + return plan + + async def _generate_plan( + self, task: Task, request: str + ) -> List[Dict[str, Any]]: + """Use the existing LLM to create a structured plan without calling tools.""" + if task.is_interrupted(): + raise TaskInterrupted() + + if not request: + default_plan = [ + { + "id": "step-1", + "title": "No request provided", + "action": "Await valid task input", + "expected_result": "Receive task details to plan", + } + ] + return default_plan + + user_prompt = ( + "Create a concise, actionable plan as a JSON array. " + "Each item must be an object with keys: " + f"{', '.join(self.plan_fields)}. " + "Keep 3-7 steps, ordered, no prose outside JSON." + f"\n\nTask: {request}" + ) + + response = await self.llm.ask( + messages=[Message.user_message(user_prompt)], + system_msgs=[Message.system_message(self.system_prompt)], + ) + + plan = self._parse_plan(response) + if not plan: + plan = [ + { + "id": "step-1", + "title": "Analyze task", + "action": f"Understand requirements: {request}", + "expected_result": "Clear scope and constraints", + }, + { + "id": "step-2", + "title": "Execute task", + "action": "Perform required actions to complete the task", + "expected_result": "Task objectives met", + }, + { + "id": "step-3", + "title": "Verify results", + "action": "Validate outputs and summarize findings", + "expected_result": "Confirmed completion with summary", + }, + ] + return plan + + def _parse_plan(self, text: str) -> List[Dict[str, Any]]: + """Parse JSON plan and normalize fields.""" + if not text: + return [] + try: + data = json.loads(text) + except json.JSONDecodeError: + return [] + + if not isinstance(data, list): + return [] + + normalized: List[Dict[str, Any]] = [] + for i, item in enumerate(data): + if not isinstance(item, dict): + continue + step = {field: item.get(field) for field in self.plan_fields} + # Fallback IDs if missing + if not step.get("id"): + step["id"] = f"step-{i+1}" + if not step.get("title") and step.get("action"): + step["title"] = step["action"] + normalized.append(step) + return normalized + + async def step(self, task: Task) -> str: # pragma: no cover - run overrides loop + raise NotImplementedError("PlannerAgent does not use step-based execution") From ce72a4e8f2b0c8d701cfdb9b788f9856376d4797 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Sun, 11 Jan 2026 23:25:10 +0800 Subject: [PATCH 07/69] =?UTF-8?q?=E8=AF=B7=E4=BF=AE=E6=94=B9=20Executor=20?= =?UTF-8?q?Agent=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Executor 只消费 Planner 生成的 plan 2. 每次执行 step 前: task.emit(execute.step.start, step) 3. 调用 tool 前: task.emit(tool.call, tool_name, args) 4. tool 执行完成后: task.emit(tool.result, result) 5. 支持 interrupt(中断后立刻停止) 不要修改 Planner 和 Tool 实现。 --- app/agent/__init__.py | 2 + app/agent/executor.py | 101 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 app/agent/executor.py diff --git a/app/agent/__init__.py b/app/agent/__init__.py index 89d8a3f58..4ce029051 100644 --- a/app/agent/__init__.py +++ b/app/agent/__init__.py @@ -1,6 +1,7 @@ from app.agent.base import BaseAgent from app.agent.browser import BrowserAgent from app.agent.mcp import MCPAgent +from app.agent.executor import ExecutorAgent from app.agent.react import ReActAgent from app.agent.planner import PlannerAgent from app.agent.swe import SWEAgent @@ -15,4 +16,5 @@ "ToolCallAgent", "MCPAgent", "PlannerAgent", + "ExecutorAgent", ] diff --git a/app/agent/executor.py b/app/agent/executor.py new file mode 100644 index 000000000..4b0a7d259 --- /dev/null +++ b/app/agent/executor.py @@ -0,0 +1,101 @@ +import json +from typing import Any, Dict, List, Optional, Union + +from app.agent.toolcall import ToolCallAgent +from app.agent.base import Task, TaskInterrupted + + +class ExecutorAgent(ToolCallAgent): + """Executor that consumes a planner-produced plan and runs its steps with tools.""" + + name: str = "executor" + description: str = "Executes structured plan steps and emits execution events." + + async def run(self, task: Task, plan: Any) -> str: + if task.is_interrupted(): + raise TaskInterrupted() + + steps = self._normalize_plan(plan) + results: List[str] = [] + + for idx, step in enumerate(steps): + if task.is_interrupted(): + raise TaskInterrupted() + + task.emit("execute.step.start", {"index": idx, "step": step}) + step_prompt = self._format_step_prompt(step, idx) + result = await super().run(task, step_prompt) + results.append(result) + + return "\n".join(results) + + def _normalize_plan(self, plan: Any) -> List[Dict[str, Any]]: + """Accept list/dict/str plan and normalize to list of dict steps.""" + if isinstance(plan, list): + return [self._ensure_dict(step, i) for i, step in enumerate(plan)] + if isinstance(plan, dict): + return [self._ensure_dict(plan, 0)] + if isinstance(plan, str): + try: + data = json.loads(plan) + if isinstance(data, list): + return [self._ensure_dict(s, i) for i, s in enumerate(data)] + if isinstance(data, dict): + return [self._ensure_dict(data, 0)] + except json.JSONDecodeError: + pass + # fallback single step + return [ + { + "id": "step-1", + "title": "Execute task", + "action": str(plan), + "expected_result": "Task completed", + } + ] + + def _ensure_dict(self, step: Any, idx: int) -> Dict[str, Any]: + if isinstance(step, dict): + if "id" not in step: + step = {**step, "id": step.get("title") or f"step-{idx+1}"} + return step + return { + "id": f"step-{idx+1}", + "title": "Execute step", + "action": str(step), + "expected_result": "", + } + + def _format_step_prompt(self, step: Dict[str, Any], idx: int) -> str: + title = step.get("title") or f"Step {idx+1}" + action = step.get("action") or "" + expected = step.get("expected_result") or "" + return ( + f"Step {idx+1}: {title}\n" + f"Action: {action}\n" + f"Expected Result: {expected}\n" + "Execute this step using available tools. Return a concise result." + ) + + async def execute_tool(self, command, task: Task) -> str: # type: ignore[override] + if task.is_interrupted(): + raise TaskInterrupted() + + name = getattr(getattr(command, "function", None), "name", None) + raw_args = getattr(getattr(command, "function", None), "arguments", None) + parsed_args: Union[dict, str, None] + try: + parsed_args = json.loads(raw_args or "{}") + except Exception: + parsed_args = raw_args + + if name: + task.emit("tool.call", {"tool": name, "args": parsed_args}) + + result = await super().execute_tool(command, task) + + task.emit("tool.result", {"tool": name, "result": result}) + return result + + +__all__ = ["ExecutorAgent"] From b74013555f3bbd04a4abefc060f6b4eb1ed8d91d Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 11:25:44 +0800 Subject: [PATCH 08/69] =?UTF-8?q?=E8=AF=B7=E6=96=B0=E5=A2=9E=20tools/runne?= =?UTF-8?q?r.py=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现 ToolRunner 类,统一所有 tool 执行入口 提供 run(task, tool_name, args) -> ToolResult 支持: timeout 捕获 stdout / stderr 在执行期间检查 task.is_interrupted() 不直接调用 os.system 不修改具体 tool 的业务逻辑 只新增 runner,不重构 tool。 --- tools/runner.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tools/runner.py diff --git a/tools/runner.py b/tools/runner.py new file mode 100644 index 000000000..103b01f1b --- /dev/null +++ b/tools/runner.py @@ -0,0 +1,84 @@ +import asyncio +import io +from contextlib import redirect_stdout, redirect_stderr +from typing import Any, Mapping, Optional + +from app.agent.base import TaskInterrupted +from core.task import Task +from app.tool.base import BaseTool, ToolResult + + +class ToolRunner: + """Unified tool execution entry with timeout, output capture, and interruption checks.""" + + def __init__( + self, + tools: Mapping[str, Any], + default_timeout: Optional[float] = None, + check_interval: float = 0.1, + ) -> None: + self.default_timeout = default_timeout + self.check_interval = check_interval + # Support ToolCollection or plain dict mapping + if hasattr(tools, "tool_map"): + self.tools = getattr(tools, "tool_map") + else: + self.tools = tools + + async def run( + self, task: Task, tool_name: str, args: Optional[dict] = None + ) -> ToolResult: + if task.is_interrupted(): + raise TaskInterrupted() + + args = args or {} + tool = self.tools.get(tool_name) if hasattr(self.tools, "get") else None + if tool is None or not isinstance(tool, BaseTool): + return ToolResult(error=f"Tool '{tool_name}' not found") + + async def _invoke(): + buf_out, buf_err = io.StringIO(), io.StringIO() + with redirect_stdout(buf_out), redirect_stderr(buf_err): + result = await tool.execute(**args) + return result, buf_out.getvalue(), buf_err.getvalue() + + tool_task = asyncio.create_task(_invoke()) + start = asyncio.get_event_loop().time() + timeout = self.default_timeout + + while True: + done, _ = await asyncio.wait( + {tool_task}, timeout=self.check_interval, return_when=asyncio.FIRST_COMPLETED + ) + if task.is_interrupted(): + tool_task.cancel() + raise TaskInterrupted() + if done: + break + if timeout is not None and (asyncio.get_event_loop().time() - start) > timeout: + tool_task.cancel() + return ToolResult(error=f"Tool '{tool_name}' execution timed out after {timeout} seconds") + + try: + result, stdout_text, stderr_text = await tool_task + except asyncio.CancelledError: + return ToolResult(error=f"Tool '{tool_name}' execution cancelled") + except Exception as exc: # pragma: no cover - safety net + return ToolResult(error=f"Tool '{tool_name}' failed: {exc}") + + system_info_parts = [] + if stdout_text: + system_info_parts.append(f"stdout:\n{stdout_text}") + if stderr_text: + system_info_parts.append(f"stderr:\n{stderr_text}") + system_info = "\n".join(system_info_parts) if system_info_parts else None + + if isinstance(result, ToolResult): + if system_info: + return result.replace(system=system_info if not result.system else f"{result.system}\n{system_info}") + return result + + return ToolResult(output=result, system=system_info) + + +__all__ = ["ToolRunner"] From e08b1229565772948de9afecdbd3f1e5ae36eaec Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 11:30:38 +0800 Subject: [PATCH 09/69] =?UTF-8?q?=E8=AF=B7=E4=BF=AE=E6=94=B9=20tools/shell?= =?UTF-8?q?.py=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 禁止直接 subprocess.run / os.system 2. 统一通过 ToolRunner 调用 3. 返回结构化 ToolResult(stdout / stderr / exit_code) 4. 支持 interrupt 不修改 shell 的功能行为。 --- tools/shell.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tools/shell.py diff --git a/tools/shell.py b/tools/shell.py new file mode 100644 index 000000000..999e0ff5f --- /dev/null +++ b/tools/shell.py @@ -0,0 +1,45 @@ +from typing import Any, Dict, Optional + +from app.tool.base import ToolResult +from app.tool.bash import Bash +from core.task import Task +from tools.runner import ToolRunner + + +class ShellResult(ToolResult): + stdout: Optional[str] = None + stderr: Optional[str] = None + exit_code: Optional[int] = None + + class Config: + arbitrary_types_allowed = True + + +class Shell: + """Shell command runner that delegates to ToolRunner and Bash tool.""" + + def __init__(self, default_timeout: Optional[float] = None): + self.runner = ToolRunner({"bash": Bash()}, default_timeout=default_timeout) + + async def run( + self, task: Task, command: str, timeout: Optional[float] = None + ) -> ShellResult: + args: Dict[str, Any] = {"command": command} + runner = self.runner + if timeout is not None: + runner = ToolRunner({"bash": runner.tools["bash"]}, default_timeout=timeout) + + result = await runner.run(task, "bash", args) + + return ShellResult( + output=result.output, + error=result.error, + system=result.system, + base64_image=result.base64_image, + stdout=result.output, + stderr=result.error, + exit_code=None, + ) + + +__all__ = ["Shell", "ShellResult"] From b6f0d26a315adf11dd27ab15104808334edfa094 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 11:40:18 +0800 Subject: [PATCH 10/69] =?UTF-8?q?=E8=AF=B7=E6=96=B0=E5=A2=9E=20context/eng?= =?UTF-8?q?ine.py=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实现 ContextEngine.build(task, agent_role, step_type) Context 分为: Hard facts(用户目标、当前 plan) Recent events(最近 tool 输出) Process summary(字符串) 支持 context token budget(简单字符裁剪即可) 不调用向量数据 --- context/engine.py | 126 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 context/engine.py diff --git a/context/engine.py b/context/engine.py new file mode 100644 index 000000000..622525800 --- /dev/null +++ b/context/engine.py @@ -0,0 +1,126 @@ +from __future__ import annotations + +import json +from typing import Any, Dict, List, Optional +import queue +import asyncio + +from core.task import Task + + +class ContextEngine: + """Builds prompt context from task state and recent events (no vector store).""" + + @classmethod + def build( + cls, + task: Task, + agent_role: Optional[str] = None, + step_type: Optional[str] = None, + budget: int = 4000, + ) -> Dict[str, Any]: + """Assemble context sections and enforce a simple character budget.""" + events = cls._snapshot_events(task) + + hard_facts = cls._collect_hard_facts(events) + recent_events = cls._collect_recent(events) + process_summary = cls._summarize(events, hard_facts) + + context = { + "agent_role": agent_role, + "step_type": step_type, + "hard_facts": hard_facts, + "recent_events": recent_events, + "process_summary": process_summary, + } + + return cls._enforce_budget(context, budget) + + @staticmethod + def _snapshot_events(task: Task) -> List[Dict[str, Any]]: + """Copy events without mutating the queue (supports asyncio.Queue and queue.Queue).""" + q = task.event_queue + items: List[Any] = [] + if isinstance(q, queue.Queue): + try: + items = list(q.queue) # type: ignore[attr-defined] + except Exception: + items = [] + elif isinstance(q, asyncio.Queue): + try: + items = list(q._queue) # type: ignore[attr-defined] + except Exception: + items = [] + return [e for e in items if isinstance(e, dict) and "type" in e] + + @staticmethod + def _collect_hard_facts(events: List[Dict[str, Any]]) -> Dict[str, Any]: + """Extract stable context: user goal and plan.""" + plan = None + plan_steps: List[Any] = [] + user_goal = None + + for ev in events: + etype = ev.get("type") + data = ev.get("data", {}) + if etype == "plan.done": + plan = data.get("plan") or plan + elif etype == "plan.step": + plan_steps.append(data.get("step")) + elif etype == "thought" and not user_goal: + # Heuristic: first thought often echoes the goal + user_goal = data.get("content") or data + + if plan is None and plan_steps: + plan = plan_steps + + return {"user_goal": user_goal, "plan": plan} + + @staticmethod + def _collect_recent(events: List[Dict[str, Any]], limit: int = 5) -> List[Any]: + """Collect recent tool-related events.""" + tool_events = [ + ev + for ev in events + if ev.get("type") in {"tool.call", "tool.result", "step_result", "execute.step.start"} + ] + return tool_events[-limit:] + + @staticmethod + def _summarize(events: List[Dict[str, Any]], hard_facts: Dict[str, Any]) -> str: + tool_calls = sum(1 for e in events if e.get("type") == "tool.call") + tool_results = sum(1 for e in events if e.get("type") == "tool.result") + steps = sum(1 for e in events if e.get("type") in {"plan.step", "execute.step.start"}) + plan_known = bool(hard_facts.get("plan")) + return ( + f"Steps seen: {steps}; tool calls: {tool_calls}; tool results: {tool_results}; " + f"plan_available: {plan_known}" + ) + + @staticmethod + def _enforce_budget(context: Dict[str, Any], budget: int) -> Dict[str, Any]: + """Trim context to fit a simple character budget.""" + text = json.dumps(context, ensure_ascii=False) + if len(text) <= budget: + return context + + # Trim recent events first, then hard facts strings + recent = context.get("recent_events") or [] + while recent and len(json.dumps(context, ensure_ascii=False)) > budget: + recent.pop(0) + context["recent_events"] = recent + + def _truncate_str(value: Any, max_len: int) -> Any: + if isinstance(value, str) and len(value) > max_len: + return value[-max_len:] + return value + + context["process_summary"] = _truncate_str(context.get("process_summary"), 300) + hard = context.get("hard_facts") or {} + if isinstance(hard, dict): + hard["user_goal"] = _truncate_str(hard.get("user_goal"), 500) + context["hard_facts"] = hard + return context + + +__all__ = ["ContextEngine"] From d52acd27e898f1f104877ce7742924b8e77c734c Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 11:56:22 +0800 Subject: [PATCH 11/69] =?UTF-8?q?=E8=AF=B7=E4=BF=AE=E6=94=B9=20Agent=20pro?= =?UTF-8?q?mpt=20=E6=9E=84=E5=BB=BA=E9=80=BB=E8=BE=91=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 所有 Agent 在调用 LLM 前,必须通过 ContextEngine.build 获取上下文 2. Agent 不得自行拼接历史记录 3. 不修改 prompt 内容本身,只替换 context 来源 只改 prompt 构建相关代码。 --- app/agent/planner.py | 6 +++++- app/agent/toolcall.py | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/agent/planner.py b/app/agent/planner.py index 9014e7ed2..cc2cdb068 100644 --- a/app/agent/planner.py +++ b/app/agent/planner.py @@ -4,6 +4,7 @@ from pydantic import Field from app.agent.base import BaseAgent, Task, TaskInterrupted +from context.engine import ContextEngine from app.schema import Message from app.prompt.planning import PLANNING_SYSTEM_PROMPT @@ -65,9 +66,12 @@ async def _generate_plan( f"\n\nTask: {request}" ) + context = ContextEngine.build(task, agent_role=self.name, step_type="plan") + ctx_msg = Message.system_message(json.dumps(context, ensure_ascii=False)) + response = await self.llm.ask( messages=[Message.user_message(user_prompt)], - system_msgs=[Message.system_message(self.system_prompt)], + system_msgs=[Message.system_message(self.system_prompt), ctx_msg], ) plan = self._parse_plan(response) diff --git a/app/agent/toolcall.py b/app/agent/toolcall.py index 04dac8beb..4ab5e4ec7 100644 --- a/app/agent/toolcall.py +++ b/app/agent/toolcall.py @@ -6,6 +6,7 @@ from app.agent.react import ReActAgent from app.agent.base import Task, TaskInterrupted +from context.engine import ContextEngine from app.exceptions import TokenLimitExceeded from app.prompt.toolcall import NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.schema import TOOL_CHOICE_TYPE, AgentState, Message, ToolCall, ToolChoice @@ -46,16 +47,22 @@ async def think(self, task: Task) -> bool: self.messages += [user_msg] try: + context = ContextEngine.build(task, agent_role=self.name) + context_msg = Message.system_message( + json.dumps(context, ensure_ascii=False) + ) if task.is_interrupted(): raise TaskInterrupted() + system_msgs = ( + [Message.system_message(self.system_prompt), context_msg] + if self.system_prompt + else [context_msg] + ) + response = await self.llm.ask_tool( messages=self.messages, - system_msgs=( - [Message.system_message(self.system_prompt)] - if self.system_prompt - else None - ), + system_msgs=system_msgs, tools=self.available_tools.to_params(), tool_choice=self.tool_choices, ) From 6445f43fbad5041cff3095a1ab1d36a92c257ca9 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 11:58:37 +0800 Subject: [PATCH 12/69] =?UTF-8?q?=E8=AF=B7=E6=96=B0=E5=A2=9E=20server/api.?= =?UTF-8?q?py=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 使用 FastAPI 2. 提供: - POST /tasks(创建任务) - GET /tasks/{id}(查询状态) - POST /tasks/{id}/interrupt 3. API 调用 TaskRegistry 4. Agent 在 background task 中运行 5. 不引入 WebSocket 只新增 server/api.py。 --- server/api.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 server/api.py diff --git a/server/api.py b/server/api.py new file mode 100644 index 000000000..914368a99 --- /dev/null +++ b/server/api.py @@ -0,0 +1,65 @@ +from typing import Optional + +import uvicorn +from fastapi import BackgroundTasks, FastAPI, HTTPException + +from app.agent.manus import Manus +from app.agent.base import TaskInterrupted +from core.task import TaskStatus +from core.task_registry import TaskRegistry + + +app = FastAPI(title="OpenManus Task API", version="0.1.0") +registry = TaskRegistry() + + +async def _run_agent(task_id: str, prompt: Optional[str]) -> None: + task = registry.get_task(task_id) + if not task: + return + + task.status = TaskStatus.RUNNING + try: + agent = await Manus.create() + await agent.run(task, prompt) + if task.status == TaskStatus.RUNNING: + task.status = TaskStatus.DONE + except TaskInterrupted: + task.status = TaskStatus.INTERRUPTED + except Exception as exc: # pragma: no cover - background safety + task.status = TaskStatus.FAILED + task.emit("error", {"message": str(exc)}) + + +@app.post("/tasks") +async def create_task(prompt: Optional[str] = None, background: BackgroundTasks = None): + task = registry.create_task() + task.status = TaskStatus.CREATED + if background is not None: + background.add_task(_run_agent, task.id, prompt) + return {"id": task.id, "status": task.status} + + +@app.get("/tasks/{task_id}") +async def get_task(task_id: str): + task = registry.get_task(task_id) + if not task: + raise HTTPException(status_code=404, detail="Task not found") + + return { + "id": task.id, + "status": task.status, + "interrupt_flag": task.interrupt_flag, + } + + +@app.post("/tasks/{task_id}/interrupt") +async def interrupt_task(task_id: str): + task = registry.interrupt_task(task_id) + if not task: + raise HTTPException(status_code=404, detail="Task not found") + return {"id": task.id, "status": task.status, "interrupt_flag": task.interrupt_flag} + + +if __name__ == "__main__": # pragma: no cover + uvicorn.run(app, host="0.0.0.0", port=8000) From 7e9f56ee2d13977646c495b217dcd146d33dde10 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 12:04:16 +0800 Subject: [PATCH 13/69] =?UTF-8?q?=E8=AF=B7=E6=96=B0=E5=A2=9E=20server/ws.p?= =?UTF-8?q?y=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. WebSocket endpoint: /tasks/{id}/stream 2. 从 task.event_queue 读取事件 3. 将事件以 JSON 形式推送给客户端 4. 支持客户端发送 interrupt 指令 5. 不包含业务逻辑,只做事件转发 不要修改 API 层。 --- server/ws.py | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 server/ws.py diff --git a/server/ws.py b/server/ws.py new file mode 100644 index 000000000..7ded2b975 --- /dev/null +++ b/server/ws.py @@ -0,0 +1,92 @@ +import asyncio +import json +import queue +from typing import Any + +from fastapi import FastAPI, WebSocket, WebSocketDisconnect + +from core.task_registry import TaskRegistry + +# Reuse registry from REST API if available; fallback to a local registry. +try: # pragma: no cover - optional import + from server.api import registry as api_registry + + registry = api_registry +except Exception: # pragma: no cover - fallback + registry = TaskRegistry() + +app = FastAPI(title="OpenManus Task WS") + + +async def _get_event(task_queue: Any): + """Await an event from either asyncio.Queue or queue.Queue.""" + if isinstance(task_queue, asyncio.Queue): + return await task_queue.get() + if isinstance(task_queue, queue.Queue): + return await asyncio.to_thread(task_queue.get) + return None + + +@app.websocket("/tasks/{task_id}/stream") +async def task_stream(websocket: WebSocket, task_id: str): + await websocket.accept() + task = registry.get_task(task_id) + if not task: + await websocket.send_text(json.dumps({"error": "Task not found"})) + await websocket.close() + return + + event_queue = task.event_queue + + try: + while True: + recv_task = asyncio.create_task(websocket.receive_text()) + event_task = asyncio.create_task(_get_event(event_queue)) + + done, pending = await asyncio.wait( + {recv_task, event_task}, return_when=asyncio.FIRST_COMPLETED + ) + + for p in pending: + p.cancel() + + if recv_task in done: + try: + message = recv_task.result() + except WebSocketDisconnect: + return + except Exception: + message = "" + + if isinstance(message, str): + try: + data = json.loads(message) + except json.JSONDecodeError: + data = {"command": message} + command = data.get("command") + if command == "interrupt": + registry.interrupt_task(task_id) + await websocket.send_text( + json.dumps({"type": "interrupt_ack", "id": task_id}) + ) + + if event_task in done: + try: + event = event_task.result() + except Exception: + event = None + + if event is None: + continue + + payload = event if isinstance(event, dict) else {"event": event} + await websocket.send_text(json.dumps(payload)) + + except WebSocketDisconnect: + return + + +if __name__ == "__main__": # pragma: no cover + import uvicorn + + uvicorn.run(app, host="0.0.0.0", port=8001) From f8604d4e62ed394fb0338b94d369e981cf312e24 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 12:07:47 +0800 Subject: [PATCH 14/69] =?UTF-8?q?=E8=AF=B7=E6=96=B0=E5=A2=9E=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. TaskInterrupted → status = INTERRUPTED 2. 未捕获异常 → status = FAILED 3. 正常完成 → status = DONE 4. 所有状态变化 emit task.status 事件 不要改变业务逻辑,只补状态收敛。 --- core/task_runner.py | 34 ++++++++++++++++++++++++++++++++++ server/api.py | 13 ++++--------- 2 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 core/task_runner.py diff --git a/core/task_runner.py b/core/task_runner.py new file mode 100644 index 000000000..7bbb492ea --- /dev/null +++ b/core/task_runner.py @@ -0,0 +1,34 @@ +from typing import Any, Awaitable, Optional + +from app.agent.base import TaskInterrupted +from core.task import Task, TaskStatus + + +async def run_with_status( + task: Task, work: Awaitable[Any], mark_running: bool = True +) -> Any: + """Execute an awaitable and update task status with unified rules.""" + + def _set_status(status: TaskStatus, reason: Optional[str] = None) -> None: + task.status = status + payload = {"status": status.value} + if reason: + payload["reason"] = reason + task.emit("task.status", payload) + + if mark_running: + _set_status(TaskStatus.RUNNING) + + try: + result = await work + _set_status(TaskStatus.DONE) + return result + except TaskInterrupted: + _set_status(TaskStatus.INTERRUPTED) + raise + except Exception as exc: + _set_status(TaskStatus.FAILED, reason=str(exc)) + raise + + +__all__ = ["run_with_status"] diff --git a/server/api.py b/server/api.py index 914368a99..2cef0aebe 100644 --- a/server/api.py +++ b/server/api.py @@ -7,6 +7,7 @@ from app.agent.base import TaskInterrupted from core.task import TaskStatus from core.task_registry import TaskRegistry +from core.task_runner import run_with_status app = FastAPI(title="OpenManus Task API", version="0.1.0") @@ -18,17 +19,11 @@ async def _run_agent(task_id: str, prompt: Optional[str]) -> None: if not task: return - task.status = TaskStatus.RUNNING - try: + async def _work(): agent = await Manus.create() await agent.run(task, prompt) - if task.status == TaskStatus.RUNNING: - task.status = TaskStatus.DONE - except TaskInterrupted: - task.status = TaskStatus.INTERRUPTED - except Exception as exc: # pragma: no cover - background safety - task.status = TaskStatus.FAILED - task.emit("error", {"message": str(exc)}) + + await run_with_status(task, _work()) @app.post("/tasks") From 1ccc414f0db231bd11a5fafd562059989f4b3f12 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 14:16:41 +0800 Subject: [PATCH 15/69] add dockerfile and ci --- .github/workflows/web-smoke-test.yml | 51 ++++++++++++++++++++++++++++ Dockerfile | 31 +++++++++++++---- app/daytona/tool_base.py | 6 ++-- app/tool/base.py | 9 ++--- server/api.py | 8 +++-- 5 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/web-smoke-test.yml diff --git a/.github/workflows/web-smoke-test.yml b/.github/workflows/web-smoke-test.yml new file mode 100644 index 000000000..6cd08c62d --- /dev/null +++ b/.github/workflows/web-smoke-test.yml @@ -0,0 +1,51 @@ +name: Web Smoke Test + +on: + push: + pull_request: + +jobs: + smoke: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Start FastAPI server + run: | + uvicorn server.api:app --host 0.0.0.0 --port 8000 --workers 1 & + echo $! > server.pid + sleep 5 + + - name: Check /health + run: | + for i in {1..10}; do + if curl -sf http://127.0.0.1:8000/health > /tmp/health.json; then + cat /tmp/health.json + exit 0 + fi + sleep 2 + done + echo "Health endpoint not responding" + exit 1 + + - name: Check /docs + run: | + curl -sf http://127.0.0.1:8000/docs > /tmp/docs.html + grep -i "swagger" /tmp/docs.html + + - name: Stop server + if: always() + run: | + if [ -f server.pid ]; then kill $(cat server.pid) || true; fi diff --git a/Dockerfile b/Dockerfile index 9f7a19081..64f419cc7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,30 @@ -FROM python:3.12-slim +# syntax=docker/dockerfile:1.6 -WORKDIR /app/OpenManus +ARG PYTHON_VERSION=3.11-slim +FROM python:${PYTHON_VERSION} AS base -RUN apt-get update && apt-get install -y --no-install-recommends git curl \ - && rm -rf /var/lib/apt/lists/* \ - && (command -v uv >/dev/null 2>&1 || pip install --no-cache-dir uv) +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 \ + POETRY_VIRTUALENVS_CREATE=false \ + UVICORN_WORKERS=1 \ + HOST=0.0.0.0 \ + PORT=8000 + +WORKDIR /app + +# Install build deps only when needed +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + curl \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . +RUN pip install -r requirements.txt COPY . . -RUN uv pip install --system -r requirements.txt +EXPOSE 8000 -CMD ["bash"] +CMD ["uvicorn", "server.api:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"] diff --git a/app/daytona/tool_base.py b/app/daytona/tool_base.py index 043578a9a..6b99143c1 100644 --- a/app/daytona/tool_base.py +++ b/app/daytona/tool_base.py @@ -3,7 +3,7 @@ from typing import Any, ClassVar, Dict, Optional from daytona import Daytona, DaytonaConfig, Sandbox, SandboxState -from pydantic import Field +from pydantic import Field, ConfigDict from app.config import config from app.daytona.sandbox import create_sandbox, start_supervisord_session @@ -64,9 +64,7 @@ class SandboxToolsBase(BaseTool): workspace_path: str = Field(default="/workspace", exclude=True) _sessions: dict[str, str] = {} - class Config: - arbitrary_types_allowed = True # Allow non-pydantic types like ThreadManager - underscore_attrs_are_private = True + model_config = ConfigDict(arbitrary_types_allowed=True) async def _ensure_sandbox(self) -> Sandbox: """Ensure we have a valid sandbox instance, retrieving it from the project if needed.""" diff --git a/app/tool/base.py b/app/tool/base.py index fdb8b7d3a..5446af1bf 100644 --- a/app/tool/base.py +++ b/app/tool/base.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from typing import Any, Dict, Optional, Union -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, ConfigDict from app.utils.logger import logger @@ -43,8 +43,7 @@ class ToolResult(BaseModel): base64_image: Optional[str] = Field(default=None) system: Optional[str] = Field(default=None) - class Config: - arbitrary_types_allowed = True + model_config = ConfigDict(arbitrary_types_allowed=True) def __bool__(self): return any(getattr(self, field) for field in self.__fields__) @@ -96,9 +95,7 @@ class BaseTool(ABC, BaseModel): parameters: Optional[dict] = None # _schemas: Dict[str, List[ToolSchema]] = {} - class Config: - arbitrary_types_allowed = True - underscore_attrs_are_private = False + model_config = ConfigDict(arbitrary_types_allowed=True, protected_namespaces=()) # def __init__(self, **data): # """Initialize tool with model validation and schema registration.""" diff --git a/server/api.py b/server/api.py index 2cef0aebe..207fe76a3 100644 --- a/server/api.py +++ b/server/api.py @@ -3,13 +3,12 @@ import uvicorn from fastapi import BackgroundTasks, FastAPI, HTTPException -from app.agent.manus import Manus from app.agent.base import TaskInterrupted +from app.agent.manus import Manus from core.task import TaskStatus from core.task_registry import TaskRegistry from core.task_runner import run_with_status - app = FastAPI(title="OpenManus Task API", version="0.1.0") registry = TaskRegistry() @@ -56,5 +55,10 @@ async def interrupt_task(task_id: str): return {"id": task.id, "status": task.status, "interrupt_flag": task.interrupt_flag} +@app.get("/", tags=["health"]) +async def health(): + return {"status": "ok"} + + if __name__ == "__main__": # pragma: no cover uvicorn.run(app, host="0.0.0.0", port=8000) From d256128e3a6005bab9f1f3e7645c8dbb3a10551d Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 21:12:12 +0800 Subject: [PATCH 16/69] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使用 SQLAlchemy 定义 Task 模型,用于 PostgreSQL。 Task 字段: task_id (UUID, 主键) status (字符串) input (JSON) result (JSON, 可为空) created_at (时间戳) updated_at (时间戳) 将原来的内存 TaskRegistry 改成 DB 操作: get_task(task_id) create_task(...) update_task(task) ORM 模型放在 server/models.py。 禁止修改业务逻辑或 API 层。 保持与现有 /tasks API 接口兼容。 --- .github/workflows/docker-smoke-test.yml | 80 +++++++++++++++++++ Dockerfile | 27 ++++--- core/task_registry.py | 102 +++++++++++++++++------- requirements.txt | 2 + server/models.py | 24 ++++++ 5 files changed, 195 insertions(+), 40 deletions(-) create mode 100644 .github/workflows/docker-smoke-test.yml create mode 100644 server/models.py diff --git a/.github/workflows/docker-smoke-test.yml b/.github/workflows/docker-smoke-test.yml new file mode 100644 index 000000000..dffa71b4b --- /dev/null +++ b/.github/workflows/docker-smoke-test.yml @@ -0,0 +1,80 @@ +name: Docker Smoke Test + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + smoke: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build image + run: docker build -t openmanus:latest . + + - name: Run container + run: | + docker run -d -p 8000:8000 --name openmanus openmanus:latest + # start websocket server inside container on port 8001 + docker exec openmanus sh -c "uvicorn server.ws:app --host 0.0.0.0 --port 8001 --workers 1 >/tmp/ws.log 2>&1 & echo \$! >/tmp/ws.pid" + sleep 8 + + - name: Check /health + run: curl --fail http://127.0.0.1:8000/health + + - name: Check /docs + run: curl --fail http://127.0.0.1:8000/docs + + - name: Install tooling for task test + run: | + sudo apt-get update && sudo apt-get install -y jq + python -m pip install --upgrade pip + pip install websockets + + - name: Simulate task lifecycle with interrupt and event stream + run: | + set -e + TASK_JSON=$(curl -s -X POST http://127.0.0.1:8000/tasks) + echo "Task created: $TASK_JSON" + TASK_ID=$(echo "$TASK_JSON" | jq -r '.id') + if [ -z "$TASK_ID" ] || [ "$TASK_ID" = "null" ]; then + echo "Failed to parse task id"; exit 1; fi + export TASK_ID + + python - <<'PY' +import asyncio, json, websockets, os, sys +task_id = os.environ["TASK_ID"] +uri = f"ws://127.0.0.1:8001/tasks/{task_id}/stream" +events = [] +async def main(): + try: + async with websockets.connect(uri) as ws: + # send interrupt quickly to avoid long-running agent + await ws.send(json.dumps({"command": "interrupt"})) + try: + for _ in range(10): + msg = await asyncio.wait_for(ws.recv(), timeout=10) + events.append(msg) + if len(events) >= 2: + break + except asyncio.TimeoutError: + pass + except Exception as e: + print("WebSocket error:", e, file=sys.stderr) + sys.exit(1) +asyncio.run(main()) +if not events: + print("No events received"); sys.exit(1) +print("Received events:", events) +PY + + - name: Stop container + if: always() + run: | + docker stop openmanus || true + docker rm openmanus || true diff --git a/Dockerfile b/Dockerfile index 64f419cc7..de42ffe86 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,30 +1,33 @@ # syntax=docker/dockerfile:1.6 -ARG PYTHON_VERSION=3.11-slim -FROM python:${PYTHON_VERSION} AS base +FROM python:3.10-slim ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1 \ - POETRY_VIRTUALENVS_CREATE=false \ - UVICORN_WORKERS=1 \ HOST=0.0.0.0 \ - PORT=8000 + PORT=8000 \ + WORKERS=1 WORKDIR /app -# Install build deps only when needed -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ - curl \ - && rm -rf /var/lib/apt/lists/* +# Install runtime curl for healthcheck (small) and create non-root user +RUN apt-get update && apt-get install -y --no-install-recommends curl \ + && rm -rf /var/lib/apt/lists/* \ + && addgroup --system app && adduser --system --ingroup app app COPY requirements.txt . -RUN pip install -r requirements.txt +RUN pip install --no-cache-dir -r requirements.txt COPY . . +# Adjust ownership for non-root execution +RUN chown -R app:app /app +USER app + EXPOSE 8000 -CMD ["uvicorn", "server.api:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"] +HEALTHCHECK --interval=30s --timeout=5s --retries=3 CMD curl -f http://localhost:${PORT}/health || exit 1 + +CMD ["sh", "-c", "uvicorn server.api:app --host ${HOST:-0.0.0.0} --port ${PORT:-8000} --workers ${WORKERS:-1}"] diff --git a/core/task_registry.py b/core/task_registry.py index b2513888d..ca97bd593 100644 --- a/core/task_registry.py +++ b/core/task_registry.py @@ -1,51 +1,97 @@ from __future__ import annotations +import asyncio +import os import threading import uuid -from typing import Dict, Optional +from typing import Optional -from core.task import Task +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from core.task import Task, TaskStatus +from server.models import Base, TaskORM -class TaskRegistry: - """In-memory registry for Task objects. - Designed to be framework-agnostic so it can back future HTTP or WebSocket - layers without introducing those dependencies here. - """ +class TaskRegistry: + """Database-backed registry for Task objects using SQLAlchemy.""" - def __init__(self) -> None: - self._tasks: Dict[str, Task] = {} + def __init__(self, db_url: Optional[str] = None) -> None: self._lock = threading.RLock() + self.db_url = db_url or os.getenv( + "DATABASE_URL", "postgresql+psycopg2://postgres:postgres@localhost:5432/openmanus" + ) + self.engine = create_engine(self.db_url) + Base.metadata.create_all(self.engine) + self.SessionLocal = sessionmaker(bind=self.engine, expire_on_commit=False) - def create_task(self, task_id: Optional[str] = None, **task_kwargs) -> Task: - """Create and register a new task. + def _to_task(self, orm: TaskORM) -> Task: + status = TaskStatus(orm.status) if orm.status in TaskStatus._value2member_map_ else TaskStatus.CREATED + # Use fresh queue per retrieval; events are in-memory only + return Task( + id=str(orm.task_id), + status=status, + event_queue=asyncio.Queue(), + interrupt_flag=False, + ) - task_id: Optional explicit id; if omitted, a UUID4 string is used. - task_kwargs: Forwarded to Task constructor (e.g., custom event_queue). - """ + def create_task( + self, task_id: Optional[str] = None, input: Optional[dict] = None, **task_kwargs + ) -> Task: with self._lock: tid = task_id or str(uuid.uuid4()) - if tid in self._tasks: - raise ValueError(f"Task with id '{tid}' already exists") - - task = Task(id=tid, **task_kwargs) - self._tasks[tid] = task - return task + session = self.SessionLocal() + try: + orm = TaskORM(task_id=tid, status=TaskStatus.CREATED.value, input=input) + session.add(orm) + session.commit() + task = Task(id=tid, status=TaskStatus.CREATED, **task_kwargs) + return task + finally: + session.close() def get_task(self, task_id: str) -> Optional[Task]: - """Retrieve a task by id.""" with self._lock: - return self._tasks.get(task_id) + session = self.SessionLocal() + try: + orm = session.get(TaskORM, task_id) + if orm is None: + return None + return self._to_task(orm) + finally: + session.close() + + def update_task(self, task: Task, result: Optional[dict] = None) -> Task: + with self._lock: + session = self.SessionLocal() + try: + orm = session.get(TaskORM, task.id) + if orm is None: + orm = TaskORM(task_id=task.id) + session.add(orm) + orm.status = task.status.value if isinstance(task.status, TaskStatus) else str(task.status) + if hasattr(task, "input"): + orm.input = getattr(task, "input") + orm.result = result if result is not None else orm.result + session.commit() + return task + finally: + session.close() def interrupt_task(self, task_id: str) -> Optional[Task]: - """Interrupt a task if it exists; returns the task or None.""" with self._lock: - task = self._tasks.get(task_id) - if task is None: - return None - task.interrupt() - return task + session = self.SessionLocal() + try: + orm = session.get(TaskORM, task_id) + if orm is None: + return None + orm.status = TaskStatus.INTERRUPTED.value + session.commit() + task = self._to_task(orm) + task.interrupt() + return task + finally: + session.close() __all__ = ["TaskRegistry"] diff --git a/requirements.txt b/requirements.txt index b1585b442..56a91fe0f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -40,3 +40,5 @@ crawl4ai~=0.6.3 huggingface-hub~=0.29.2 setuptools~=75.8.0 +sqlalchemy~=2.0.36 +psycopg2-binary~=2.9.10 diff --git a/server/models.py b/server/models.py new file mode 100644 index 000000000..6e9743173 --- /dev/null +++ b/server/models.py @@ -0,0 +1,24 @@ +import uuid +from datetime import datetime + +from sqlalchemy import Column, DateTime, String, func +from sqlalchemy.dialects.postgresql import JSONB, UUID +from sqlalchemy.orm import declarative_base + +Base = declarative_base() + + +class TaskORM(Base): + __tablename__ = "tasks" + + task_id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + status = Column(String, nullable=False) + input = Column(JSONB, nullable=True) + result = Column(JSONB, nullable=True) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column( + DateTime(timezone=True), server_default=func.now(), onupdate=func.now() + ) + + +__all__ = ["Base", "TaskORM"] From 558917bcf1c02983ad37351e283a503c02636ff0 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 23:21:33 +0800 Subject: [PATCH 17/69] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使用 Celery 作为异步任务执行框架。 创建 server/celery_app.py,初始化 Celery: broker 使用 Redis (redis://redis:6379/0) backend 使用 PostgreSQL 或 Redis 将 Task 执行逻辑包装成 Celery task: 接收 task_id,执行原来逻辑 执行完成后更新数据库 task.status = COMPLETED 将执行结果写入 task.result FastAPI 的 /tasks POST API: 创建 Task(写 DB) 立即调用 Celery 异步执行 FastAPI 的 /tasks/{task_id} GET API: 直接查询数据库 不改变现有 API 路径。 --- requirements.txt | 2 ++ server/api.py | 12 ++++++------ server/celery_app.py | 19 +++++++++++++++++++ server/tasks.py | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 server/celery_app.py create mode 100644 server/tasks.py diff --git a/requirements.txt b/requirements.txt index 56a91fe0f..e14746971 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,3 +42,5 @@ huggingface-hub~=0.29.2 setuptools~=75.8.0 sqlalchemy~=2.0.36 psycopg2-binary~=2.9.10 +celery~=5.4.0 +redis~=5.2.1 diff --git a/server/api.py b/server/api.py index 207fe76a3..b8c5ecf45 100644 --- a/server/api.py +++ b/server/api.py @@ -8,29 +8,29 @@ from core.task import TaskStatus from core.task_registry import TaskRegistry from core.task_runner import run_with_status +from server.tasks import run_task app = FastAPI(title="OpenManus Task API", version="0.1.0") registry = TaskRegistry() async def _run_agent(task_id: str, prompt: Optional[str]) -> None: + # Legacy background runner (unused when Celery is available) task = registry.get_task(task_id) if not task: return - async def _work(): agent = await Manus.create() await agent.run(task, prompt) - await run_with_status(task, _work()) @app.post("/tasks") -async def create_task(prompt: Optional[str] = None, background: BackgroundTasks = None): - task = registry.create_task() +async def create_task(prompt: Optional[str] = None): + task = registry.create_task(input={"prompt": prompt} if prompt else None) task.status = TaskStatus.CREATED - if background is not None: - background.add_task(_run_agent, task.id, prompt) + # enqueue Celery task + run_task.delay(task.id, prompt) return {"id": task.id, "status": task.status} diff --git a/server/celery_app.py b/server/celery_app.py new file mode 100644 index 000000000..264b5f921 --- /dev/null +++ b/server/celery_app.py @@ -0,0 +1,19 @@ +import os + +from celery import Celery + +broker_url = os.getenv("CELERY_BROKER_URL", "redis://redis:6379/0") +backend_url = os.getenv("CELERY_RESULT_BACKEND", os.getenv("DATABASE_URL", "redis://redis:6379/0")) + +celery_app = Celery("openmanus", broker=broker_url, backend=backend_url) + +celery_app.conf.update( + task_serializer="json", + accept_content=["json"], + result_serializer="json", + timezone="UTC", + task_always_eager=False, +) + + +__all__ = ["celery_app"] diff --git a/server/tasks.py b/server/tasks.py new file mode 100644 index 000000000..1553222f0 --- /dev/null +++ b/server/tasks.py @@ -0,0 +1,39 @@ +import asyncio +from typing import Optional + +from app.agent.manus import Manus +from core.task import Task, TaskStatus +from core.task_registry import TaskRegistry +from server.celery_app import celery_app + +registry = TaskRegistry() + + +@celery_app.task(name="run_task") +def run_task(task_id: str, prompt: Optional[str] = None): + """Celery task wrapper to execute Manus agent and persist status/result.""" + task = registry.get_task(task_id) + if task is None: + return {"error": "task not found"} + + async def _run(): + agent = await Manus.create() + result = await agent.run(task, prompt) + return result + + try: + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + result = loop.run_until_complete(_run()) + task.status = "COMPLETED" + registry.update_task(task, result={"output": result}) + return {"status": "COMPLETED", "result": result} + except Exception as exc: # pragma: no cover + task.status = TaskStatus.FAILED + registry.update_task(task, result={"error": str(exc)}) + return {"status": "FAILED", "error": str(exc)} + finally: + try: + loop.close() + except Exception: + pass From c79a178840d63cd445f0f6e7ee84d6e283a8f042 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 23:23:38 +0800 Subject: [PATCH 18/69] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=EF=BC=9A=201.=20=E4=BF=AE=E6=94=B9=20server/api.py=EF=BC=8C?= =?UTF-8?q?=E4=BD=BF=20API=20=E6=9F=A5=E8=AF=A2=E5=92=8C=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E8=AF=BB=E5=8F=96=20PostgreSQL=E3=80=82=202.?= =?UTF-8?q?=20POST=20/tasks=EF=BC=9A=20=20=20=20-=20=E5=86=99=E5=85=A5=20D?= =?UTF-8?q?B=20=20=20=20-=20=E8=B0=83=E7=94=A8=20Celery=20task=20=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E6=89=A7=E8=A1=8C=20=20=20=20-=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=20task=5Fid=20=E5=92=8C=20status=3DCREATED=203.=20GET=20/tasks?= =?UTF-8?q?/{task=5Fid}=EF=BC=9A=20=20=20=20-=20=E6=9F=A5=E8=AF=A2=20DB=20?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=20status=20+=20result=204.=20POST=20/tasks/{?= =?UTF-8?q?task=5Fid}/interrupt=EF=BC=9A=20=20=20=20-=20=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=20DB=20task.status=3DINTERRUPTED=20=20=20=20-=20=E5=8F=AF?= =?UTF-8?q?=E5=8F=91=E9=80=81=20Celery=20revoke=20=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E5=8F=96=E6=B6=88=E4=BB=BB=E5=8A=A1=205.=20=E4=BF=9D=E6=8C=81?= =?UTF-8?q?=20FastAPI=20=E8=B7=AF=E7=94=B1=E4=B8=8D=E5=8F=98=206.=20?= =?UTF-8?q?=E4=B8=8D=E4=BF=AE=E6=94=B9=E4=B8=9A=E5=8A=A1=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/api.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/server/api.py b/server/api.py index b8c5ecf45..9e906428f 100644 --- a/server/api.py +++ b/server/api.py @@ -9,6 +9,8 @@ from core.task_registry import TaskRegistry from core.task_runner import run_with_status from server.tasks import run_task +from server.celery_app import celery_app +from server.models import TaskORM app = FastAPI(title="OpenManus Task API", version="0.1.0") registry = TaskRegistry() @@ -29,30 +31,38 @@ async def _work(): async def create_task(prompt: Optional[str] = None): task = registry.create_task(input={"prompt": prompt} if prompt else None) task.status = TaskStatus.CREATED - # enqueue Celery task - run_task.delay(task.id, prompt) + # enqueue Celery task with deterministic task_id for revoke + run_task.apply_async(args=[task.id, prompt], task_id=task.id) return {"id": task.id, "status": task.status} @app.get("/tasks/{task_id}") async def get_task(task_id: str): - task = registry.get_task(task_id) - if not task: - raise HTTPException(status_code=404, detail="Task not found") - - return { - "id": task.id, - "status": task.status, - "interrupt_flag": task.interrupt_flag, - } + with registry.SessionLocal() as session: + orm = session.get(TaskORM, task_id) + if orm is None: + raise HTTPException(status_code=404, detail="Task not found") + return { + "id": str(orm.task_id), + "status": orm.status, + "result": orm.result, + } @app.post("/tasks/{task_id}/interrupt") async def interrupt_task(task_id: str): - task = registry.interrupt_task(task_id) - if not task: - raise HTTPException(status_code=404, detail="Task not found") - return {"id": task.id, "status": task.status, "interrupt_flag": task.interrupt_flag} + with registry.SessionLocal() as session: + orm = session.get(TaskORM, task_id) + if orm is None: + raise HTTPException(status_code=404, detail="Task not found") + orm.status = TaskStatus.INTERRUPTED.value + session.commit() + # best-effort revoke Celery task + try: + celery_app.control.revoke(task_id, terminate=True) + except Exception: + pass + return {"id": task_id, "status": TaskStatus.INTERRUPTED.value} @app.get("/", tags=["health"]) From a4b444b658f4ce23258cf487de331e677238e9b4 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 23:24:54 +0800 Subject: [PATCH 19/69] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=EF=BC=9A=201.=20=E5=9C=A8=E9=A1=B9=E7=9B=AE=E6=A0=B9=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=20Dockerfile=EF=BC=8C=E7=94=A8=E4=BA=8E=20FastAPI=20W?= =?UTF-8?q?eb=EF=BC=9A=20=20=20=20-=20Python=203.10-slim=20=20=20=20-=20?= =?UTF-8?q?=E5=AE=89=E8=A3=85=20requirements.txt=20=20=20=20-=20CMD=20uvic?= =?UTF-8?q?orn=20main:app=20--host=200.0.0.0=20--port=208000=202.=20?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=20docker-compose.yml=EF=BC=9A=20=20=20=20-?= =?UTF-8?q?=20=E6=9C=8D=E5=8A=A1=EF=BC=9A=20=20=20=20=20=20a)=20web:=20Fas?= =?UTF-8?q?tAPI=20=20=20=20=20=20b)=20worker:=20Celery=20Worker=EF=BC=8C?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=20Redis=20+=20PostgreSQL=20=20=20=20=20=20c)?= =?UTF-8?q?=20redis:=20=E6=9C=80=E6=96=B0=E5=AE=98=E6=96=B9=E9=95=9C?= =?UTF-8?q?=E5=83=8F=20=20=20=20=20=20d)=20postgres:=20=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E5=AE=98=E6=96=B9=E9=95=9C=E5=83=8F=EF=BC=8C=E6=8C=81=E4=B9=85?= =?UTF-8?q?=E5=8C=96=E5=8D=B7=20=20=20=20-=20=E7=BD=91=E7=BB=9C=E4=BA=92?= =?UTF-8?q?=E9=80=9A=20=20=20=20-=20=E6=98=BE=E5=BC=8F=E6=9A=B4=E9=9C=B2?= =?UTF-8?q?=E7=AB=AF=E5=8F=A3=208000=203.=20Web=20=E4=B8=8E=20Worker=20?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=90=8C=E4=B8=80=E4=BB=A3=E7=A0=81=E5=BA=93?= =?UTF-8?q?=204.=20=E4=BF=9D=E6=8C=81=20API=20=E4=B8=8E=20DB=20=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E5=8F=82=E6=95=B0=E4=B8=80=E8=87=B4=205.=20=E4=B8=8D?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=9A=E5=8A=A1=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 18 ++---------------- docker-compose.yml | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 16 deletions(-) create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile index de42ffe86..f873ce0fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,29 +5,15 @@ FROM python:3.10-slim ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ - PIP_DISABLE_PIP_VERSION_CHECK=1 \ - HOST=0.0.0.0 \ - PORT=8000 \ - WORKERS=1 + PIP_DISABLE_PIP_VERSION_CHECK=1 WORKDIR /app -# Install runtime curl for healthcheck (small) and create non-root user -RUN apt-get update && apt-get install -y --no-install-recommends curl \ - && rm -rf /var/lib/apt/lists/* \ - && addgroup --system app && adduser --system --ingroup app app - COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . -# Adjust ownership for non-root execution -RUN chown -R app:app /app -USER app - EXPOSE 8000 -HEALTHCHECK --interval=30s --timeout=5s --retries=3 CMD curl -f http://localhost:${PORT}/health || exit 1 - -CMD ["sh", "-c", "uvicorn server.api:app --host ${HOST:-0.0.0.0} --port ${PORT:-8000} --workers ${WORKERS:-1}"] +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..5afc622c8 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,47 @@ +version: "3.9" + +services: + web: + build: . + image: openmanus-web:latest + command: uvicorn main:app --host 0.0.0.0 --port 8000 + ports: + - "8000:8000" + environment: + - DATABASE_URL=postgresql+psycopg2://postgres:postgres@postgres:5432/openmanus + - CELERY_BROKER_URL=redis://redis:6379/0 + - CELERY_RESULT_BACKEND=redis://redis:6379/0 + depends_on: + - postgres + - redis + + worker: + build: . + image: openmanus-worker:latest + command: celery -A server.celery_app.celery_app worker -l info + environment: + - DATABASE_URL=postgresql+psycopg2://postgres:postgres@postgres:5432/openmanus + - CELERY_BROKER_URL=redis://redis:6379/0 + - CELERY_RESULT_BACKEND=redis://redis:6379/0 + depends_on: + - postgres + - redis + + redis: + image: redis:latest + ports: + - "6379:6379" + + postgres: + image: postgres:latest + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=openmanus + volumes: + - pgdata:/var/lib/postgresql/data + ports: + - "5432:5432" + +volumes: + pgdata: From 20446120511aafa283c135743e4828f33be534da Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Mon, 12 Jan 2026 23:26:17 +0800 Subject: [PATCH 20/69] =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=EF=BC=9A=201.=20=E5=88=9B=E5=BB=BA=20.github/workflows/docker-?= =?UTF-8?q?celery-smoke-test.yml=202.=20CI=20=E6=AD=A5=E9=AA=A4=EF=BC=9A?= =?UTF-8?q?=20=20=20=20a)=20checkout=20=E4=BB=A3=E7=A0=81=20=20=20=20b)=20?= =?UTF-8?q?build=20docker-compose=20=20=20=20c)=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E5=AE=B9=E5=99=A8=20(web=20+=20worker=20+=20redis=20+=20postgr?= =?UTF-8?q?es)=20=20=20=20d)=20=E7=AD=89=E5=BE=85=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=20=20=20=20e)=20=E9=AA=8C=E8=AF=81=20/health?= =?UTF-8?q?=20=E8=BF=94=E5=9B=9E=20200=20=20=20=20f)=20=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=20/docs=20=E8=BF=94=E5=9B=9E=20200=20=20=20=20g)=20=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=20/tasks=20POST=20+=20GET=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=20status=20=20=20=20h)=20=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E5=B9=B6=E6=B8=85=E7=90=86=E5=AE=B9=E5=99=A8=203.=20=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E4=BB=BB=E6=84=8F=E6=AD=A5=E9=AA=A4=20CI=20=E7=BA=A2?= =?UTF-8?q?=E7=81=AF=204.=20=E4=B8=8D=E4=BF=AE=E6=94=B9=E6=BA=90=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=B8=9A=E5=8A=A1=E9=80=BB=E8=BE=91=205.=20Docker=20+?= =?UTF-8?q?=20Celery=20+=20DB=20=E5=BF=85=E9=A1=BB=E5=92=8C=20PR=20?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workflows/docker-celery-smoke-test.yml | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/docker-celery-smoke-test.yml diff --git a/.github/workflows/docker-celery-smoke-test.yml b/.github/workflows/docker-celery-smoke-test.yml new file mode 100644 index 000000000..198cc62cb --- /dev/null +++ b/.github/workflows/docker-celery-smoke-test.yml @@ -0,0 +1,58 @@ +name: Docker Celery Smoke Test + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + smoke: + runs-on: ubuntu-latest + + services: + docker: + image: docker:24.0.5-dind + privileged: true + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and start stack + run: | + docker compose build + docker compose up -d + sleep 10 + + - name: Check /health + run: curl --fail http://127.0.0.1:8000/health + + - name: Check /docs + run: curl --fail http://127.0.0.1:8000/docs + + - name: Task create and poll + run: | + set -e + TASK_JSON=$(curl -s -X POST http://127.0.0.1:8000/tasks -H "Content-Type: application/json" -d '{"prompt":"ping"}') + echo "Created: $TASK_JSON" + TASK_ID=$(echo "$TASK_JSON" | python -c "import sys, json; print(json.load(sys.stdin)['id'])") + if [ -z "$TASK_ID" ]; then echo "No task id"; exit 1; fi + for i in {1..10}; do + STATUS_JSON=$(curl -s http://127.0.0.1:8000/tasks/$TASK_ID) + echo "Status: $STATUS_JSON" + STATUS=$(echo "$STATUS_JSON" | python -c "import sys, json; print(json.load(sys.stdin).get('status'))") + if [ "$STATUS" = "COMPLETED" ] || [ "$STATUS" = "FAILED" ] || [ "$STATUS" = "INTERRUPTED" ]; then + exit 0 + fi + sleep 2 + done + echo "Task did not complete in time" + exit 1 + + - name: Tear down + if: always() + run: docker compose down -v From 29d352a38c9ca5dfdd7450d9545f6a5429e2b276 Mon Sep 17 00:00:00 2001 From: LukeJiaoR <460388402@qq.com> Date: Tue, 13 Jan 2026 02:13:25 +0800 Subject: [PATCH 21/69] fix pre-commit check --- .github/workflows/docker-smoke-test.yml | 50 ++++++++++++------------- .pre-commit-config.yaml | 2 +- app/agent/__init__.py | 4 +- app/agent/base.py | 4 +- app/agent/browser.py | 4 +- app/agent/executor.py | 4 +- app/agent/manus.py | 2 +- app/agent/mcp.py | 10 ++--- app/agent/planner.py | 8 ++-- app/agent/sandbox_agent.py | 4 +- app/agent/toolcall.py | 12 +++--- app/daytona/tool_base.py | 2 +- app/tool/base.py | 2 +- context/engine.py | 11 ++++-- core/task.py | 5 ++- core/task_registry.py | 15 ++++++-- server/api.py | 8 ++-- server/celery_app.py | 5 ++- server/models.py | 2 +- server/tasks.py | 3 +- server/ws.py | 1 + tools/runner.py | 23 +++++++++--- 22 files changed, 106 insertions(+), 75 deletions(-) diff --git a/.github/workflows/docker-smoke-test.yml b/.github/workflows/docker-smoke-test.yml index dffa71b4b..901e25385 100644 --- a/.github/workflows/docker-smoke-test.yml +++ b/.github/workflows/docker-smoke-test.yml @@ -47,31 +47,31 @@ jobs: export TASK_ID python - <<'PY' -import asyncio, json, websockets, os, sys -task_id = os.environ["TASK_ID"] -uri = f"ws://127.0.0.1:8001/tasks/{task_id}/stream" -events = [] -async def main(): - try: - async with websockets.connect(uri) as ws: - # send interrupt quickly to avoid long-running agent - await ws.send(json.dumps({"command": "interrupt"})) - try: - for _ in range(10): - msg = await asyncio.wait_for(ws.recv(), timeout=10) - events.append(msg) - if len(events) >= 2: - break - except asyncio.TimeoutError: - pass - except Exception as e: - print("WebSocket error:", e, file=sys.stderr) - sys.exit(1) -asyncio.run(main()) -if not events: - print("No events received"); sys.exit(1) -print("Received events:", events) -PY + import asyncio, json, websockets, os, sys + task_id = os.environ["TASK_ID"] + uri = f"ws://127.0.0.1:8001/tasks/{task_id}/stream" + events = [] + async def main(): + try: + async with websockets.connect(uri) as ws: + # send interrupt quickly to avoid long-running agent + await ws.send(json.dumps({"command": "interrupt"})) + try: + for _ in range(10): + msg = await asyncio.wait_for(ws.recv(), timeout=10) + events.append(msg) + if len(events) >= 2: + break + except asyncio.TimeoutError: + pass + except Exception as e: + print("WebSocket error:", e, file=sys.stderr) + sys.exit(1) + asyncio.run(main()) + if not events: + print("No events received"); sys.exit(1) + print("Received events:", events) + PY - name: Stop container if: always() diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 84be37205..d9f765f23 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: black - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer diff --git a/app/agent/__init__.py b/app/agent/__init__.py index 4ce029051..0e67b0651 100644 --- a/app/agent/__init__.py +++ b/app/agent/__init__.py @@ -1,9 +1,9 @@ from app.agent.base import BaseAgent from app.agent.browser import BrowserAgent -from app.agent.mcp import MCPAgent from app.agent.executor import ExecutorAgent -from app.agent.react import ReActAgent +from app.agent.mcp import MCPAgent from app.agent.planner import PlannerAgent +from app.agent.react import ReActAgent from app.agent.swe import SWEAgent from app.agent.toolcall import ToolCallAgent diff --git a/app/agent/base.py b/app/agent/base.py index a848ade8d..77e32a734 100644 --- a/app/agent/base.py +++ b/app/agent/base.py @@ -157,7 +157,9 @@ async def run(self, task: Task, input: Any) -> str: if self.current_step >= self.max_steps: self.current_step = 0 self.state = AgentState.IDLE - termination_msg = f"Terminated: Reached max steps ({self.max_steps})" + termination_msg = ( + f"Terminated: Reached max steps ({self.max_steps})" + ) results.append(termination_msg) task.emit("terminated", {"reason": termination_msg}) return "\n".join(results) if results else "No steps executed" diff --git a/app/agent/browser.py b/app/agent/browser.py index acf1fd0ce..e77fe63e3 100644 --- a/app/agent/browser.py +++ b/app/agent/browser.py @@ -3,8 +3,8 @@ from pydantic import Field, model_validator -from app.agent.toolcall import ToolCallAgent from app.agent.base import Task, TaskInterrupted +from app.agent.toolcall import ToolCallAgent from app.prompt.browser import NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.schema import Message, ToolChoice from app.tool import BrowserUseTool, Terminate, ToolCollection @@ -38,7 +38,7 @@ async def get_browser_state(self) -> Optional[dict]: else: self._current_base64_image = None return json.loads(result.output) - except Exception as e: + except Exception: return None async def format_next_step_prompt(self) -> str: diff --git a/app/agent/executor.py b/app/agent/executor.py index 4b0a7d259..781854216 100644 --- a/app/agent/executor.py +++ b/app/agent/executor.py @@ -1,8 +1,8 @@ import json -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Union -from app.agent.toolcall import ToolCallAgent from app.agent.base import Task, TaskInterrupted +from app.agent.toolcall import ToolCallAgent class ExecutorAgent(ToolCallAgent): diff --git a/app/agent/manus.py b/app/agent/manus.py index cb4bc0190..c31758e9b 100644 --- a/app/agent/manus.py +++ b/app/agent/manus.py @@ -2,9 +2,9 @@ from pydantic import Field, model_validator +from app.agent.base import Task, TaskInterrupted from app.agent.browser import BrowserContextHelper from app.agent.toolcall import ToolCallAgent -from app.agent.base import Task, TaskInterrupted from app.config import config from app.prompt.manus import NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.tool import Terminate, ToolCollection diff --git a/app/agent/mcp.py b/app/agent/mcp.py index 90f6d3772..3531cc230 100644 --- a/app/agent/mcp.py +++ b/app/agent/mcp.py @@ -2,8 +2,8 @@ from pydantic import Field -from app.agent.toolcall import ToolCallAgent from app.agent.base import Task, TaskInterrupted +from app.agent.toolcall import ToolCallAgent from app.prompt.mcp import MULTIMEDIA_RESPONSE_PROMPT, NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.schema import AgentState, Message from app.tool.base import ToolResult @@ -148,9 +148,7 @@ async def think(self, task: Task) -> bool: await self._refresh_tools(task) # All tools removed indicates shutdown if not self.mcp_clients.tool_map: - task.emit( - "info", {"message": "MCP service has shut down, ending run."} - ) + task.emit("info", {"message": "MCP service has shut down, ending run."}) self.state = AgentState.FINISHED return False @@ -162,7 +160,9 @@ async def _handle_special_tool( ) -> None: """Handle special tool execution and state changes""" # First process with parent handler - await super()._handle_special_tool(task=task, name=name, result=result, **kwargs) + await super()._handle_special_tool( + task=task, name=name, result=result, **kwargs + ) # Handle multimedia responses if isinstance(result, ToolResult) and result.base64_image: diff --git a/app/agent/planner.py b/app/agent/planner.py index cc2cdb068..b36ac9848 100644 --- a/app/agent/planner.py +++ b/app/agent/planner.py @@ -4,9 +4,9 @@ from pydantic import Field from app.agent.base import BaseAgent, Task, TaskInterrupted -from context.engine import ContextEngine -from app.schema import Message from app.prompt.planning import PLANNING_SYSTEM_PROMPT +from app.schema import Message +from context.engine import ContextEngine class PlannerAgent(BaseAgent): @@ -40,9 +40,7 @@ async def run(self, task: Task, input: Any) -> List[Dict[str, Any]]: task.emit("plan.done", {"steps": len(plan), "plan": plan}) return plan - async def _generate_plan( - self, task: Task, request: str - ) -> List[Dict[str, Any]]: + async def _generate_plan(self, task: Task, request: str) -> List[Dict[str, Any]]: """Use the existing LLM to create a structured plan without calling tools.""" if task.is_interrupted(): raise TaskInterrupted() diff --git a/app/agent/sandbox_agent.py b/app/agent/sandbox_agent.py index edde7199f..ec0ea8079 100644 --- a/app/agent/sandbox_agent.py +++ b/app/agent/sandbox_agent.py @@ -2,9 +2,9 @@ from pydantic import Field, model_validator +from app.agent.base import Task, TaskInterrupted from app.agent.browser import BrowserContextHelper from app.agent.toolcall import ToolCallAgent -from app.agent.base import Task, TaskInterrupted from app.config import config from app.daytona.sandbox import create_sandbox, delete_sandbox from app.daytona.tool_base import SandboxToolsBase @@ -104,7 +104,7 @@ async def initialize_sandbox_tools( ] self.available_tools.add_tools(*sb_tools) - except Exception as e: + except Exception: raise async def initialize_mcp_servers(self) -> None: diff --git a/app/agent/toolcall.py b/app/agent/toolcall.py index 4ab5e4ec7..c49b6918b 100644 --- a/app/agent/toolcall.py +++ b/app/agent/toolcall.py @@ -4,13 +4,13 @@ from pydantic import Field -from app.agent.react import ReActAgent from app.agent.base import Task, TaskInterrupted -from context.engine import ContextEngine +from app.agent.react import ReActAgent from app.exceptions import TokenLimitExceeded from app.prompt.toolcall import NEXT_STEP_PROMPT, SYSTEM_PROMPT from app.schema import TOOL_CHOICE_TYPE, AgentState, Message, ToolCall, ToolChoice from app.tool import CreateChatCompletion, Terminate, ToolCollection +from context.engine import ContextEngine TOOL_CALL_REQUIRED = "Tool calls required but none provided" @@ -98,7 +98,9 @@ async def think(self, task: Task) -> bool: "agent": self.name, "content": content, "tool_count": len(tool_calls) if tool_calls else 0, - "tools": [call.function.name for call in tool_calls] if tool_calls else [], + "tools": [call.function.name for call in tool_calls] + if tool_calls + else [], "arguments": tool_calls[0].function.arguments if tool_calls else None, }, ) @@ -239,9 +241,7 @@ async def execute_tool(self, command: ToolCall, task: Task) -> str: ) return f"Error: {error_msg}" - async def _handle_special_tool( - self, task: Task, name: str, result: Any, **kwargs - ): + async def _handle_special_tool(self, task: Task, name: str, result: Any, **kwargs): """Handle special tool execution and state changes.""" if not self._is_special_tool(name): return diff --git a/app/daytona/tool_base.py b/app/daytona/tool_base.py index 6b99143c1..5312e1194 100644 --- a/app/daytona/tool_base.py +++ b/app/daytona/tool_base.py @@ -3,7 +3,7 @@ from typing import Any, ClassVar, Dict, Optional from daytona import Daytona, DaytonaConfig, Sandbox, SandboxState -from pydantic import Field, ConfigDict +from pydantic import ConfigDict, Field from app.config import config from app.daytona.sandbox import create_sandbox, start_supervisord_session diff --git a/app/tool/base.py b/app/tool/base.py index 5446af1bf..6857f3681 100644 --- a/app/tool/base.py +++ b/app/tool/base.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from typing import Any, Dict, Optional, Union -from pydantic import BaseModel, Field, ConfigDict +from pydantic import BaseModel, ConfigDict, Field from app.utils.logger import logger diff --git a/context/engine.py b/context/engine.py index 622525800..893205197 100644 --- a/context/engine.py +++ b/context/engine.py @@ -1,9 +1,9 @@ from __future__ import annotations +import asyncio import json -from typing import Any, Dict, List, Optional import queue -import asyncio +from typing import Any, Dict, List, Optional from core.task import Task @@ -82,7 +82,8 @@ def _collect_recent(events: List[Dict[str, Any]], limit: int = 5) -> List[Any]: tool_events = [ ev for ev in events - if ev.get("type") in {"tool.call", "tool.result", "step_result", "execute.step.start"} + if ev.get("type") + in {"tool.call", "tool.result", "step_result", "execute.step.start"} ] return tool_events[-limit:] @@ -90,7 +91,9 @@ def _collect_recent(events: List[Dict[str, Any]], limit: int = 5) -> List[Any]: def _summarize(events: List[Dict[str, Any]], hard_facts: Dict[str, Any]) -> str: tool_calls = sum(1 for e in events if e.get("type") == "tool.call") tool_results = sum(1 for e in events if e.get("type") == "tool.result") - steps = sum(1 for e in events if e.get("type") in {"plan.step", "execute.step.start"}) + steps = sum( + 1 for e in events if e.get("type") in {"plan.step", "execute.step.start"} + ) plan_known = bool(hard_facts.get("plan")) return ( f"Steps seen: {steps}; tool calls: {tool_calls}; tool results: {tool_results}; " diff --git a/core/task.py b/core/task.py index 163d15de1..86b7ec75a 100644 --- a/core/task.py +++ b/core/task.py @@ -2,7 +2,6 @@ import asyncio import queue -import threading from dataclasses import dataclass, field from enum import Enum from typing import Any, Optional, Union @@ -60,7 +59,9 @@ def emit(self, type: str, data: Any) -> None: elif isinstance(self.event_queue, queue.Queue): self.event_queue.put_nowait(event) else: - raise TypeError("event_queue must be an asyncio.Queue or queue.Queue instance") + raise TypeError( + "event_queue must be an asyncio.Queue or queue.Queue instance" + ) def interrupt(self) -> None: """Mark task as interrupted.""" diff --git a/core/task_registry.py b/core/task_registry.py index ca97bd593..d1c1f6914 100644 --- a/core/task_registry.py +++ b/core/task_registry.py @@ -19,14 +19,19 @@ class TaskRegistry: def __init__(self, db_url: Optional[str] = None) -> None: self._lock = threading.RLock() self.db_url = db_url or os.getenv( - "DATABASE_URL", "postgresql+psycopg2://postgres:postgres@localhost:5432/openmanus" + "DATABASE_URL", + "postgresql+psycopg2://postgres:postgres@localhost:5432/openmanus", ) self.engine = create_engine(self.db_url) Base.metadata.create_all(self.engine) self.SessionLocal = sessionmaker(bind=self.engine, expire_on_commit=False) def _to_task(self, orm: TaskORM) -> Task: - status = TaskStatus(orm.status) if orm.status in TaskStatus._value2member_map_ else TaskStatus.CREATED + status = ( + TaskStatus(orm.status) + if orm.status in TaskStatus._value2member_map_ + else TaskStatus.CREATED + ) # Use fresh queue per retrieval; events are in-memory only return Task( id=str(orm.task_id), @@ -69,7 +74,11 @@ def update_task(self, task: Task, result: Optional[dict] = None) -> Task: if orm is None: orm = TaskORM(task_id=task.id) session.add(orm) - orm.status = task.status.value if isinstance(task.status, TaskStatus) else str(task.status) + orm.status = ( + task.status.value + if isinstance(task.status, TaskStatus) + else str(task.status) + ) if hasattr(task, "input"): orm.input = getattr(task, "input") orm.result = result if result is not None else orm.result diff --git a/server/api.py b/server/api.py index 9e906428f..226a155f8 100644 --- a/server/api.py +++ b/server/api.py @@ -1,16 +1,16 @@ from typing import Optional import uvicorn -from fastapi import BackgroundTasks, FastAPI, HTTPException +from fastapi import FastAPI, HTTPException -from app.agent.base import TaskInterrupted from app.agent.manus import Manus from core.task import TaskStatus from core.task_registry import TaskRegistry from core.task_runner import run_with_status -from server.tasks import run_task from server.celery_app import celery_app from server.models import TaskORM +from server.tasks import run_task + app = FastAPI(title="OpenManus Task API", version="0.1.0") registry = TaskRegistry() @@ -21,9 +21,11 @@ async def _run_agent(task_id: str, prompt: Optional[str]) -> None: task = registry.get_task(task_id) if not task: return + async def _work(): agent = await Manus.create() await agent.run(task, prompt) + await run_with_status(task, _work()) diff --git a/server/celery_app.py b/server/celery_app.py index 264b5f921..f3fc580a4 100644 --- a/server/celery_app.py +++ b/server/celery_app.py @@ -2,8 +2,11 @@ from celery import Celery + broker_url = os.getenv("CELERY_BROKER_URL", "redis://redis:6379/0") -backend_url = os.getenv("CELERY_RESULT_BACKEND", os.getenv("DATABASE_URL", "redis://redis:6379/0")) +backend_url = os.getenv( + "CELERY_RESULT_BACKEND", os.getenv("DATABASE_URL", "redis://redis:6379/0") +) celery_app = Celery("openmanus", broker=broker_url, backend=backend_url) diff --git a/server/models.py b/server/models.py index 6e9743173..939c93483 100644 --- a/server/models.py +++ b/server/models.py @@ -1,10 +1,10 @@ import uuid -from datetime import datetime from sqlalchemy import Column, DateTime, String, func from sqlalchemy.dialects.postgresql import JSONB, UUID from sqlalchemy.orm import declarative_base + Base = declarative_base() diff --git a/server/tasks.py b/server/tasks.py index 1553222f0..f91ce19b2 100644 --- a/server/tasks.py +++ b/server/tasks.py @@ -2,10 +2,11 @@ from typing import Optional from app.agent.manus import Manus -from core.task import Task, TaskStatus +from core.task import TaskStatus from core.task_registry import TaskRegistry from server.celery_app import celery_app + registry = TaskRegistry() diff --git a/server/ws.py b/server/ws.py index 7ded2b975..c1e7554ce 100644 --- a/server/ws.py +++ b/server/ws.py @@ -7,6 +7,7 @@ from core.task_registry import TaskRegistry + # Reuse registry from REST API if available; fallback to a local registry. try: # pragma: no cover - optional import from server.api import registry as api_registry diff --git a/tools/runner.py b/tools/runner.py index 103b01f1b..435b0749e 100644 --- a/tools/runner.py +++ b/tools/runner.py @@ -1,11 +1,11 @@ import asyncio import io -from contextlib import redirect_stdout, redirect_stderr +from contextlib import redirect_stderr, redirect_stdout from typing import Any, Mapping, Optional from app.agent.base import TaskInterrupted -from core.task import Task from app.tool.base import BaseTool, ToolResult +from core.task import Task class ToolRunner: @@ -48,16 +48,23 @@ async def _invoke(): while True: done, _ = await asyncio.wait( - {tool_task}, timeout=self.check_interval, return_when=asyncio.FIRST_COMPLETED + {tool_task}, + timeout=self.check_interval, + return_when=asyncio.FIRST_COMPLETED, ) if task.is_interrupted(): tool_task.cancel() raise TaskInterrupted() if done: break - if timeout is not None and (asyncio.get_event_loop().time() - start) > timeout: + if ( + timeout is not None + and (asyncio.get_event_loop().time() - start) > timeout + ): tool_task.cancel() - return ToolResult(error=f"Tool '{tool_name}' execution timed out after {timeout} seconds") + return ToolResult( + error=f"Tool '{tool_name}' execution timed out after {timeout} seconds" + ) try: result, stdout_text, stderr_text = await tool_task @@ -75,7 +82,11 @@ async def _invoke(): if isinstance(result, ToolResult): if system_info: - return result.replace(system=system_info if not result.system else f"{result.system}\n{system_info}") + return result.replace( + system=system_info + if not result.system + else f"{result.system}\n{system_info}" + ) return result return ToolResult(output=result, system=system_info) From c3ebfff5e0dd6e0f9f6a0afc3b6d04abd14333da Mon Sep 17 00:00:00 2001 From: MohamedElsaeidy Date: Thu, 14 May 2026 21:31:50 +0300 Subject: [PATCH 22/69] OpenManus v2: conversation-first runtime, persistent sandbox, live observability, and UI overhaul --- README_ja.md | 193 - README_ko.md | 192 - README_zh.md | 198 - frontend/.gitignore | 24 + frontend/.prettierrc | 10 + frontend/components.json | 21 + frontend/eslint.config.js | 23 + frontend/index.html | 14 + frontend/package-lock.json | 7892 +++++++++++++++++ frontend/package.json | 75 + frontend/postcss.config.mjs | 8 + frontend/public/logo.jpg | Bin 0 -> 65677 bytes frontend/src/app.tsx | 96 + .../src/components/block/confirm/index.tsx | 137 + .../src/components/block/markdown/index.tsx | 27 + .../components/features/chat/input/index.tsx | 109 + .../features/chat/messages/index.tsx | 172 + .../features/chat/messages/step/index.tsx | 96 + .../features/chat/messages/tools/index.tsx | 100 + .../features/chat/preview/index.tsx | 40 + .../features/chat/preview/preview-content.tsx | 495 ++ .../chat/preview/preview-description.tsx | 33 + .../components/features/chat/preview/store.ts | 11 + frontend/src/components/ui/alert-dialog.tsx | 86 + frontend/src/components/ui/alert.tsx | 39 + frontend/src/components/ui/avatar.tsx | 26 + frontend/src/components/ui/badge.tsx | 35 + frontend/src/components/ui/button.tsx | 48 + frontend/src/components/ui/card.tsx | 44 + frontend/src/components/ui/checkbox.tsx | 24 + frontend/src/components/ui/dialog.tsx | 74 + frontend/src/components/ui/dropdown-menu.tsx | 189 + frontend/src/components/ui/form.tsx | 115 + frontend/src/components/ui/image.tsx | 17 + frontend/src/components/ui/input.tsx | 21 + frontend/src/components/ui/label.tsx | 19 + frontend/src/components/ui/link.tsx | 17 + .../src/components/ui/navigation-menu.tsx | 123 + frontend/src/components/ui/popover.tsx | 35 + frontend/src/components/ui/select.tsx | 139 + frontend/src/components/ui/separator.tsx | 21 + frontend/src/components/ui/sheet.tsx | 87 + frontend/src/components/ui/sidebar.tsx | 597 ++ frontend/src/components/ui/skeleton.tsx | 7 + frontend/src/components/ui/slider.tsx | 47 + frontend/src/components/ui/sonner.tsx | 27 + frontend/src/components/ui/tabs.tsx | 37 + frontend/src/components/ui/textarea.tsx | 18 + frontend/src/components/ui/tooltip.tsx | 41 + frontend/src/hooks/use-async.ts | 124 + frontend/src/hooks/use-auto-scroll.ts | 43 + frontend/src/hooks/use-mobile.ts | 19 + frontend/src/hooks/use-tasks.ts | 10 + frontend/src/hooks/use-theme.ts | 53 + frontend/src/hooks/use-tools.ts | 103 + frontend/src/libs/auth.ts | 51 + frontend/src/libs/chat-messages/index.ts | 205 + frontend/src/libs/chat-messages/types.d.ts | 80 + frontend/src/libs/cookies.ts | 54 + frontend/src/libs/crypto.ts | 135 + frontend/src/libs/image.ts | 33 + frontend/src/libs/language.ts | 19 + frontend/src/libs/maskdata.ts | 14 + frontend/src/libs/password.ts | 11 + frontend/src/libs/prisma.ts | 9 + frontend/src/libs/to.ts | 27 + frontend/src/libs/tools.ts | 20 + frontend/src/libs/utils.ts | 38 + frontend/src/main.tsx | 15 + frontend/src/pages/HomePage.tsx | 61 + frontend/src/pages/TaskDetailPage.tsx | 209 + frontend/src/services/index.ts | 9 + frontend/src/services/tasks.ts | 109 + frontend/src/styles/animations.css | 85 + frontend/src/styles/globals.css | 139 + frontend/src/vite-env.d.ts | 12 + frontend/tsconfig.app.json | 32 + frontend/tsconfig.json | 15 + frontend/tsconfig.node.json | 24 + frontend/vite.config.ts | 21 + 80 files changed, 13095 insertions(+), 583 deletions(-) delete mode 100644 README_ja.md delete mode 100644 README_ko.md delete mode 100644 README_zh.md create mode 100644 frontend/.gitignore create mode 100644 frontend/.prettierrc create mode 100644 frontend/components.json create mode 100644 frontend/eslint.config.js create mode 100644 frontend/index.html create mode 100644 frontend/package-lock.json create mode 100644 frontend/package.json create mode 100644 frontend/postcss.config.mjs create mode 100644 frontend/public/logo.jpg create mode 100644 frontend/src/app.tsx create mode 100644 frontend/src/components/block/confirm/index.tsx create mode 100644 frontend/src/components/block/markdown/index.tsx create mode 100644 frontend/src/components/features/chat/input/index.tsx create mode 100644 frontend/src/components/features/chat/messages/index.tsx create mode 100644 frontend/src/components/features/chat/messages/step/index.tsx create mode 100644 frontend/src/components/features/chat/messages/tools/index.tsx create mode 100644 frontend/src/components/features/chat/preview/index.tsx create mode 100644 frontend/src/components/features/chat/preview/preview-content.tsx create mode 100644 frontend/src/components/features/chat/preview/preview-description.tsx create mode 100644 frontend/src/components/features/chat/preview/store.ts create mode 100644 frontend/src/components/ui/alert-dialog.tsx create mode 100644 frontend/src/components/ui/alert.tsx create mode 100644 frontend/src/components/ui/avatar.tsx create mode 100644 frontend/src/components/ui/badge.tsx create mode 100644 frontend/src/components/ui/button.tsx create mode 100644 frontend/src/components/ui/card.tsx create mode 100644 frontend/src/components/ui/checkbox.tsx create mode 100644 frontend/src/components/ui/dialog.tsx create mode 100644 frontend/src/components/ui/dropdown-menu.tsx create mode 100644 frontend/src/components/ui/form.tsx create mode 100644 frontend/src/components/ui/image.tsx create mode 100644 frontend/src/components/ui/input.tsx create mode 100644 frontend/src/components/ui/label.tsx create mode 100644 frontend/src/components/ui/link.tsx create mode 100644 frontend/src/components/ui/navigation-menu.tsx create mode 100644 frontend/src/components/ui/popover.tsx create mode 100644 frontend/src/components/ui/select.tsx create mode 100644 frontend/src/components/ui/separator.tsx create mode 100644 frontend/src/components/ui/sheet.tsx create mode 100644 frontend/src/components/ui/sidebar.tsx create mode 100644 frontend/src/components/ui/skeleton.tsx create mode 100644 frontend/src/components/ui/slider.tsx create mode 100644 frontend/src/components/ui/sonner.tsx create mode 100644 frontend/src/components/ui/tabs.tsx create mode 100644 frontend/src/components/ui/textarea.tsx create mode 100644 frontend/src/components/ui/tooltip.tsx create mode 100644 frontend/src/hooks/use-async.ts create mode 100644 frontend/src/hooks/use-auto-scroll.ts create mode 100644 frontend/src/hooks/use-mobile.ts create mode 100644 frontend/src/hooks/use-tasks.ts create mode 100644 frontend/src/hooks/use-theme.ts create mode 100644 frontend/src/hooks/use-tools.ts create mode 100644 frontend/src/libs/auth.ts create mode 100644 frontend/src/libs/chat-messages/index.ts create mode 100644 frontend/src/libs/chat-messages/types.d.ts create mode 100644 frontend/src/libs/cookies.ts create mode 100644 frontend/src/libs/crypto.ts create mode 100644 frontend/src/libs/image.ts create mode 100644 frontend/src/libs/language.ts create mode 100644 frontend/src/libs/maskdata.ts create mode 100644 frontend/src/libs/password.ts create mode 100644 frontend/src/libs/prisma.ts create mode 100644 frontend/src/libs/to.ts create mode 100644 frontend/src/libs/tools.ts create mode 100644 frontend/src/libs/utils.ts create mode 100644 frontend/src/main.tsx create mode 100644 frontend/src/pages/HomePage.tsx create mode 100644 frontend/src/pages/TaskDetailPage.tsx create mode 100644 frontend/src/services/index.ts create mode 100644 frontend/src/services/tasks.ts create mode 100644 frontend/src/styles/animations.css create mode 100644 frontend/src/styles/globals.css create mode 100644 frontend/src/vite-env.d.ts create mode 100644 frontend/tsconfig.app.json create mode 100644 frontend/tsconfig.json create mode 100644 frontend/tsconfig.node.json create mode 100644 frontend/vite.config.ts diff --git a/README_ja.md b/README_ja.md deleted file mode 100644 index d5fd281e5..000000000 --- a/README_ja.md +++ /dev/null @@ -1,193 +0,0 @@ -

- -

- -[English](README.md) | [中文](README_zh.md) | [한국어](README_ko.md) | 日本語 - -[![GitHub stars](https://img.shields.io/github/stars/FoundationAgents/OpenManus?style=social)](https://github.com/FoundationAgents/OpenManus/stargazers) -  -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)   -[![Discord Follow](https://dcbadge.vercel.app/api/server/DYn29wFk9z?style=flat)](https://discord.gg/DYn29wFk9z) -[![Demo](https://img.shields.io/badge/Demo-Hugging%20Face-yellow)](https://huggingface.co/spaces/lyh-917/OpenManusDemo) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.15186407.svg)](https://doi.org/10.5281/zenodo.15186407) - -# 👋 OpenManus - -Manusは素晴らしいですが、OpenManusは*招待コード*なしでどんなアイデアも実現できます!🛫 - -私たちのチームメンバー [@Xinbin Liang](https://github.com/mannaandpoem) と [@Jinyu Xiang](https://github.com/XiangJinyu)(主要開発者)、そして [@Zhaoyang Yu](https://github.com/MoshiQAQ)、[@Jiayi Zhang](https://github.com/didiforgithub)、[@Sirui Hong](https://github.com/stellaHSR) は [@MetaGPT](https://github.com/geekan/MetaGPT) から来ました。プロトタイプは3時間以内に立ち上げられ、継続的に開発を進めています! - -これはシンプルな実装ですので、どんな提案、貢献、フィードバックも歓迎します! - -OpenManusで自分だけのエージェントを楽しみましょう! - -また、UIUCとOpenManusの研究者が共同開発した[OpenManus-RL](https://github.com/OpenManus/OpenManus-RL)をご紹介できることを嬉しく思います。これは強化学習(RL)ベース(GRPOなど)のLLMエージェントチューニング手法に特化したオープンソースプロジェクトです。 - -## プロジェクトデモ - - - -## インストール方法 - -インストール方法は2つ提供しています。方法2(uvを使用)は、より高速なインストールと優れた依存関係管理のため推奨されています。 - -### 方法1:condaを使用 - -1. 新しいconda環境を作成します: - -```bash -conda create -n open_manus python=3.12 -conda activate open_manus -``` - -2. リポジトリをクローンします: - -```bash -git clone https://github.com/FoundationAgents/OpenManus.git -cd OpenManus -``` - -3. 依存関係をインストールします: - -```bash -pip install -r requirements.txt -``` - -### 方法2:uvを使用(推奨) - -1. uv(高速なPythonパッケージインストーラーと管理機能)をインストールします: - -```bash -curl -LsSf https://astral.sh/uv/install.sh | sh -``` - -2. リポジトリをクローンします: - -```bash -git clone https://github.com/FoundationAgents/OpenManus.git -cd OpenManus -``` - -3. 新しい仮想環境を作成してアクティベートします: - -```bash -uv venv --python 3.12 -source .venv/bin/activate # Unix/macOSの場合 -# Windowsの場合: -# .venv\Scripts\activate -``` - -4. 依存関係をインストールします: - -```bash -uv pip install -r requirements.txt -``` - -### ブラウザ自動化ツール(オプション) -```bash -playwright install -``` - -## 設定 - -OpenManusを使用するには、LLM APIの設定が必要です。以下の手順に従って設定してください: - -1. `config`ディレクトリに`config.toml`ファイルを作成します(サンプルからコピーできます): - -```bash -cp config/config.example.toml config/config.toml -``` - -2. `config/config.toml`を編集してAPIキーを追加し、設定をカスタマイズします: - -```toml -# グローバルLLM設定 -[llm] -model = "gpt-4o" -base_url = "https://api.openai.com/v1" -api_key = "sk-..." # 実際のAPIキーに置き換えてください -max_tokens = 4096 -temperature = 0.0 - -# 特定のLLMモデル用のオプション設定 -[llm.vision] -model = "gpt-4o" -base_url = "https://api.openai.com/v1" -api_key = "sk-..." # 実際のAPIキーに置き換えてください -``` - -## クイックスタート - -OpenManusを実行する一行コマンド: - -```bash -python main.py -``` - -その後、ターミナルからプロンプトを入力してください! - -MCP ツールバージョンを使用する場合は、以下を実行します: -```bash -python run_mcp.py -``` - -開発中のマルチエージェントバージョンを試すには、以下を実行します: - -```bash -python run_flow.py -``` - -## カスタムマルチエージェントの追加 - -現在、一般的なOpenManusエージェントに加えて、データ分析とデータ可視化タスクに適したDataAnalysisエージェントが組み込まれています。このエージェントを`config.toml`の`run_flow`に追加することができます。 - -```toml -# run-flowのオプション設定 -[runflow] -use_data_analysis_agent = true # デフォルトでは無効、trueに変更すると有効化されます -``` - -これに加えて、エージェントが正常に動作するために必要な依存関係をインストールする必要があります:[具体的なインストールガイド](app/tool/chart_visualization/README_ja.md##インストール) - - -## 貢献方法 - -我々は建設的な意見や有益な貢献を歓迎します!issueを作成するか、プルリクエストを提出してください。 - -または @mannaandpoem に📧メールでご連絡ください:mannaandpoem@gmail.com - -**注意**: プルリクエストを送信する前に、pre-commitツールを使用して変更を確認してください。`pre-commit run --all-files`を実行してチェックを実行します。 - -## コミュニティグループ -Feishuのネットワーキンググループに参加して、他の開発者と経験を共有しましょう! - -
- OpenManus 交流群 -
- -## スター履歴 - -[![Star History Chart](https://api.star-history.com/svg?repos=FoundationAgents/OpenManus&type=Date)](https://star-history.com/#FoundationAgents/OpenManus&Date) - -## 謝辞 - -このプロジェクトの基本的なサポートを提供してくれた[anthropic-computer-use](https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo) -と[browser-use](https://github.com/browser-use/browser-use)に感謝します! - -さらに、[AAAJ](https://github.com/metauto-ai/agent-as-a-judge)、[MetaGPT](https://github.com/geekan/MetaGPT)、[OpenHands](https://github.com/All-Hands-AI/OpenHands)、[SWE-agent](https://github.com/SWE-agent/SWE-agent)にも感謝します。 - -また、Hugging Face デモスペースをサポートしてくださった阶跃星辰 (stepfun)にも感謝いたします。 - -OpenManusはMetaGPTのコントリビューターによって構築されました。このエージェントコミュニティに大きな感謝を! - -## 引用 -```bibtex -@misc{openmanus2025, - author = {Xinbin Liang and Jinyu Xiang and Zhaoyang Yu and Jiayi Zhang and Sirui Hong and Sheng Fan and Xiao Tang}, - title = {OpenManus: An open-source framework for building general AI agents}, - year = {2025}, - publisher = {Zenodo}, - doi = {10.5281/zenodo.15186407}, - url = {https://doi.org/10.5281/zenodo.15186407}, -} -``` diff --git a/README_ko.md b/README_ko.md deleted file mode 100644 index 5080f43e7..000000000 --- a/README_ko.md +++ /dev/null @@ -1,192 +0,0 @@ -

- -

- -[English](README.md) | [中文](README_zh.md) | 한국어 | [日本語](README_ja.md) - -[![GitHub stars](https://img.shields.io/github/stars/FoundationAgents/OpenManus?style=social)](https://github.com/FoundationAgents/OpenManus/stargazers) -  -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)   -[![Discord Follow](https://dcbadge.vercel.app/api/server/DYn29wFk9z?style=flat)](https://discord.gg/DYn29wFk9z) -[![Demo](https://img.shields.io/badge/Demo-Hugging%20Face-yellow)](https://huggingface.co/spaces/lyh-917/OpenManusDemo) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.15186407.svg)](https://doi.org/10.5281/zenodo.15186407) - -# 👋 OpenManus - -Manus는 놀라운 도구지만, OpenManus는 *초대 코드* 없이도 모든 아이디어를 실현할 수 있습니다! 🛫 - -우리 팀의 멤버인 [@Xinbin Liang](https://github.com/mannaandpoem)와 [@Jinyu Xiang](https://github.com/XiangJinyu) (핵심 작성자), 그리고 [@Zhaoyang Yu](https://github.com/MoshiQAQ), [@Jiayi Zhang](https://github.com/didiforgithub), [@Sirui Hong](https://github.com/stellaHSR)이 함께 했습니다. 우리는 [@MetaGPT](https://github.com/geekan/MetaGPT)로부터 왔습니다. 프로토타입은 단 3시간 만에 출시되었으며, 계속해서 발전하고 있습니다! - -이 프로젝트는 간단한 구현에서 시작되었으며, 여러분의 제안, 기여 및 피드백을 환영합니다! - -OpenManus를 통해 여러분만의 에이전트를 즐겨보세요! - -또한 [OpenManus-RL](https://github.com/OpenManus/OpenManus-RL)을 소개하게 되어 기쁩니다. OpenManus와 UIUC 연구자들이 공동 개발한 이 오픈소스 프로젝트는 LLM 에이전트에 대해 강화 학습(RL) 기반 (예: GRPO) 튜닝 방법을 제공합니다. - -## 프로젝트 데모 - - - -## 설치 방법 - -두 가지 설치 방법을 제공합니다. **방법 2 (uv 사용)** 이 더 빠른 설치와 효율적인 종속성 관리를 위해 권장됩니다. - -### 방법 1: conda 사용 - -1. 새로운 conda 환경을 생성합니다: - -```bash -conda create -n open_manus python=3.12 -conda activate open_manus -``` - -2. 저장소를 클론합니다: - -```bash -git clone https://github.com/FoundationAgents/OpenManus.git -cd OpenManus -``` - -3. 종속성을 설치합니다: - -```bash -pip install -r requirements.txt -``` - -### 방법 2: uv 사용 (권장) - -1. uv를 설치합니다. (빠른 Python 패키지 설치 및 종속성 관리 도구): - -```bash -curl -LsSf https://astral.sh/uv/install.sh | sh -``` - -2. 저장소를 클론합니다: - -```bash -git clone https://github.com/FoundationAgents/OpenManus.git -cd OpenManus -``` - -3. 새로운 가상 환경을 생성하고 활성화합니다: - -```bash -uv venv --python 3.12 -source .venv/bin/activate # Unix/macOS의 경우 -# Windows의 경우: -# .venv\Scripts\activate -``` - -4. 종속성을 설치합니다: - -```bash -uv pip install -r requirements.txt -``` - -### 브라우저 자동화 도구 (선택사항) -```bash -playwright install -``` - -## 설정 방법 - -OpenManus를 사용하려면 사용하는 LLM API에 대한 설정이 필요합니다. 아래 단계를 따라 설정을 완료하세요: - -1. `config` 디렉토리에 `config.toml` 파일을 생성하세요 (예제 파일을 복사하여 사용할 수 있습니다): - -```bash -cp config/config.example.toml config/config.toml -``` - -2. `config/config.toml` 파일을 편집하여 API 키를 추가하고 설정을 커스터마이징하세요: - -```toml -# 전역 LLM 설정 -[llm] -model = "gpt-4o" -base_url = "https://api.openai.com/v1" -api_key = "sk-..." # 실제 API 키로 변경하세요 -max_tokens = 4096 -temperature = 0.0 - -# 특정 LLM 모델에 대한 선택적 설정 -[llm.vision] -model = "gpt-4o" -base_url = "https://api.openai.com/v1" -api_key = "sk-..." # 실제 API 키로 변경하세요 -``` - -## 빠른 시작 - -OpenManus를 실행하는 한 줄 명령어: - -```bash -python main.py -``` - -이후 터미널에서 아이디어를 작성하세요! - -MCP 도구 버전을 사용하려면 다음을 실행하세요: -```bash -python run_mcp.py -``` - -불안정한 멀티 에이전트 버전을 실행하려면 다음을 실행할 수 있습니다: - -```bash -python run_flow.py -``` - -### 사용자 정의 다중 에이전트 추가 - -현재 일반 OpenManus 에이전트 외에도 데이터 분석 및 데이터 시각화 작업에 적합한 DataAnalysis 에이전트를 통합했습니다. 이 에이전트를 `config.toml`의 `run_flow`에 추가할 수 있습니다. - -```toml -# run-flow에 대한 선택적 구성 -[runflow] -use_data_analysis_agent = true # 기본적으로 비활성화되어 있으며, 활성화하려면 true로 변경 -``` - -또한, 에이전트가 제대로 작동하도록 관련 종속성을 설치해야 합니다: [상세 설치 가이드](app/tool/chart_visualization/README.md##Installation) - -## 기여 방법 - -모든 친절한 제안과 유용한 기여를 환영합니다! 이슈를 생성하거나 풀 리퀘스트를 제출해 주세요. - -또는 📧 메일로 연락주세요. @mannaandpoem : mannaandpoem@gmail.com - -**참고**: pull request를 제출하기 전에 pre-commit 도구를 사용하여 변경 사항을 확인하십시오. `pre-commit run --all-files`를 실행하여 검사를 실행합니다. - -## 커뮤니티 그룹 -Feishu 네트워킹 그룹에 참여하여 다른 개발자들과 경험을 공유하세요! - -
- OpenManus 交流群 -
- -## Star History - -[![Star History Chart](https://api.star-history.com/svg?repos=FoundationAgents/OpenManus&type=Date)](https://star-history.com/#FoundationAgents/OpenManus&Date) - -## 감사의 글 - -이 프로젝트에 기본적인 지원을 제공해 주신 [anthropic-computer-use](https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo)와 -[browser-use](https://github.com/browser-use/browser-use)에게 감사드립니다! - -또한, [AAAJ](https://github.com/metauto-ai/agent-as-a-judge), [MetaGPT](https://github.com/geekan/MetaGPT), [OpenHands](https://github.com/All-Hands-AI/OpenHands), [SWE-agent](https://github.com/SWE-agent/SWE-agent)에 깊은 감사를 드립니다. - -또한 Hugging Face 데모 공간을 지원해 주신 阶跃星辰 (stepfun)에게 감사드립니다. - -OpenManus는 MetaGPT 기여자들에 의해 개발되었습니다. 이 에이전트 커뮤니티에 깊은 감사를 전합니다! - -## 인용 -```bibtex -@misc{openmanus2025, - author = {Xinbin Liang and Jinyu Xiang and Zhaoyang Yu and Jiayi Zhang and Sirui Hong and Sheng Fan and Xiao Tang}, - title = {OpenManus: An open-source framework for building general AI agents}, - year = {2025}, - publisher = {Zenodo}, - doi = {10.5281/zenodo.15186407}, - url = {https://doi.org/10.5281/zenodo.15186407}, -} -``` diff --git a/README_zh.md b/README_zh.md deleted file mode 100644 index 680ccc1d9..000000000 --- a/README_zh.md +++ /dev/null @@ -1,198 +0,0 @@ -

- -

- -[English](README.md) | 中文 | [한국어](README_ko.md) | [日本語](README_ja.md) - -[![GitHub stars](https://img.shields.io/github/stars/FoundationAgents/OpenManus?style=social)](https://github.com/FoundationAgents/OpenManus/stargazers) -  -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)   -[![Discord Follow](https://dcbadge.vercel.app/api/server/DYn29wFk9z?style=flat)](https://discord.gg/DYn29wFk9z) -[![Demo](https://img.shields.io/badge/Demo-Hugging%20Face-yellow)](https://huggingface.co/spaces/lyh-917/OpenManusDemo) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.15186407.svg)](https://doi.org/10.5281/zenodo.15186407) - -# 👋 OpenManus - -Manus 非常棒,但 OpenManus 无需邀请码即可实现任何创意 🛫! - -我们的团队成员 [@Xinbin Liang](https://github.com/mannaandpoem) 和 [@Jinyu Xiang](https://github.com/XiangJinyu)(核心作者),以及 [@Zhaoyang Yu](https://github.com/MoshiQAQ)、[@Jiayi Zhang](https://github.com/didiforgithub) 和 [@Sirui Hong](https://github.com/stellaHSR),来自 [@MetaGPT](https://github.com/geekan/MetaGPT)团队。我们在 3 -小时内完成了开发并持续迭代中! - -这是一个简洁的实现方案,欢迎任何建议、贡献和反馈! - -用 OpenManus 开启你的智能体之旅吧! - -我们也非常高兴地向大家介绍 [OpenManus-RL](https://github.com/OpenManus/OpenManus-RL),这是一个专注于基于强化学习(RL,例如 GRPO)的方法来优化大语言模型(LLM)智能体的开源项目,由来自UIUC 和 OpenManus 的研究人员合作开发。 - -## 项目演示 - - - -## 安装指南 - -我们提供两种安装方式。推荐使用方式二(uv),因为它能提供更快的安装速度和更好的依赖管理。 - -### 方式一:使用 conda - -1. 创建新的 conda 环境: - -```bash -conda create -n open_manus python=3.12 -conda activate open_manus -``` - -2. 克隆仓库: - -```bash -git clone https://github.com/FoundationAgents/OpenManus.git -cd OpenManus -``` - -3. 安装依赖: - -```bash -pip install -r requirements.txt -``` - -### 方式二:使用 uv(推荐) - -1. 安装 uv(一个快速的 Python 包管理器): - -```bash -curl -LsSf https://astral.sh/uv/install.sh | sh -``` - -2. 克隆仓库: - -```bash -git clone https://github.com/FoundationAgents/OpenManus.git -cd OpenManus -``` - -3. 创建并激活虚拟环境: - -```bash -uv venv --python 3.12 -source .venv/bin/activate # Unix/macOS 系统 -# Windows 系统使用: -# .venv\Scripts\activate -``` - -4. 安装依赖: - -```bash -uv pip install -r requirements.txt -``` - -### 浏览器自动化工具(可选) -```bash -playwright install -``` - -## 配置说明 - -OpenManus 需要配置使用的 LLM API,请按以下步骤设置: - -1. 在 `config` 目录创建 `config.toml` 文件(可从示例复制): - -```bash -cp config/config.example.toml config/config.toml -``` - -2. 编辑 `config/config.toml` 添加 API 密钥和自定义设置: - -```toml -# 全局 LLM 配置 -[llm] -model = "gpt-4o" -base_url = "https://api.openai.com/v1" -api_key = "sk-..." # 替换为真实 API 密钥 -max_tokens = 4096 -temperature = 0.0 - -# 可选特定 LLM 模型配置 -[llm.vision] -model = "gpt-4o" -base_url = "https://api.openai.com/v1" -api_key = "sk-..." # 替换为真实 API 密钥 -``` - -## 快速启动 - -一行命令运行 OpenManus: - -```bash -python main.py -``` - -然后通过终端输入你的创意! - -如需使用 MCP 工具版本,可运行: -```bash -python run_mcp.py -``` - -如需体验不稳定的多智能体版本,可运行: - -```bash -python run_flow.py -``` - -## 添加自定义多智能体 - -目前除了通用的 OpenManus Agent, 我们还内置了DataAnalysis Agent,适用于数据分析和数据可视化任务,你可以在`config.toml`中将这个智能体加入到`run_flow`中 -```toml -# run-flow可选配置 -[runflow] -use_data_analysis_agent = true # 默认关闭,将其改为true则为激活 -``` -除此之外,你还需要安装相关的依赖来确保智能体正常运行:[具体安装指南](app/tool/chart_visualization/README_zh.md##安装) - - -## 贡献指南 - -我们欢迎任何友好的建议和有价值的贡献!可以直接创建 issue 或提交 pull request。 - -或通过 📧 邮件联系 @mannaandpoem:mannaandpoem@gmail.com - -**注意**: 在提交 pull request 之前,请使用 pre-commit 工具检查您的更改。运行 `pre-commit run --all-files` 来执行检查。 - -## 交流群 - -加入我们的飞书交流群,与其他开发者分享经验! - -
- OpenManus 交流群 -
- -## Star 数量 - -[![Star History Chart](https://api.star-history.com/svg?repos=FoundationAgents/OpenManus&type=Date)](https://star-history.com/#FoundationAgents/OpenManus&Date) - - -## 赞助商 -感谢[PPIO](https://ppinfra.com/user/register?invited_by=OCPKCN&utm_source=github_openmanus&utm_medium=github_readme&utm_campaign=link) 提供的算力支持。 -> PPIO派欧云:一键调用高性价比的开源模型API和GPU容器 - -## 致谢 - -特别感谢 [anthropic-computer-use](https://github.com/anthropics/anthropic-quickstarts/tree/main/computer-use-demo) -和 [browser-use](https://github.com/browser-use/browser-use) 为本项目提供的基础支持! - -此外,我们感谢 [AAAJ](https://github.com/metauto-ai/agent-as-a-judge),[MetaGPT](https://github.com/geekan/MetaGPT),[OpenHands](https://github.com/All-Hands-AI/OpenHands) 和 [SWE-agent](https://github.com/SWE-agent/SWE-agent). - -我们也感谢阶跃星辰 (stepfun) 提供的 Hugging Face 演示空间支持。 - -OpenManus 由 MetaGPT 社区的贡献者共同构建,感谢这个充满活力的智能体开发者社区! - -## 引用 -```bibtex -@misc{openmanus2025, - author = {Xinbin Liang and Jinyu Xiang and Zhaoyang Yu and Jiayi Zhang and Sirui Hong and Sheng Fan and Xiao Tang}, - title = {OpenManus: An open-source framework for building general AI agents}, - year = {2025}, - publisher = {Zenodo}, - doi = {10.5281/zenodo.15186407}, - url = {https://doi.org/10.5281/zenodo.15186407}, -} -``` diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 000000000..a547bf36d --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 000000000..f524b2258 --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,10 @@ +{ + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "printWidth": 150, + "bracketSpacing": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/frontend/components.json b/frontend/components.json new file mode 100644 index 000000000..b9444a489 --- /dev/null +++ b/frontend/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/styles/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/libs/utils", + "ui": "@/components/ui", + "lib": "@/libs", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js new file mode 100644 index 000000000..d94e7deb7 --- /dev/null +++ b/frontend/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { globalIgnores } from 'eslint/config' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 000000000..123a90778 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,14 @@ + + + + + + + OpenManus + + + +
+ + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 000000000..7d8061893 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,7892 @@ +{ + "name": "openmanus-frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "openmanus-frontend", + "version": "0.0.0", + "dependencies": { + "@hookform/resolvers": "^4.1.3", + "@prisma/client": "^6.5.0", + "@radix-ui/react-alert-dialog": "^1.1.6", + "@radix-ui/react-avatar": "^1.1.3", + "@radix-ui/react-checkbox": "^1.1.5", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-label": "^2.1.2", + "@radix-ui/react-navigation-menu": "^1.2.5", + "@radix-ui/react-popover": "^1.1.6", + "@radix-ui/react-select": "^2.1.6", + "@radix-ui/react-separator": "^1.1.2", + "@radix-ui/react-slider": "^1.2.3", + "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-tabs": "^1.1.3", + "@radix-ui/react-tooltip": "^1.1.8", + "@tailwindcss/vite": "^4.1.11", + "@types/node": "^24.0.4", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "github-markdown-css": "^5.8.1", + "jose": "^6.0.10", + "json-schema-to-ts": "^3.1.1", + "lodash": "^4.17.21", + "lucide-react": "^0.483.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-hook-form": "^7.55.0", + "react-markdown": "^10.1.0", + "react-router-dom": "^6.30.1", + "react-syntax-highlighter": "^15.6.1", + "react-use-websocket": "^4.13.0", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "sonner": "^2.0.2", + "tailwind-merge": "^3.3.1", + "zod": "^3.24.2", + "zustand": "^5.0.3" + }, + "devDependencies": { + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.29.0", + "@tailwindcss/postcss": "^4.1.10", + "@tailwindcss/typography": "^0.5.16", + "@types/lodash": "^4.17.18", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@types/react-syntax-highlighter": "^15.5.13", + "@vitejs/plugin-react": "^4.5.2", + "autoprefixer": "^10.4.21", + "eslint": "^9.29.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.2.0", + "prettier": "^3.6.1", + "prettier-plugin-tailwindcss": "^0.6.13", + "tailwindcss": "^4.1.10", + "tw-animate-css": "^1.3.4", + "typescript": "~5.8.3", + "typescript-eslint": "^8.34.1", + "vite": "^7.0.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz", + "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", + "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.4", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.4", + "@babel/types": "^7.27.3", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.5", + "@babel/types": "^7.27.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", + "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", + "integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.29.0.tgz", + "integrity": "sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz", + "integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.0.tgz", + "integrity": "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz", + "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.1.tgz", + "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.1", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.3.tgz", + "integrity": "sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, + "node_modules/@hookform/resolvers": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-4.1.3.tgz", + "integrity": "sha512-Jsv6UOWYTrEFJ/01ZrnwVXs7KDvP8XIo115i++5PWvNkNvkrsTfGiLS6w+eJ57CYtUtDQalUWovCZDHFJ8u1VQ==", + "license": "MIT", + "dependencies": { + "@standard-schema/utils": "^0.3.0" + }, + "peerDependencies": { + "react-hook-form": "^7.0.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@prisma/client": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.10.1.tgz", + "integrity": "sha512-Re4pMlcUsQsUTAYMK7EJ4Bw2kg3WfZAAlr8GjORJaK4VOP6LxRQUQ1TuLnxcF42XqGkWQ36q5CQF1yVadANQ6w==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.14.tgz", + "integrity": "sha512-IOZfZ3nPvN6lXpJTBCunFQPRSvK8MDgSc1FB85xnIpUKOw9en0dJj8JmCAxV7BiZdtYlUpmrQjoTFkVYtdoWzQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.14", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.2.tgz", + "integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz", + "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", + "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz", + "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz", + "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.15.tgz", + "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-navigation-menu": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.13.tgz", + "integrity": "sha512-WG8wWfDiJlSF5hELjwfjSGOXcBR/ZMhBFCGYe8vERpC39CQYZeq1PQ2kaYHdye3V95d06H89KGMsVCIE4LWo3g==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz", + "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz", + "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz", + "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz", + "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.5.tgz", + "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slider": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.5.tgz", + "integrity": "sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.12.tgz", + "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz", + "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.10", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@remix-run/router": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", + "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz", + "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.0.tgz", + "integrity": "sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.0.tgz", + "integrity": "sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.0.tgz", + "integrity": "sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.0.tgz", + "integrity": "sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.0.tgz", + "integrity": "sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.0.tgz", + "integrity": "sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.0.tgz", + "integrity": "sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.0.tgz", + "integrity": "sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.0.tgz", + "integrity": "sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.0.tgz", + "integrity": "sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.0.tgz", + "integrity": "sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.0.tgz", + "integrity": "sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.0.tgz", + "integrity": "sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.0.tgz", + "integrity": "sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.0.tgz", + "integrity": "sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.0.tgz", + "integrity": "sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.0.tgz", + "integrity": "sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.0.tgz", + "integrity": "sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.0.tgz", + "integrity": "sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.0.tgz", + "integrity": "sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.10.tgz", + "integrity": "sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.10" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.10.tgz", + "integrity": "sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.10", + "@tailwindcss/oxide-darwin-arm64": "4.1.10", + "@tailwindcss/oxide-darwin-x64": "4.1.10", + "@tailwindcss/oxide-freebsd-x64": "4.1.10", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.10", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.10", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.10", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.10", + "@tailwindcss/oxide-linux-x64-musl": "4.1.10", + "@tailwindcss/oxide-wasm32-wasi": "4.1.10", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.10", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.10" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.10.tgz", + "integrity": "sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.10.tgz", + "integrity": "sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.10.tgz", + "integrity": "sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.10.tgz", + "integrity": "sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.10.tgz", + "integrity": "sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.10.tgz", + "integrity": "sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.10.tgz", + "integrity": "sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.10.tgz", + "integrity": "sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.10.tgz", + "integrity": "sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.10.tgz", + "integrity": "sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.10", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz", + "integrity": "sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz", + "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.10.tgz", + "integrity": "sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.10", + "@tailwindcss/oxide": "4.1.10", + "postcss": "^8.4.41", + "tailwindcss": "4.1.10" + } + }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", + "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", + "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.11", + "@tailwindcss/oxide": "4.1.11", + "tailwindcss": "4.1.11" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/node": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", + "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.11" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", + "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-x64": "4.1.11", + "@tailwindcss/oxide-freebsd-x64": "4.1.11", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-x64-musl": "4.1.11", + "@tailwindcss/oxide-wasm32-wasi": "4.1.11", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", + "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", + "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", + "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", + "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", + "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", + "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", + "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", + "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", + "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", + "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.11", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", + "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", + "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite/node_modules/tailwindcss": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", + "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.18.tgz", + "integrity": "sha512-KJ65INaxqxmU6EoCiJmRPZC9H9RVWCRd349tXM2M3O5NA7cY6YL7c0bHAHQ93NOfTObEQ004kd2QVHs/r0+m4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.0.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz", + "integrity": "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz", + "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/react-syntax-highlighter": { + "version": "15.5.13", + "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz", + "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz", + "integrity": "sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/type-utils": "8.35.0", + "@typescript-eslint/utils": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.35.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.0.tgz", + "integrity": "sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/typescript-estree": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.0.tgz", + "integrity": "sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.35.0", + "@typescript-eslint/types": "^8.35.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz", + "integrity": "sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz", + "integrity": "sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz", + "integrity": "sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.35.0", + "@typescript-eslint/utils": "8.35.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.0.tgz", + "integrity": "sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz", + "integrity": "sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.35.0", + "@typescript-eslint/tsconfig-utils": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.0.tgz", + "integrity": "sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/typescript-estree": "8.35.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz", + "integrity": "sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.35.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.6.0.tgz", + "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.19", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001724", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001724.tgz", + "integrity": "sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.173", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.173.tgz", + "integrity": "sha512-2bFhXP2zqSfQHugjqJIDFVwa+qIxyNApenmXTp9EjaKtdPrES5Qcn9/aSFy/NaP2E+fWG/zxKu/LBvY36p5VNQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.29.0.tgz", + "integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.20.1", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.14.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.29.0", + "@eslint/plugin-kit": "^0.3.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.20", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", + "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "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.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/github-markdown-css": { + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.8.1.tgz", + "integrity": "sha512-8G+PFvqigBQSWLQjyzgpa2ThD9bo7+kDsriUIidGcRhXgmcaAWUIpCZf8DavJgc+xifjbCG+GvMyWr0XMXmc7g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", + "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "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==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "license": "MIT", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript/node_modules/@types/hast": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/hastscript/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/hastscript/node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hastscript/node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hastscript/node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/highlightjs-vue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz", + "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", + "license": "CC0-1.0" + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jose": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.0.11.tgz", + "integrity": "sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lowlight": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "license": "MIT", + "dependencies": { + "fault": "^1.0.0", + "highlight.js": "~10.7.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.483.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.483.0.tgz", + "integrity": "sha512-WldsY17Qb/T3VZdMnVQ9C3DDIP7h1ViDTHVdVGnLZcvHNg30zH/MTQ04RTORjexoGmpsXroiQXZ4QyR0kBy0FA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.1.tgz", + "integrity": "sha512-5xGWRa90Sp2+x1dQtNpIpeOQpTDBs9cZDmA/qs2vDNN2i18PdapqY7CmBeyLlMuGqXJRIOPaCaVZTLNQRWUH/A==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.13.tgz", + "integrity": "sha512-uQ0asli1+ic8xrrSmIOaElDu0FacR4x69GynTh2oZjFY10JUt6EEumTQl5tB4fMeD6I1naKd+4rXQQ7esT2i1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "@zackad/prettier-plugin-twig": "*", + "prettier": "^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-marko": "*", + "prettier-plugin-multiline-arrays": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-sort-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "@zackad/prettier-plugin-twig": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-marko": { + "optional": true + }, + "prettier-plugin-multiline-arrays": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + } + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/react-hook-form": { + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.58.1.tgz", + "integrity": "sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-router": { + "version": "6.30.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz", + "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz", + "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.0", + "react-router": "6.30.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-syntax-highlighter": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz", + "integrity": "sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.3.1", + "highlight.js": "^10.4.1", + "highlightjs-vue": "^1.0.0", + "lowlight": "^1.17.0", + "prismjs": "^1.27.0", + "refractor": "^3.6.0" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/react-use-websocket": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.13.0.tgz", + "integrity": "sha512-anMuVoV//g2N76Wxqvqjjo1X48r9Np3y1/gMl7arX84tAPXdy5R7sB5lO5hvCzQRYjqXwV8XMAiEBOUbyrZFrw==", + "license": "MIT" + }, + "node_modules/refractor": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", + "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", + "license": "MIT", + "dependencies": { + "hastscript": "^6.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.27.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "license": "MIT", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/prismjs": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", + "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.0.tgz", + "integrity": "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.44.0", + "@rollup/rollup-android-arm64": "4.44.0", + "@rollup/rollup-darwin-arm64": "4.44.0", + "@rollup/rollup-darwin-x64": "4.44.0", + "@rollup/rollup-freebsd-arm64": "4.44.0", + "@rollup/rollup-freebsd-x64": "4.44.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.0", + "@rollup/rollup-linux-arm-musleabihf": "4.44.0", + "@rollup/rollup-linux-arm64-gnu": "4.44.0", + "@rollup/rollup-linux-arm64-musl": "4.44.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.0", + "@rollup/rollup-linux-riscv64-gnu": "4.44.0", + "@rollup/rollup-linux-riscv64-musl": "4.44.0", + "@rollup/rollup-linux-s390x-gnu": "4.44.0", + "@rollup/rollup-linux-x64-gnu": "4.44.0", + "@rollup/rollup-linux-x64-musl": "4.44.0", + "@rollup/rollup-win32-arm64-msvc": "4.44.0", + "@rollup/rollup-win32-ia32-msvc": "4.44.0", + "@rollup/rollup-win32-x64-msvc": "4.44.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/sonner": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.5.tgz", + "integrity": "sha512-YwbHQO6cSso3HBXlbCkgrgzDNIhws14r4MO87Ofy+cV2X7ES4pOoAK3+veSmVTvqNx1BWUxlhPmZzP00Crk2aQ==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-js": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", + "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.9" + } + }, + "node_modules/style-to-object": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", + "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tailwind-merge": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", + "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz", + "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT" + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tw-animate-css": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.4.tgz", + "integrity": "sha512-dd1Ht6/YQHcNbq0znIT6dG8uhO7Ce+VIIhZUhjsryXsMPJQz3bZg7Q2eNzLwipb25bRZslGb2myio5mScd1TFg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Wombosvideo" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.35.0.tgz", + "integrity": "sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.35.0", + "@typescript-eslint/parser": "8.35.0", + "@typescript-eslint/utils": "8.35.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.0.tgz", + "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.6", + "picomatch": "^4.0.2", + "postcss": "^8.5.6", + "rollup": "^4.40.0", + "tinyglobby": "^0.2.14" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zustand": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.5.tgz", + "integrity": "sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 000000000..6cf2597af --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,75 @@ +{ + "name": "openmanus-frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@hookform/resolvers": "^4.1.3", + "@prisma/client": "^6.5.0", + "@radix-ui/react-alert-dialog": "^1.1.6", + "@radix-ui/react-avatar": "^1.1.3", + "@radix-ui/react-checkbox": "^1.1.5", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-label": "^2.1.2", + "@radix-ui/react-navigation-menu": "^1.2.5", + "@radix-ui/react-popover": "^1.1.6", + "@radix-ui/react-select": "^2.1.6", + "@radix-ui/react-separator": "^1.1.2", + "@radix-ui/react-slider": "^1.2.3", + "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-tabs": "^1.1.3", + "@radix-ui/react-tooltip": "^1.1.8", + "@tailwindcss/vite": "^4.1.11", + "@types/node": "^24.0.4", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "github-markdown-css": "^5.8.1", + "jose": "^6.0.10", + "json-schema-to-ts": "^3.1.1", + "lodash": "^4.17.21", + "lucide-react": "^0.483.0", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-hook-form": "^7.55.0", + "react-markdown": "^10.1.0", + "react-router-dom": "^6.30.1", + "react-syntax-highlighter": "^15.6.1", + "react-use-websocket": "^4.13.0", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "sonner": "^2.0.2", + "tailwind-merge": "^3.3.1", + "zod": "^3.24.2", + "zustand": "^5.0.3" + }, + "devDependencies": { + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.29.0", + "@tailwindcss/postcss": "^4.1.10", + "@tailwindcss/typography": "^0.5.16", + "@types/lodash": "^4.17.18", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@types/react-syntax-highlighter": "^15.5.13", + "@vitejs/plugin-react": "^4.5.2", + "autoprefixer": "^10.4.21", + "eslint": "^9.29.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.2.0", + "prettier": "^3.6.1", + "prettier-plugin-tailwindcss": "^0.6.13", + "tailwindcss": "^4.1.10", + "tw-animate-css": "^1.3.4", + "typescript": "~5.8.3", + "typescript-eslint": "^8.34.1", + "vite": "^7.0.0" + } +} diff --git a/frontend/postcss.config.mjs b/frontend/postcss.config.mjs new file mode 100644 index 000000000..6a83185b6 --- /dev/null +++ b/frontend/postcss.config.mjs @@ -0,0 +1,8 @@ +const config = { + plugins: { + '@tailwindcss/postcss': {}, + autoprefixer: {}, + }, +}; + +export default config; diff --git a/frontend/public/logo.jpg b/frontend/public/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..634b8f6851a075182ad04a04c5f4afec33a90e83 GIT binary patch literal 65677 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%0A2>(^-Vpx>3)QTwM! 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 ZNK%&X1&gfzH(uZ1WBLE}(wJ{U{{bAq0IC20 literal 0 HcmV?d00001 diff --git a/frontend/src/app.tsx b/frontend/src/app.tsx new file mode 100644 index 000000000..0d16edae3 --- /dev/null +++ b/frontend/src/app.tsx @@ -0,0 +1,96 @@ +import { ConfirmDialog } from '@/components/block/confirm'; +import { + Sidebar, + SidebarContent, + SidebarGroup, + SidebarGroupContent, + SidebarGroupLabel, + SidebarHeader, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, +} from '@/components/ui/sidebar'; +import { Home, List } from 'lucide-react'; +import { useEffect } from 'react'; +import { Link, Route, Routes, useLocation } from 'react-router-dom'; +import { SidebarProvider } from './components/ui/sidebar'; +import { useRecentTasks } from './hooks/use-tasks'; +import { cn } from './libs/utils'; +import HomePage from './pages/HomePage'; +import TaskDetailPage from './pages/TaskDetailPage'; + +const router = [ + { + path: '/', + label: 'Home', + icon: , + element: , + }, + { + path: '/tasks/:taskId', + label: 'Task Detail', + icon: , + element: , + }, +]; + +function App() { + const { tasks, refreshTasks } = useRecentTasks(); + const location = useLocation(); + + const currentTaskId = location.pathname.split('/').pop(); + + useEffect(() => { + refreshTasks(); + }, []); + + return ( + +
+ + +
+
+ OpenManus +
+ + + GitHub + + + +
+
+ + + Recent Tasks + + + {tasks.map(item => ( + + + + {item.request} + + + + ))} + + + + +
+
+ + {router.map(item => ( + + ))} + +
+ +
+
+ ); +} + +export default App; diff --git a/frontend/src/components/block/confirm/index.tsx b/frontend/src/components/block/confirm/index.tsx new file mode 100644 index 000000000..42007d43c --- /dev/null +++ b/frontend/src/components/block/confirm/index.tsx @@ -0,0 +1,137 @@ +import React, { useState } from 'react'; +import { create } from 'zustand'; +import { devtools } from 'zustand/middleware'; +import type { FieldValues, UseFormReturn } from 'react-hook-form'; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { cn } from '@/libs/utils'; +import { Button } from '@/components/ui/button'; + +interface ConfirmDialogStore { + open: boolean; + content: React.ReactNode; + className?: string; + buttonText?: { cancel?: string; confirm?: string; loading?: string }; + operations?: (props: { setOpen: (value: boolean) => void }) => React.ReactNode[]; + onConfirm?: () => void | Promise; + setOpen: (value: boolean) => void; + setContent: (content: React.ReactNode) => void; + setOnConfirm: (onConfirm?: () => void) => void; + setButtonText: (buttonText?: { cancel?: string; confirm?: string; loading?: string }) => void; + setOperations: (operations?: (props: { setOpen: (value: boolean) => void }) => React.ReactNode[]) => void; + setClassName: (className?: string) => void; +} + +const useConfirmDialogStore = create()( + devtools(set => ({ + open: false, + content: null, + className: undefined, + buttonText: { cancel: 'Cancel', confirm: 'Confirm', loading: 'Processing' }, + operations: () => [], + onConfirm: undefined, + setOpen: (value: boolean) => set({ open: value }), + setContent: content => set({ content }), + setOnConfirm: onConfirm => set({ onConfirm }), + setButtonText: buttonText => set({ buttonText }), + setOperations: operations => set({ operations }), + setClassName: className => set({ className }), + })), +); + +const ConfirmDialog = () => { + const { open, content, buttonText, operations, onConfirm, setOpen, className } = useConfirmDialogStore(); + const [isSubmitting, setIsSubmitting] = useState(false); + + const handleConfirm = async () => { + setIsSubmitting(true); + try { + await onConfirm?.(); + } finally { + setIsSubmitting(false); + setOpen(false); + } + }; + return ( + !isSubmitting && setOpen(value)}> + + + + +
{content}
+ + {operations ? ( + operations({ setOpen }) + ) : ( + <> + + {buttonText?.confirm && ( + + )} + + )} + +
+
+ ); +}; + +ConfirmDialog.displayName = 'ConfirmDialog'; + +function confirm(props: { + content: React.ReactNode | ((props: { form?: UseFormReturn }) => React.ReactNode); + className?: string; + buttonText?: { cancel?: string; confirm?: string; loading?: string }; + operations?: (props: { setOpen: (value: boolean) => void }) => React.ReactNode[]; + onConfirm?: (formData?: F) => R | Promise; + form?: UseFormReturn; +}) { + const { setOpen, setContent, setOnConfirm, setButtonText, setOperations, setClassName } = useConfirmDialogStore.getState(); + + const wrappedOnConfirm = async () => { + if (props.form) { + const formData = props.form.getValues(); + await props.onConfirm?.(formData); + } else { + await props.onConfirm?.(); + } + }; + + setContent(typeof props.content === 'function' ? props.content({ form: props.form }) : props.content); + setOnConfirm(wrappedOnConfirm); + setOperations(props.operations); + setButtonText(props.buttonText); + setClassName(props.className); + setOpen(true); +} + +export async function asyncConfirm(props: { + content: React.ReactNode | ((props: { form?: UseFormReturn }) => React.ReactNode); + buttonText?: { cancel?: string; confirm?: string }; + operations?: (props: { setOpen: (value: boolean) => void }) => React.ReactNode[]; + onConfirm?: (formData?: F) => R | Promise; + form?: UseFormReturn; +}) { + const promise = new Promise(resolve => { + confirm({ + content: props.content, + buttonText: props.buttonText, + operations: props.operations, + form: props.form, + onConfirm: async (formData?: F) => { + if (!props.onConfirm) { + resolve(undefined as any); + return; + } + const res = await props.onConfirm(formData as any); + resolve(res); + }, + }); + }); + return promise; +} + +export { ConfirmDialog, confirm }; diff --git a/frontend/src/components/block/markdown/index.tsx b/frontend/src/components/block/markdown/index.tsx new file mode 100644 index 000000000..f0a63969f --- /dev/null +++ b/frontend/src/components/block/markdown/index.tsx @@ -0,0 +1,27 @@ +import { cn } from '@/libs/utils'; +import React from 'react'; +import ReactMarkdown from 'react-markdown'; +import rehypeRaw from 'rehype-raw'; +import remarkGfm from 'remark-gfm'; + +export const Markdown: React.FC<{ children: string | null; className?: string }> = ({ children, className }) => { + return ( +
+ ); +}; diff --git a/frontend/src/components/features/chat/input/index.tsx b/frontend/src/components/features/chat/input/index.tsx new file mode 100644 index 000000000..29b8e593a --- /dev/null +++ b/frontend/src/components/features/chat/input/index.tsx @@ -0,0 +1,109 @@ +import { confirm } from '@/components/block/confirm'; +import { Button } from '@/components/ui/button'; +import { DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Textarea } from '@/components/ui/textarea'; +import { PauseCircle, Rocket, Send } from 'lucide-react'; +import { useState } from 'react'; + +interface ChatInputProps { + taskId?: string; + status?: 'idle' | 'thinking' | 'terminating' | 'completed'; + onSubmit?: (value: { taskId?: string; prompt: string }) => Promise; + onTerminate?: () => Promise; +} + +export const ChatInput = ({ taskId, status = 'idle', onSubmit, onTerminate }: ChatInputProps) => { + const [value, setValue] = useState(''); + + const handleKeyDown = async (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + if (status === 'thinking' || status === 'terminating' || !value.trim()) { + return; + } + await onSubmit?.({ taskId, prompt: value.trim() }); + setValue(''); + } + }; + + const handleSendClick = async () => { + if (status === 'thinking' || status === 'terminating') { + confirm({ + content: ( + + Terminate Task + Are you sure you want to terminate this task? + + ), + onConfirm: async () => { + await onTerminate?.(); + }, + buttonText: { + cancel: 'Cancel', + confirm: 'Terminate', + loading: 'Terminating...', + }, + }); + return; + } + const v = value.trim(); + if (v) { + await onSubmit?.({ prompt: v }); + setValue(''); + } + }; + + return ( +
+
+ {status !== 'idle' && ( +
+ +
+ )} +
+
+ { + return ( + + {children} + + ); + }, + }} + > + {children} + +