diff --git a/.github/workflows/linting.yaml b/.github/workflows/linting.yaml index 7c12e0a2..aa054369 100644 --- a/.github/workflows/linting.yaml +++ b/.github/workflows/linting.yaml @@ -27,4 +27,4 @@ jobs: pip install pre-commit - name: Run pre-commit - run: pre-commit run --all-files + run: pre-commit run --all-files --show-diff-on-failure diff --git a/README-zh.md b/README-zh.md index e69de29b..ccef4055 100644 --- a/README-zh.md +++ b/README-zh.md @@ -0,0 +1,1380 @@ +# LightRAG: Simple and Fast Retrieval-Augmented Generation + +LightRAG Diagram + +## 🎉 新闻 + +- [X] [2025.03.18]🎯📢LightRAG现已支持引文功能。 +- [X] [2025.02.05]🎯📢我们团队发布了[VideoRAG](https://github.com/HKUDS/VideoRAG),用于理解超长上下文视频。 +- [X] [2025.01.13]🎯📢我们团队发布了[MiniRAG](https://github.com/HKUDS/MiniRAG),使用小型模型简化RAG。 +- [X] [2025.01.06]🎯📢现在您可以[使用PostgreSQL进行存储](#using-postgresql-for-storage)。 +- [X] [2024.12.31]🎯📢LightRAG现在支持[通过文档ID删除](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#delete)。 +- [X] [2024.11.25]🎯📢LightRAG现在支持无缝集成[自定义知识图谱](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#insert-custom-kg),使用户能够用自己的领域专业知识增强系统。 +- [X] [2024.11.19]🎯📢LightRAG的综合指南现已在[LearnOpenCV](https://learnopencv.com/lightrag)上发布。非常感谢博客作者。 +- [X] [2024.11.12]🎯📢LightRAG现在支持[Oracle Database 23ai的所有存储类型(KV、向量和图)](https://github.com/HKUDS/LightRAG/blob/main/examples/lightrag_oracle_demo.py)。 +- [X] [2024.11.11]🎯📢LightRAG现在支持[通过实体名称删除实体](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#delete)。 +- [X] [2024.11.09]🎯📢推出[LightRAG Gui](https://lightrag-gui.streamlit.app),允许您插入、查询、可视化和下载LightRAG知识。 +- [X] [2024.11.04]🎯📢现在您可以[使用Neo4J进行存储](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#using-neo4j-for-storage)。 +- [X] [2024.10.29]🎯📢LightRAG现在通过`textract`支持多种文件类型,包括PDF、DOC、PPT和CSV。 +- [X] [2024.10.20]🎯📢我们为LightRAG添加了一个新功能:图形可视化。 +- [X] [2024.10.18]🎯📢我们添加了[LightRAG介绍视频](https://youtu.be/oageL-1I0GE)的链接。感谢作者! +- [X] [2024.10.17]🎯📢我们创建了一个[Discord频道](https://discord.gg/yF2MmDJyGJ)!欢迎加入分享和讨论!🎉🎉 +- [X] [2024.10.16]🎯📢LightRAG现在支持[Ollama模型](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#quick-start)! +- [X] [2024.10.15]🎯📢LightRAG现在支持[Hugging Face模型](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#quick-start)! + +
+ + 算法流程图 + + +![LightRAG索引流程图](https://learnopencv.com/wp-content/uploads/2024/11/LightRAG-VectorDB-Json-KV-Store-Indexing-Flowchart-scaled.jpg) +*图1:LightRAG索引流程图 - 图片来源:[Source](https://learnopencv.com/lightrag/)* +![LightRAG检索和查询流程图](https://learnopencv.com/wp-content/uploads/2024/11/LightRAG-Querying-Flowchart-Dual-Level-Retrieval-Generation-Knowledge-Graphs-scaled.jpg) +*图2:LightRAG检索和查询流程图 - 图片来源:[Source](https://learnopencv.com/lightrag/)* + +
+ +## 安装 + +### 安装LightRAG核心 + +* 从源代码安装(推荐) + +```bash +cd LightRAG +pip install -e . +``` + +* 从PyPI安装 + +```bash +pip install lightrag-hku +``` + +### 安装LightRAG服务器 + +LightRAG服务器旨在提供Web UI和API支持。Web UI便于文档索引、知识图谱探索和简单的RAG查询界面。LightRAG服务器还提供兼容Ollama的接口,旨在将LightRAG模拟为Ollama聊天模型。这使得AI聊天机器人(如Open WebUI)可以轻松访问LightRAG。 + +* 从PyPI安装 + +```bash +pip install "lightrag-hku[api]" +``` + +* 从源代码安装 + +```bash +# 如有必要,创建Python虚拟环境 +# 以可编辑模式安装并支持API +pip install -e ".[api]" +``` + +**有关LightRAG服务器的更多信息,请参阅[LightRAG服务器](./lightrag/api/README.md)。** + +## 快速开始 + +* [视频演示](https://www.youtube.com/watch?v=g21royNJ4fw)展示如何在本地运行LightRAG。 +* 所有代码都可以在`examples`中找到。 +* 如果使用OpenAI模型,请在环境中设置OpenAI API密钥:`export OPENAI_API_KEY="sk-..."`。 +* 下载演示文本"狄更斯的圣诞颂歌": + +```bash +curl https://raw.githubusercontent.com/gusye1234/nano-graphrag/main/tests/mock_data.txt > ./book.txt +``` + +## 查询 + +使用以下Python代码片段(在脚本中)初始化LightRAG并执行查询: + +```python +import os +import asyncio +from lightrag import LightRAG, QueryParam +from lightrag.llm.openai import gpt_4o_mini_complete, gpt_4o_complete, openai_embed +from lightrag.kg.shared_storage import initialize_pipeline_status +from lightrag.utils import setup_logger + +setup_logger("lightrag", level="INFO") + +async def initialize_rag(): + rag = LightRAG( + working_dir="your/path", + embedding_func=openai_embed, + llm_model_func=gpt_4o_mini_complete + ) + + await rag.initialize_storages() + await initialize_pipeline_status() + + return rag + +def main(): + # 初始化RAG实例 + rag = asyncio.run(initialize_rag()) + # 插入文本 + rag.insert("Your text") + + # 执行朴素搜索 + mode="naive" + # 执行本地搜索 + mode="local" + # 执行全局搜索 + mode="global" + # 执行混合搜索 + mode="hybrid" + # 混合模式集成知识图谱和向量检索 + mode="mix" + + rag.query( + "这个故事的主要主题是什么?", + param=QueryParam(mode=mode) + ) + +if __name__ == "__main__": + main() +``` + +### 查询参数 + +```python +class QueryParam: + mode: Literal["local", "global", "hybrid", "naive", "mix"] = "global" + """指定检索模式: + - "local":专注于上下文相关信息。 + - "global":利用全局知识。 + - "hybrid":结合本地和全局检索方法。 + - "naive":执行基本搜索,不使用高级技术。 + - "mix":集成知识图谱和向量检索。混合模式结合知识图谱和向量搜索: + - 同时使用结构化(KG)和非结构化(向量)信息 + - 通过分析关系和上下文提供全面的答案 + - 通过HTML img标签支持图像内容 + - 允许通过top_k参数控制检索深度 + """ + only_need_context: bool = False + """如果为True,仅返回检索到的上下文而不生成响应。""" + response_type: str = "Multiple Paragraphs" + """定义响应格式。示例:'Multiple Paragraphs'(多段落), 'Single Paragraph'(单段落), 'Bullet Points'(要点列表)。""" + top_k: int = 60 + """要检索的顶部项目数量。在'local'模式下代表实体,在'global'模式下代表关系。""" + max_token_for_text_unit: int = 4000 + """每个检索文本块允许的最大令牌数。""" + max_token_for_global_context: int = 4000 + """全局检索中关系描述的最大令牌分配。""" + max_token_for_local_context: int = 4000 + """本地检索中实体描述的最大令牌分配。""" + ids: list[str] | None = None # 仅支持PG向量数据库 + """用于过滤RAG的ID列表。""" + ... +``` + +> top_k的默认值可以通过环境变量TOP_K更改。 + +
+ 使用类OpenAI的API + +* LightRAG还支持类OpenAI的聊天/嵌入API: + +```python +async def llm_model_func( + prompt, system_prompt=None, history_messages=[], keyword_extraction=False, **kwargs +) -> str: + return await openai_complete_if_cache( + "solar-mini", + prompt, + system_prompt=system_prompt, + history_messages=history_messages, + api_key=os.getenv("UPSTAGE_API_KEY"), + base_url="https://api.upstage.ai/v1/solar", + **kwargs + ) + +async def embedding_func(texts: list[str]) -> np.ndarray: + return await openai_embed( + texts, + model="solar-embedding-1-large-query", + api_key=os.getenv("UPSTAGE_API_KEY"), + base_url="https://api.upstage.ai/v1/solar" + ) + +async def initialize_rag(): + rag = LightRAG( + working_dir=WORKING_DIR, + llm_model_func=llm_model_func, + embedding_func=EmbeddingFunc( + embedding_dim=4096, + max_token_size=8192, + func=embedding_func + ) + ) + + await rag.initialize_storages() + await initialize_pipeline_status() + + return rag +``` + +
+ +
+ 使用Hugging Face模型 + +* 如果您想使用Hugging Face模型,只需要按如下方式设置LightRAG: + +参见`lightrag_hf_demo.py` + +```python +# 使用Hugging Face模型初始化LightRAG +rag = LightRAG( + working_dir=WORKING_DIR, + llm_model_func=hf_model_complete, # 使用Hugging Face模型进行文本生成 + llm_model_name='meta-llama/Llama-3.1-8B-Instruct', # Hugging Face的模型名称 + # 使用Hugging Face嵌入函数 + embedding_func=EmbeddingFunc( + embedding_dim=384, + max_token_size=5000, + func=lambda texts: hf_embed( + texts, + tokenizer=AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2"), + embed_model=AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2") + ) + ), +) +``` + +
+ +
+ 使用Ollama模型 + +### 概述 + +如果您想使用Ollama模型,您需要拉取计划使用的模型和嵌入模型,例如`nomic-embed-text`。 + +然后您只需要按如下方式设置LightRAG: + +```python +# 使用Ollama模型初始化LightRAG +rag = LightRAG( + working_dir=WORKING_DIR, + llm_model_func=ollama_model_complete, # 使用Ollama模型进行文本生成 + llm_model_name='your_model_name', # 您的模型名称 + # 使用Ollama嵌入函数 + embedding_func=EmbeddingFunc( + embedding_dim=768, + max_token_size=8192, + func=lambda texts: ollama_embed( + texts, + embed_model="nomic-embed-text" + ) + ), +) +``` + +### 增加上下文大小 + +为了使LightRAG正常工作,上下文应至少为32k令牌。默认情况下,Ollama模型的上下文大小为8k。您可以通过以下两种方式之一实现这一点: + +#### 在Modelfile中增加`num_ctx`参数。 + +1. 拉取模型: + +```bash +ollama pull qwen2 +``` + +2. 显示模型文件: + +```bash +ollama show --modelfile qwen2 > Modelfile +``` + +3. 编辑Modelfile,添加以下行: + +```bash +PARAMETER num_ctx 32768 +``` + +4. 创建修改后的模型: + +```bash +ollama create -f Modelfile qwen2m +``` + +#### 通过Ollama API设置`num_ctx`。 + +您可以使用`llm_model_kwargs`参数配置ollama: + +```python +rag = LightRAG( + working_dir=WORKING_DIR, + llm_model_func=ollama_model_complete, # 使用Ollama模型进行文本生成 + llm_model_name='your_model_name', # 您的模型名称 + llm_model_kwargs={"options": {"num_ctx": 32768}}, + # 使用Ollama嵌入函数 + embedding_func=EmbeddingFunc( + embedding_dim=768, + max_token_size=8192, + func=lambda texts: ollama_embedding( + texts, + embed_model="nomic-embed-text" + ) + ), +) +``` + +#### 低RAM GPU + +为了在低RAM GPU上运行此实验,您应该选择小型模型并调整上下文窗口(增加上下文会增加内存消耗)。例如,在6Gb RAM的改装挖矿GPU上运行这个ollama示例需要将上下文大小设置为26k,同时使用`gemma2:2b`。它能够在`book.txt`中找到197个实体和19个关系。 + +
+
+ LlamaIndex + +LightRAG支持与LlamaIndex集成。 + +1. **LlamaIndex** (`llm/llama_index_impl.py`): + - 通过LlamaIndex与OpenAI和其他提供商集成 + - 详细设置和示例请参见[LlamaIndex文档](lightrag/llm/Readme.md) + +### 使用示例 + +```python +# 使用LlamaIndex直接访问OpenAI +import asyncio +from lightrag import LightRAG +from lightrag.llm.llama_index_impl import llama_index_complete_if_cache, llama_index_embed +from llama_index.embeddings.openai import OpenAIEmbedding +from llama_index.llms.openai import OpenAI +from lightrag.kg.shared_storage import initialize_pipeline_status +from lightrag.utils import setup_logger + +# 为LightRAG设置日志处理程序 +setup_logger("lightrag", level="INFO") + +async def initialize_rag(): + rag = LightRAG( + working_dir="your/path", + llm_model_func=llama_index_complete_if_cache, # LlamaIndex兼容的完成函数 + embedding_func=EmbeddingFunc( # LlamaIndex兼容的嵌入函数 + embedding_dim=1536, + max_token_size=8192, + func=lambda texts: llama_index_embed(texts, embed_model=embed_model) + ), + ) + + await rag.initialize_storages() + await initialize_pipeline_status() + + return rag + +def main(): + # 初始化RAG实例 + rag = asyncio.run(initialize_rag()) + + with open("./book.txt", "r", encoding="utf-8") as f: + rag.insert(f.read()) + + # 执行朴素搜索 + print( + rag.query("这个故事的主要主题是什么?", param=QueryParam(mode="naive")) + ) + + # 执行本地搜索 + print( + rag.query("这个故事的主要主题是什么?", param=QueryParam(mode="local")) + ) + + # 执行全局搜索 + print( + rag.query("这个故事的主要主题是什么?", param=QueryParam(mode="global")) + ) + + # 执行混合搜索 + print( + rag.query("这个故事的主要主题是什么?", param=QueryParam(mode="hybrid")) + ) + +if __name__ == "__main__": + main() +``` + +#### 详细文档和示例,请参见: + +- [LlamaIndex文档](lightrag/llm/Readme.md) +- [直接OpenAI示例](examples/lightrag_llamaindex_direct_demo.py) +- [LiteLLM代理示例](examples/lightrag_llamaindex_litellm_demo.py) + +
+
+ 对话历史支持 + +LightRAG现在通过对话历史功能支持多轮对话。以下是使用方法: + +```python +# 创建对话历史 +conversation_history = [ + {"role": "user", "content": "主角对圣诞节的态度是什么?"}, + {"role": "assistant", "content": "在故事开始时,埃比尼泽·斯克鲁奇对圣诞节持非常消极的态度..."}, + {"role": "user", "content": "他的态度是如何改变的?"} +] + +# 创建带有对话历史的查询参数 +query_param = QueryParam( + mode="mix", # 或其他模式:"local"、"global"、"hybrid" + conversation_history=conversation_history, # 添加对话历史 + history_turns=3 # 考虑最近的对话轮数 +) + +# 进行考虑对话历史的查询 +response = rag.query( + "是什么导致了他性格的这种变化?", + param=query_param +) +``` + +
+ +
+ 自定义提示支持 + +LightRAG现在支持自定义提示,以便对系统行为进行精细控制。以下是使用方法: + +```python +# 创建查询参数 +query_param = QueryParam( + mode="hybrid", # 或其他模式:"local"、"global"、"hybrid"、"mix"和"naive" +) + +# 示例1:使用默认系统提示 +response_default = rag.query( + "可再生能源的主要好处是什么?", + param=query_param +) +print(response_default) + +# 示例2:使用自定义提示 +custom_prompt = """ +您是环境科学领域的专家助手。请提供详细且结构化的答案,并附带示例。 +---对话历史--- +{history} + +---知识库--- +{context_data} + +---响应规则--- + +- 目标格式和长度:{response_type} +""" +response_custom = rag.query( + "可再生能源的主要好处是什么?", + param=query_param, + system_prompt=custom_prompt # 传递自定义提示 +) +print(response_custom) +``` + +
+ +
+ 独立关键词提取 + +我们引入了新函数`query_with_separate_keyword_extraction`来增强关键词提取功能。该函数将关键词提取过程与用户提示分开,专注于查询以提高提取关键词的相关性。 + +##### 工作原理 + +该函数将输入分为两部分: + +- `用户查询` +- `提示` + +然后仅对`用户查询`执行关键词提取。这种分离确保提取过程是集中和相关的,不受`提示`中任何额外语言的影响。它还允许`提示`纯粹用于响应格式化,保持用户原始问题的意图和清晰度。 + +##### 使用示例 + +这个`示例`展示了如何为教育内容定制函数,专注于为高年级学生提供详细解释。 + +```python +rag.query_with_separate_keyword_extraction( + query="解释重力定律", + prompt="提供适合学习物理的高中生的详细解释。", + param=QueryParam(mode="hybrid") +) +``` + +
+ +
+ 插入自定义KG + +```python +custom_kg = { + "chunks": [ + { + "content": "Alice和Bob正在合作进行量子计算研究。", + "source_id": "doc-1" + } + ], + "entities": [ + { + "entity_name": "Alice", + "entity_type": "person", + "description": "Alice是一位专门研究量子物理的研究员。", + "source_id": "doc-1" + }, + { + "entity_name": "Bob", + "entity_type": "person", + "description": "Bob是一位数学家。", + "source_id": "doc-1" + }, + { + "entity_name": "量子计算", + "entity_type": "technology", + "description": "量子计算利用量子力学现象进行计算。", + "source_id": "doc-1" + } + ], + "relationships": [ + { + "src_id": "Alice", + "tgt_id": "Bob", + "description": "Alice和Bob是研究伙伴。", + "keywords": "合作 研究", + "weight": 1.0, + "source_id": "doc-1" + }, + { + "src_id": "Alice", + "tgt_id": "量子计算", + "description": "Alice进行量子计算研究。", + "keywords": "研究 专业", + "weight": 1.0, + "source_id": "doc-1" + }, + { + "src_id": "Bob", + "tgt_id": "量子计算", + "description": "Bob研究量子计算。", + "keywords": "研究 应用", + "weight": 1.0, + "source_id": "doc-1" + } + ] +} + +rag.insert_custom_kg(custom_kg) +``` + +
+ +## 插入 + +#### 基本插入 + +```python +# 基本插入 +rag.insert("文本") +``` + +
+ 批量插入 + +```python +# 基本批量插入:一次插入多个文本 +rag.insert(["文本1", "文本2",...]) + +# 带有自定义批量大小配置的批量插入 +rag = LightRAG( + working_dir=WORKING_DIR, + addon_params={ + "insert_batch_size": 4 # 每批处理4个文档 + } +) + +rag.insert(["文本1", "文本2", "文本3", ...]) # 文档将以4个为一批进行处理 +``` + +`addon_params`中的`insert_batch_size`参数控制插入过程中每批处理的文档数量。这对于以下情况很有用: + +- 管理大型文档集合的内存使用 +- 优化处理速度 +- 提供更好的进度跟踪 +- 如果未指定,默认值为10 + +
+ +
+ 带ID插入 + +如果您想为文档提供自己的ID,文档数量和ID数量必须相同。 + +```python +# 插入单个文本,并为其提供ID +rag.insert("文本1", ids=["文本1的ID"]) + +# 插入多个文本,并为它们提供ID +rag.insert(["文本1", "文本2",...], ids=["文本1的ID", "文本2的ID"]) +``` + +
+ +
+ 使用管道插入 + +`apipeline_enqueue_documents`和`apipeline_process_enqueue_documents`函数允许您对文档进行增量插入到图中。 + +这对于需要在后台处理文档的场景很有用,同时仍允许主线程继续执行。 + +并使用例程处理新文档。 + +```python +rag = LightRAG(..) + +await rag.apipeline_enqueue_documents(input) +# 您的循环例程 +await rag.apipeline_process_enqueue_documents(input) +``` + +
+ +
+ 插入多文件类型支持 + +`textract`支持读取TXT、DOCX、PPTX、CSV和PDF等文件类型。 + +```python +import textract + +file_path = 'TEXT.pdf' +text_content = textract.process(file_path) + +rag.insert(text_content.decode('utf-8')) +``` + +
+ +
+ 引文功能 + +通过提供文件路径,系统确保可以将来源追溯到其原始文档。 + +```python +# 定义文档及其文件路径 +documents = ["文档内容1", "文档内容2"] +file_paths = ["path/to/doc1.txt", "path/to/doc2.txt"] + +# 插入带有文件路径的文档 +rag.insert(documents, file_paths=file_paths) +``` + +
+ +## 存储 + +
+ 使用Neo4J进行存储 + +* 对于生产级场景,您很可能想要利用企业级解决方案 +* 进行KG存储。推荐在Docker中运行Neo4J以进行无缝本地测试。 +* 参见:https://hub.docker.com/_/neo4j + +```python +export NEO4J_URI="neo4j://localhost:7687" +export NEO4J_USERNAME="neo4j" +export NEO4J_PASSWORD="password" + +# 为LightRAG设置日志记录器 +setup_logger("lightrag", level="INFO") + +# 当您启动项目时,请确保通过指定kg="Neo4JStorage"来覆盖默认的KG:NetworkX。 + +# 注意:默认设置使用NetworkX +# 使用Neo4J实现初始化LightRAG。 +async def initialize_rag(): + rag = LightRAG( + working_dir=WORKING_DIR, + llm_model_func=gpt_4o_mini_complete, # 使用gpt_4o_mini_complete LLM模型 + graph_storage="Neo4JStorage", #<-----------覆盖KG默认值 + ) + + # 初始化数据库连接 + await rag.initialize_storages() + # 初始化文档处理的管道状态 + await initialize_pipeline_status() + + return rag +``` + +参见test_neo4j.py获取工作示例。 + +
+ +
+ 使用Faiss进行存储 + +- 安装所需依赖: + +``` +pip install faiss-cpu +``` + +如果您有GPU支持,也可以安装`faiss-gpu`。 + +- 这里我们使用`sentence-transformers`,但您也可以使用维度为`3072`的`OpenAIEmbedding`模型。 + +```python +async def embedding_func(texts: list[str]) -> np.ndarray: + model = SentenceTransformer('all-MiniLM-L6-v2') + embeddings = model.encode(texts, convert_to_numpy=True) + return embeddings + +# 使用LLM模型函数和嵌入函数初始化LightRAG +rag = LightRAG( + working_dir=WORKING_DIR, + llm_model_func=llm_model_func, + embedding_func=EmbeddingFunc( + embedding_dim=384, + max_token_size=8192, + func=embedding_func, + ), + vector_storage="FaissVectorDBStorage", + vector_db_storage_cls_kwargs={ + "cosine_better_than_threshold": 0.3 # 您期望的阈值 + } +) +``` + +
+ +
+ 使用PostgreSQL进行存储 + +对于生产级场景,您很可能想要利用企业级解决方案。PostgreSQL可以为您提供一站式解决方案,作为KV存储、向量数据库(pgvector)和图数据库(apache AGE)。 + +* PostgreSQL很轻量,整个二进制发行版包括所有必要的插件可以压缩到40MB:参考[Windows发布版](https://github.com/ShanGor/apache-age-windows/releases/tag/PG17%2Fv1.5.0-rc0),它在Linux/Mac上也很容易安装。 +* 如果您是初学者并想避免麻烦,推荐使用docker,请从这个镜像开始(请务必阅读概述):https://hub.docker.com/r/shangor/postgres-for-rag +* 如何开始?参考:[examples/lightrag_zhipu_postgres_demo.py](https://github.com/HKUDS/LightRAG/blob/main/examples/lightrag_zhipu_postgres_demo.py) +* 为AGE创建索引示例:(如有必要,将下面的`dickens`改为您的图名) + ```sql + load 'age'; + SET search_path = ag_catalog, "$user", public; + CREATE INDEX CONCURRENTLY entity_p_idx ON dickens."Entity" (id); + CREATE INDEX CONCURRENTLY vertex_p_idx ON dickens."_ag_label_vertex" (id); + CREATE INDEX CONCURRENTLY directed_p_idx ON dickens."DIRECTED" (id); + CREATE INDEX CONCURRENTLY directed_eid_idx ON dickens."DIRECTED" (end_id); + CREATE INDEX CONCURRENTLY directed_sid_idx ON dickens."DIRECTED" (start_id); + CREATE INDEX CONCURRENTLY directed_seid_idx ON dickens."DIRECTED" (start_id,end_id); + CREATE INDEX CONCURRENTLY edge_p_idx ON dickens."_ag_label_edge" (id); + CREATE INDEX CONCURRENTLY edge_sid_idx ON dickens."_ag_label_edge" (start_id); + CREATE INDEX CONCURRENTLY edge_eid_idx ON dickens."_ag_label_edge" (end_id); + CREATE INDEX CONCURRENTLY edge_seid_idx ON dickens."_ag_label_edge" (start_id,end_id); + create INDEX CONCURRENTLY vertex_idx_node_id ON dickens."_ag_label_vertex" (ag_catalog.agtype_access_operator(properties, '"node_id"'::agtype)); + create INDEX CONCURRENTLY entity_idx_node_id ON dickens."Entity" (ag_catalog.agtype_access_operator(properties, '"node_id"'::agtype)); + CREATE INDEX CONCURRENTLY entity_node_id_gin_idx ON dickens."Entity" using gin(properties); + ALTER TABLE dickens."DIRECTED" CLUSTER ON directed_sid_idx; + + -- 如有必要可以删除 + drop INDEX entity_p_idx; + drop INDEX vertex_p_idx; + drop INDEX directed_p_idx; + drop INDEX directed_eid_idx; + drop INDEX directed_sid_idx; + drop INDEX directed_seid_idx; + drop INDEX edge_p_idx; + drop INDEX edge_sid_idx; + drop INDEX edge_eid_idx; + drop INDEX edge_seid_idx; + drop INDEX vertex_idx_node_id; + drop INDEX entity_idx_node_id; + drop INDEX entity_node_id_gin_idx; + ``` +* Apache AGE的已知问题:发布版本存在以下问题: + > 您可能会发现节点/边的属性是空的。 + > 这是发布版本的已知问题:https://github.com/apache/age/pull/1721 + > + > 您可以从源代码编译AGE来修复它。 + > + +## 删除 + +```python +# 删除实体:通过实体名称删除实体 +rag.delete_by_entity("Project Gutenberg") + +# 删除文档:通过文档ID删除与文档相关的实体和关系 +rag.delete_by_doc_id("doc_id") +``` + +## 编辑实体和关系 + +LightRAG现在支持全面的知识图谱管理功能,允许您在知识图谱中创建、编辑和删除实体和关系。 + +
+ 创建实体和关系 + +```python +# 创建新实体 +entity = rag.create_entity("Google", { + "description": "Google是一家专注于互联网相关服务和产品的跨国科技公司。", + "entity_type": "company" +}) + +# 创建另一个实体 +product = rag.create_entity("Gmail", { + "description": "Gmail是由Google开发的电子邮件服务。", + "entity_type": "product" +}) + +# 创建实体之间的关系 +relation = rag.create_relation("Google", "Gmail", { + "description": "Google开发和运营Gmail。", + "keywords": "开发 运营 服务", + "weight": 2.0 +}) +``` + +
+ +
+ 编辑实体和关系 + +```python +# 编辑现有实体 +updated_entity = rag.edit_entity("Google", { + "description": "Google是Alphabet Inc.的子公司,成立于1998年。", + "entity_type": "tech_company" +}) + +# 重命名实体(所有关系都会正确迁移) +renamed_entity = rag.edit_entity("Gmail", { + "entity_name": "Google Mail", + "description": "Google Mail(前身为Gmail)是一项电子邮件服务。" +}) + +# 编辑实体之间的关系 +updated_relation = rag.edit_relation("Google", "Google Mail", { + "description": "Google创建并维护Google Mail服务。", + "keywords": "创建 维护 电子邮件服务", + "weight": 3.0 +}) +``` + +
+ +所有操作都有同步和异步版本。异步版本带有前缀"a"(例如,`acreate_entity`,`aedit_relation`)。 + +#### 实体操作 + +- **create_entity**:创建具有指定属性的新实体 +- **edit_entity**:更新现有实体的属性或重命名它 + +#### 关系操作 + +- **create_relation**:在现有实体之间创建新关系 +- **edit_relation**:更新现有关系的属性 + +这些操作在图数据库和向量数据库组件之间保持数据一致性,确保您的知识图谱保持连贯。 + +## 数据导出功能 + +## 概述 + +LightRAG允许您以各种格式导出知识图谱数据,用于分析、共享和备份目的。系统支持导出实体、关系和关系数据。 + +## 导出功能 + +### 基本用法 + +```python +# 基本CSV导出(默认格式) +rag.export_data("knowledge_graph.csv") + +# 指定任意格式 +rag.export_data("output.xlsx", file_format="excel") +``` + +### 支持的不同文件格式 + +```python +# 以CSV格式导出数据 +rag.export_data("graph_data.csv", file_format="csv") + +# 导出数据到Excel表格 +rag.export_data("graph_data.xlsx", file_format="excel") + +# 以markdown格式导出数据 +rag.export_data("graph_data.md", file_format="md") + +# 导出数据为文本 +rag.export_data("graph_data.txt", file_format="txt") +``` + +## 附加选项 + +在导出中包含向量嵌入(可选): + +```python +rag.export_data("complete_data.csv", include_vector_data=True) +``` + +## 导出数据包括 + +所有导出包括: + +* 实体信息(名称、ID、元数据) +* 关系数据(实体之间的连接) +* 来自向量数据库的关系信息 + +## 实体合并 + +
+ 合并实体及其关系 + +LightRAG现在支持将多个实体合并为单个实体,自动处理所有关系: + +```python +# 基本实体合并 +rag.merge_entities( + source_entities=["人工智能", "AI", "机器智能"], + target_entity="AI技术" +) +``` + +使用自定义合并策略: + +```python +# 为不同字段定义自定义合并策略 +rag.merge_entities( + source_entities=["约翰·史密斯", "史密斯博士", "J·史密斯"], + target_entity="约翰·史密斯", + merge_strategy={ + "description": "concatenate", # 组合所有描述 + "entity_type": "keep_first", # 保留第一个实体的类型 + "source_id": "join_unique" # 组合所有唯一的源ID + } +) +``` + +使用自定义目标实体数据: + +```python +# 为合并后的实体指定确切值 +rag.merge_entities( + source_entities=["纽约", "NYC", "大苹果"], + target_entity="纽约市", + target_entity_data={ + "entity_type": "LOCATION", + "description": "纽约市是美国人口最多的城市。", + } +) +``` + +结合两种方法的高级用法: + +```python +# 使用策略和自定义数据合并公司实体 +rag.merge_entities( + source_entities=["微软公司", "Microsoft Corporation", "MSFT"], + target_entity="微软", + merge_strategy={ + "description": "concatenate", # 组合所有描述 + "source_id": "join_unique" # 组合源ID + }, + target_entity_data={ + "entity_type": "ORGANIZATION", + } +) +``` + +合并实体时: + +* 所有来自源实体的关系都会重定向到目标实体 +* 重复的关系会被智能合并 +* 防止自我关系(循环) +* 合并后删除源实体 +* 保留关系权重和属性 + +
+ +## 缓存 + +
+ 清除缓存 + +您可以使用不同模式清除LLM响应缓存: + +```python +# 清除所有缓存 +await rag.aclear_cache() + +# 清除本地模式缓存 +await rag.aclear_cache(modes=["local"]) + +# 清除提取缓存 +await rag.aclear_cache(modes=["default"]) + +# 清除多个模式 +await rag.aclear_cache(modes=["local", "global", "hybrid"]) + +# 同步版本 +rag.clear_cache(modes=["local"]) +``` + +有效的模式包括: + +- `"default"`:提取缓存 +- `"naive"`:朴素搜索缓存 +- `"local"`:本地搜索缓存 +- `"global"`:全局搜索缓存 +- `"hybrid"`:混合搜索缓存 +- `"mix"`:混合搜索缓存 + +
+ +## LightRAG初始化参数 + +
+ 参数 + +| **参数** | **类型** | **说明** | **默认值** | +|--------------|----------|-----------------|-------------| +| **working_dir** | `str` | 存储缓存的目录 | `lightrag_cache+timestamp` | +| **kv_storage** | `str` | 文档和文本块的存储类型。支持的类型:`JsonKVStorage`、`OracleKVStorage` | `JsonKVStorage` | +| **vector_storage** | `str` | 嵌入向量的存储类型。支持的类型:`NanoVectorDBStorage`、`OracleVectorDBStorage` | `NanoVectorDBStorage` | +| **graph_storage** | `str` | 图边和节点的存储类型。支持的类型:`NetworkXStorage`、`Neo4JStorage`、`OracleGraphStorage` | `NetworkXStorage` | +| **chunk_token_size** | `int` | 拆分文档时每个块的最大令牌大小 | `1200` | +| **chunk_overlap_token_size** | `int` | 拆分文档时两个块之间的重叠令牌大小 | `100` | +| **tiktoken_model_name** | `str` | 用于计算令牌数的Tiktoken编码器的模型名称 | `gpt-4o-mini` | +| **entity_extract_max_gleaning** | `int` | 实体提取过程中的循环次数,附加历史消息 | `1` | +| **entity_summary_to_max_tokens** | `int` | 每个实体摘要的最大令牌大小 | `500` | +| **node_embedding_algorithm** | `str` | 节点嵌入算法(当前未使用) | `node2vec` | +| **node2vec_params** | `dict` | 节点嵌入的参数 | `{"dimensions": 1536,"num_walks": 10,"walk_length": 40,"window_size": 2,"iterations": 3,"random_seed": 3,}` | +| **embedding_func** | `EmbeddingFunc` | 从文本生成嵌入向量的函数 | `openai_embed` | +| **embedding_batch_num** | `int` | 嵌入过程的最大批量大小(每批发送多个文本) | `32` | +| **embedding_func_max_async** | `int` | 最大并发异步嵌入进程数 | `16` | +| **llm_model_func** | `callable` | LLM生成的函数 | `gpt_4o_mini_complete` | +| **llm_model_name** | `str` | 用于生成的LLM模型名称 | `meta-llama/Llama-3.2-1B-Instruct` | +| **llm_model_max_token_size** | `int` | LLM生成的最大令牌大小(影响实体关系摘要) | `32768`(默认值由环境变量MAX_TOKENS更改) | +| **llm_model_max_async** | `int` | 最大并发异步LLM进程数 | `4`(默认值由环境变量MAX_ASYNC更改) | +| **llm_model_kwargs** | `dict` | LLM生成的附加参数 | | +| **vector_db_storage_cls_kwargs** | `dict` | 向量数据库的附加参数,如设置节点和关系检索的阈值 | cosine_better_than_threshold: 0.2(默认值由环境变量COSINE_THRESHOLD更改) | +| **enable_llm_cache** | `bool` | 如果为`TRUE`,将LLM结果存储在缓存中;重复的提示返回缓存的响应 | `TRUE` | +| **enable_llm_cache_for_entity_extract** | `bool` | 如果为`TRUE`,将实体提取的LLM结果存储在缓存中;适合初学者调试应用程序 | `TRUE` | +| **addon_params** | `dict` | 附加参数,例如`{"example_number": 1, "language": "Simplified Chinese", "entity_types": ["organization", "person", "geo", "event"], "insert_batch_size": 10}`:设置示例限制、输出语言和文档处理的批量大小 | `example_number: 所有示例, language: English, insert_batch_size: 10` | +| **convert_response_to_json_func** | `callable` | 未使用 | `convert_response_to_json` | +| **embedding_cache_config** | `dict` | 问答缓存的配置。包含三个参数:`enabled`:布尔值,启用/禁用缓存查找功能。启用时,系统将在生成新答案之前检查缓存的响应。`similarity_threshold`:浮点值(0-1),相似度阈值。当新问题与缓存问题的相似度超过此阈值时,将直接返回缓存的答案而不调用LLM。`use_llm_check`:布尔值,启用/禁用LLM相似度验证。启用时,在返回缓存答案之前,将使用LLM作为二次检查来验证问题之间的相似度。 | 默认:`{"enabled": False, "similarity_threshold": 0.95, "use_llm_check": False}` | + +
+ +## 错误处理 + +
+点击查看错误处理详情 + +API包括全面的错误处理: + +- 文件未找到错误(404) +- 处理错误(500) +- 支持多种文件编码(UTF-8和GBK) + +
+ +## API + +LightRag可以安装API支持,以提供Fast api接口来执行数据上传和索引/Rag操作/重新扫描输入文件夹等。 + +[LightRag API](lightrag/api/README.md) + +## 图形可视化 + +LightRAG服务器提供全面的知识图谱可视化功能。它支持各种重力布局、节点查询、子图过滤等。**有关LightRAG服务器的更多信息,请参阅[LightRAG服务器](./lightrag/api/README.md)。** + +![iShot_2025-03-23_12.40.08](./README.assets/iShot_2025-03-23_12.40.08.png) + +## 评估 + +### 数据集 + +LightRAG使用的数据集可以从[TommyChien/UltraDomain](https://huggingface.co/datasets/TommyChien/UltraDomain)下载。 + +### 生成查询 + +LightRAG使用以下提示生成高级查询,相应的代码在`example/generate_query.py`中。 + +
+ 提示 + +```python +给定以下数据集描述: + +{description} + +请识别5个可能会使用此数据集的潜在用户。对于每个用户,列出他们会使用此数据集执行的5个任务。然后,对于每个(用户,任务)组合,生成5个需要对整个数据集有高级理解的问题。 + +按以下结构输出结果: +- 用户1:[用户描述] + - 任务1:[任务描述] + - 问题1: + - 问题2: + - 问题3: + - 问题4: + - 问题5: + - 任务2:[任务描述] + ... + - 任务5:[任务描述] +- 用户2:[用户描述] + ... +- 用户5:[用户描述] + ... +``` + +
+ +### 批量评估 + +为了评估两个RAG系统在高级查询上的性能,LightRAG使用以下提示,具体代码可在`example/batch_eval.py`中找到。 + +
+ 提示 + +```python +---角色--- +您是一位专家,负责根据三个标准评估同一问题的两个答案:**全面性**、**多样性**和**赋能性**。 +---目标--- +您将根据三个标准评估同一问题的两个答案:**全面性**、**多样性**和**赋能性**。 + +- **全面性**:答案提供了多少细节来涵盖问题的所有方面和细节? +- **多样性**:答案在提供关于问题的不同视角和见解方面有多丰富多样? +- **赋能性**:答案在多大程度上帮助读者理解并对主题做出明智判断? + +对于每个标准,选择更好的答案(答案1或答案2)并解释原因。然后,根据这三个类别选择总体赢家。 + +这是问题: +{query} + +这是两个答案: + +**答案1:** +{answer1} + +**答案2:** +{answer2} + +使用上述三个标准评估两个答案,并为每个标准提供详细解释。 + +以下列JSON格式输出您的评估: + +{{ + "全面性": {{ + "获胜者": "[答案1或答案2]", + "解释": "[在此提供解释]" + }}, + "赋能性": {{ + "获胜者": "[答案1或答案2]", + "解释": "[在此提供解释]" + }}, + "总体获胜者": {{ + "获胜者": "[答案1或答案2]", + "解释": "[根据三个标准总结为什么这个答案是总体获胜者]" + }} +}} +``` + +
+ +### 总体性能表 + +| |**农业**| |**计算机科学**| |**法律**| |**混合**| | +|----------------------|---------------|------------|------|------------|---------|------------|-------|------------| +| |NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**| +|**全面性**|32.4%|**67.6%**|38.4%|**61.6%**|16.4%|**83.6%**|38.8%|**61.2%**| +|**多样性**|23.6%|**76.4%**|38.0%|**62.0%**|13.6%|**86.4%**|32.4%|**67.6%**| +|**赋能性**|32.4%|**67.6%**|38.8%|**61.2%**|16.4%|**83.6%**|42.8%|**57.2%**| +|**总体**|32.4%|**67.6%**|38.8%|**61.2%**|15.2%|**84.8%**|40.0%|**60.0%**| +| |RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**| +|**全面性**|31.6%|**68.4%**|38.8%|**61.2%**|15.2%|**84.8%**|39.2%|**60.8%**| +|**多样性**|29.2%|**70.8%**|39.2%|**60.8%**|11.6%|**88.4%**|30.8%|**69.2%**| +|**赋能性**|31.6%|**68.4%**|36.4%|**63.6%**|15.2%|**84.8%**|42.4%|**57.6%**| +|**总体**|32.4%|**67.6%**|38.0%|**62.0%**|14.4%|**85.6%**|40.0%|**60.0%**| +| |HyDE|**LightRAG**|HyDE|**LightRAG**|HyDE|**LightRAG**|HyDE|**LightRAG**| +|**全面性**|26.0%|**74.0%**|41.6%|**58.4%**|26.8%|**73.2%**|40.4%|**59.6%**| +|**多样性**|24.0%|**76.0%**|38.8%|**61.2%**|20.0%|**80.0%**|32.4%|**67.6%**| +|**赋能性**|25.2%|**74.8%**|40.8%|**59.2%**|26.0%|**74.0%**|46.0%|**54.0%**| +|**总体**|24.8%|**75.2%**|41.6%|**58.4%**|26.4%|**73.6%**|42.4%|**57.6%**| +| |GraphRAG|**LightRAG**|GraphRAG|**LightRAG**|GraphRAG|**LightRAG**|GraphRAG|**LightRAG**| +|**全面性**|45.6%|**54.4%**|48.4%|**51.6%**|48.4%|**51.6%**|**50.4%**|49.6%| +|**多样性**|22.8%|**77.2%**|40.8%|**59.2%**|26.4%|**73.6%**|36.0%|**64.0%**| +|**赋能性**|41.2%|**58.8%**|45.2%|**54.8%**|43.6%|**56.4%**|**50.8%**|49.2%| +|**总体**|45.2%|**54.8%**|48.0%|**52.0%**|47.2%|**52.8%**|**50.4%**|49.6%| + +## 复现 + +所有代码都可以在`./reproduce`目录中找到。 + +### 步骤0 提取唯一上下文 + +首先,我们需要提取数据集中的唯一上下文。 + +
+ 代码 + +```python +def extract_unique_contexts(input_directory, output_directory): + + os.makedirs(output_directory, exist_ok=True) + + jsonl_files = glob.glob(os.path.join(input_directory, '*.jsonl')) + print(f"找到{len(jsonl_files)}个JSONL文件。") + + for file_path in jsonl_files: + filename = os.path.basename(file_path) + name, ext = os.path.splitext(filename) + output_filename = f"{name}_unique_contexts.json" + output_path = os.path.join(output_directory, output_filename) + + unique_contexts_dict = {} + + print(f"处理文件:{filename}") + + try: + with open(file_path, 'r', encoding='utf-8') as infile: + for line_number, line in enumerate(infile, start=1): + line = line.strip() + if not line: + continue + try: + json_obj = json.loads(line) + context = json_obj.get('context') + if context and context not in unique_contexts_dict: + unique_contexts_dict[context] = None + except json.JSONDecodeError as e: + print(f"文件{filename}第{line_number}行JSON解码错误:{e}") + except FileNotFoundError: + print(f"未找到文件:{filename}") + continue + except Exception as e: + print(f"处理文件{filename}时发生错误:{e}") + continue + + unique_contexts_list = list(unique_contexts_dict.keys()) + print(f"文件{filename}中有{len(unique_contexts_list)}个唯一的`context`条目。") + + try: + with open(output_path, 'w', encoding='utf-8') as outfile: + json.dump(unique_contexts_list, outfile, ensure_ascii=False, indent=4) + print(f"唯一的`context`条目已保存到:{output_filename}") + except Exception as e: + print(f"保存到文件{output_filename}时发生错误:{e}") + + print("所有文件已处理完成。") + +``` + +
+ +### 步骤1 插入上下文 + +对于提取的上下文,我们将它们插入到LightRAG系统中。 + +
+ 代码 + +```python +def insert_text(rag, file_path): + with open(file_path, mode='r') as f: + unique_contexts = json.load(f) + + retries = 0 + max_retries = 3 + while retries < max_retries: + try: + rag.insert(unique_contexts) + break + except Exception as e: + retries += 1 + print(f"插入失败,重试({retries}/{max_retries}),错误:{e}") + time.sleep(10) + if retries == max_retries: + print("超过最大重试次数后插入失败") +``` + +
+ +### 步骤2 生成查询 + +我们从数据集中每个上下文的前半部分和后半部分提取令牌,然后将它们组合为数据集描述以生成查询。 + +
+ 代码 + +```python +tokenizer = GPT2Tokenizer.from_pretrained('gpt2') + +def get_summary(context, tot_tokens=2000): + tokens = tokenizer.tokenize(context) + half_tokens = tot_tokens // 2 + + start_tokens = tokens[1000:1000 + half_tokens] + end_tokens = tokens[-(1000 + half_tokens):1000] + + summary_tokens = start_tokens + end_tokens + summary = tokenizer.convert_tokens_to_string(summary_tokens) + + return summary +``` + +
+ +### 步骤3 查询 + +对于步骤2中生成的查询,我们将提取它们并查询LightRAG。 + +
+ 代码 + +```python +def extract_queries(file_path): + with open(file_path, 'r') as f: + data = f.read() + + data = data.replace('**', '') + + queries = re.findall(r'- Question \d+: (.+)', data) + + return queries +``` + +
+ +## Star历史 + + + + + + Star History Chart + + + +## 贡献 + +感谢所有贡献者! + + + + + +## 🌟引用 + +```python +@article{guo2024lightrag, +title={LightRAG: Simple and Fast Retrieval-Augmented Generation}, +author={Zirui Guo and Lianghao Xia and Yanhua Yu and Tu Ao and Chao Huang}, +year={2024}, +eprint={2410.05779}, +archivePrefix={arXiv}, +primaryClass={cs.IR} +} +``` + +**感谢您对我们工作的关注!** diff --git a/README.assets/b2aaf634151b4706892693ffb43d9093.png b/README.assets/b2aaf634151b4706892693ffb43d9093.png new file mode 100644 index 00000000..ac387811 Binary files /dev/null and b/README.assets/b2aaf634151b4706892693ffb43d9093.png differ diff --git a/README.assets/iShot_2025-03-23_12.40.08.png b/README.assets/iShot_2025-03-23_12.40.08.png new file mode 100644 index 00000000..c4250b12 Binary files /dev/null and b/README.assets/iShot_2025-03-23_12.40.08.png differ diff --git a/README.md b/README.md index 5ff32d4c..c15c5dad 100644 --- a/README.md +++ b/README.md @@ -28,22 +28,10 @@ -
-This repository hosts the code of LightRAG. The structure of this code is based on nano-graphrag. -LightRAG Diagram -
- -
+LightRAG Diagram - - - - -
- - 🎉 News - +## 🎉 News - [X] [2025.03.18]🎯📢LightRAG now supports citation functionality. - [X] [2025.02.05]🎯📢Our team has released [VideoRAG](https://github.com/HKUDS/VideoRAG) understanding extremely long-context videos. @@ -63,8 +51,6 @@ This repository hosts the code of LightRAG. The structure of this code is based - [X] [2024.10.16]🎯📢LightRAG now supports [Ollama models](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#quick-start)! - [X] [2024.10.15]🎯📢LightRAG now supports [Hugging Face models](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#quick-start)! -
-
Algorithm Flowchart @@ -630,11 +616,11 @@ rag.insert(["TEXT1", "TEXT2",...]) rag = LightRAG( working_dir=WORKING_DIR, addon_params={ - "insert_batch_size": 20 # Process 20 documents per batch + "insert_batch_size": 4 # Process 4 documents per batch } ) -rag.insert(["TEXT1", "TEXT2", "TEXT3", ...]) # Documents will be processed in batches of 20 +rag.insert(["TEXT1", "TEXT2", "TEXT3", ...]) # Documents will be processed in batches of 4 ``` The `insert_batch_size` parameter in `addon_params` controls how many documents are processed in each batch during insertion. This is useful for: @@ -1081,33 +1067,33 @@ Valid modes are:
Parameters -| **Parameter** | **Type** | **Explanation** | **Default** | -| -------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -| **working\_dir** | `str` | Directory where the cache will be stored | `lightrag_cache+timestamp` | -| **kv\_storage** | `str` | Storage type for documents and text chunks. Supported types:`JsonKVStorage`, `OracleKVStorage` | `JsonKVStorage` | -| **vector\_storage** | `str` | Storage type for embedding vectors. Supported types:`NanoVectorDBStorage`, `OracleVectorDBStorage` | `NanoVectorDBStorage` | -| **graph\_storage** | `str` | Storage type for graph edges and nodes. Supported types:`NetworkXStorage`, `Neo4JStorage`, `OracleGraphStorage` | `NetworkXStorage` | -| **chunk\_token\_size** | `int` | Maximum token size per chunk when splitting documents | `1200` | -| **chunk\_overlap\_token\_size** | `int` | Overlap token size between two chunks when splitting documents | `100` | -| **tiktoken\_model\_name** | `str` | Model name for the Tiktoken encoder used to calculate token numbers | `gpt-4o-mini` | -| **entity\_extract\_max\_gleaning** | `int` | Number of loops in the entity extraction process, appending history messages | `1` | -| **entity\_summary\_to\_max\_tokens** | `int` | Maximum token size for each entity summary | `500` | -| **node\_embedding\_algorithm** | `str` | Algorithm for node embedding (currently not used) | `node2vec` | -| **node2vec\_params** | `dict` | Parameters for node embedding | `{"dimensions": 1536,"num_walks": 10,"walk_length": 40,"window_size": 2,"iterations": 3,"random_seed": 3,}` | -| **embedding\_func** | `EmbeddingFunc` | Function to generate embedding vectors from text | `openai_embed` | -| **embedding\_batch\_num** | `int` | Maximum batch size for embedding processes (multiple texts sent per batch) | `32` | -| **embedding\_func\_max\_async** | `int` | Maximum number of concurrent asynchronous embedding processes | `16` | -| **llm\_model\_func** | `callable` | Function for LLM generation | `gpt_4o_mini_complete` | -| **llm\_model\_name** | `str` | LLM model name for generation | `meta-llama/Llama-3.2-1B-Instruct` | -| **llm\_model\_max\_token\_size** | `int` | Maximum token size for LLM generation (affects entity relation summaries) | `32768`(default value changed by env var MAX_TOKENS) | -| **llm\_model\_max\_async** | `int` | Maximum number of concurrent asynchronous LLM processes | `4`(default value changed by env var MAX_ASYNC) | -| **llm\_model\_kwargs** | `dict` | Additional parameters for LLM generation | | -| **vector\_db\_storage\_cls\_kwargs** | `dict` | Additional parameters for vector database, like setting the threshold for nodes and relations retrieval. | cosine_better_than_threshold: 0.2(default value changed by env var COSINE_THRESHOLD) | -| **enable\_llm\_cache** | `bool` | If `TRUE`, stores LLM results in cache; repeated prompts return cached responses | `TRUE` | -| **enable\_llm\_cache\_for\_entity\_extract** | `bool` | If `TRUE`, stores LLM results in cache for entity extraction; Good for beginners to debug your application | `TRUE` | -| **addon\_params** | `dict` | Additional parameters, e.g.,`{"example_number": 1, "language": "Simplified Chinese", "entity_types": ["organization", "person", "geo", "event"], "insert_batch_size": 10}`: sets example limit, output language, and batch size for document processing | `example_number: all examples, language: English, insert_batch_size: 10` | -| **convert\_response\_to\_json\_func** | `callable` | Not used | `convert_response_to_json` | -| **embedding\_cache\_config** | `dict` | Configuration for question-answer caching. Contains three parameters:`
`- `enabled`: Boolean value to enable/disable cache lookup functionality. When enabled, the system will check cached responses before generating new answers.`
`- `similarity_threshold`: Float value (0-1), similarity threshold. When a new question's similarity with a cached question exceeds this threshold, the cached answer will be returned directly without calling the LLM.`
`- `use_llm_check`: Boolean value to enable/disable LLM similarity verification. When enabled, LLM will be used as a secondary check to verify the similarity between questions before returning cached answers. | Default:`{"enabled": False, "similarity_threshold": 0.95, "use_llm_check": False}` | +| **Parameter** | **Type** | **Explanation** | **Default** | +|--------------|----------|-----------------|-------------| +| **working_dir** | `str` | Directory where the cache will be stored | `lightrag_cache+timestamp` | +| **kv_storage** | `str` | Storage type for documents and text chunks. Supported types: `JsonKVStorage`, `OracleKVStorage` | `JsonKVStorage` | +| **vector_storage** | `str` | Storage type for embedding vectors. Supported types: `NanoVectorDBStorage`, `OracleVectorDBStorage` | `NanoVectorDBStorage` | +| **graph_storage** | `str` | Storage type for graph edges and nodes. Supported types: `NetworkXStorage`, `Neo4JStorage`, `OracleGraphStorage` | `NetworkXStorage` | +| **chunk_token_size** | `int` | Maximum token size per chunk when splitting documents | `1200` | +| **chunk_overlap_token_size** | `int` | Overlap token size between two chunks when splitting documents | `100` | +| **tiktoken_model_name** | `str` | Model name for the Tiktoken encoder used to calculate token numbers | `gpt-4o-mini` | +| **entity_extract_max_gleaning** | `int` | Number of loops in the entity extraction process, appending history messages | `1` | +| **entity_summary_to_max_tokens** | `int` | Maximum token size for each entity summary | `500` | +| **node_embedding_algorithm** | `str` | Algorithm for node embedding (currently not used) | `node2vec` | +| **node2vec_params** | `dict` | Parameters for node embedding | `{"dimensions": 1536,"num_walks": 10,"walk_length": 40,"window_size": 2,"iterations": 3,"random_seed": 3,}` | +| **embedding_func** | `EmbeddingFunc` | Function to generate embedding vectors from text | `openai_embed` | +| **embedding_batch_num** | `int` | Maximum batch size for embedding processes (multiple texts sent per batch) | `32` | +| **embedding_func_max_async** | `int` | Maximum number of concurrent asynchronous embedding processes | `16` | +| **llm_model_func** | `callable` | Function for LLM generation | `gpt_4o_mini_complete` | +| **llm_model_name** | `str` | LLM model name for generation | `meta-llama/Llama-3.2-1B-Instruct` | +| **llm_model_max_token_size** | `int` | Maximum token size for LLM generation (affects entity relation summaries) | `32768`(default value changed by env var MAX_TOKENS) | +| **llm_model_max_async** | `int` | Maximum number of concurrent asynchronous LLM processes | `4`(default value changed by env var MAX_ASYNC) | +| **llm_model_kwargs** | `dict` | Additional parameters for LLM generation | | +| **vector_db_storage_cls_kwargs** | `dict` | Additional parameters for vector database, like setting the threshold for nodes and relations retrieval | cosine_better_than_threshold: 0.2(default value changed by env var COSINE_THRESHOLD) | +| **enable_llm_cache** | `bool` | If `TRUE`, stores LLM results in cache; repeated prompts return cached responses | `TRUE` | +| **enable_llm_cache_for_entity_extract** | `bool` | If `TRUE`, stores LLM results in cache for entity extraction; Good for beginners to debug your application | `TRUE` | +| **addon_params** | `dict` | Additional parameters, e.g., `{"example_number": 1, "language": "Simplified Chinese", "entity_types": ["organization", "person", "geo", "event"], "insert_batch_size": 10}`: sets example limit, output language, and batch size for document processing | `example_number: all examples, language: English, insert_batch_size: 10` | +| **convert_response_to_json_func** | `callable` | Not used | `convert_response_to_json` | +| **embedding_cache_config** | `dict` | Configuration for question-answer caching. Contains three parameters: `enabled`: Boolean value to enable/disable cache lookup functionality. When enabled, the system will check cached responses before generating new answers. `similarity_threshold`: Float value (0-1), similarity threshold. When a new question's similarity with a cached question exceeds this threshold, the cached answer will be returned directly without calling the LLM. `use_llm_check`: Boolean value to enable/disable LLM similarity verification. When enabled, LLM will be used as a secondary check to verify the similarity between questions before returning cached answers. | Default: `{"enabled": False, "similarity_threshold": 0.95, "use_llm_check": False}` |
@@ -1132,166 +1118,9 @@ LightRag can be installed with API support to serve a Fast api interface to perf ## Graph Visualization -
- Graph visualization with html +The LightRAG Server offers a comprehensive knowledge graph visualization feature. It supports various gravity layouts, node queries, subgraph filtering, and more. **For more information about LightRAG Server, please refer to [LightRAG Server](./lightrag/api/README.md).** -* The following code can be found in `examples/graph_visual_with_html.py` - -```python -import networkx as nx -from pyvis.network import Network - -# Load the GraphML file -G = nx.read_graphml('./dickens/graph_chunk_entity_relation.graphml') - -# Create a Pyvis network -net = Network(notebook=True) - -# Convert NetworkX graph to Pyvis network -net.from_nx(G) - -# Save and display the network -net.show('knowledge_graph.html') -``` - -
- -
- Graph visualization with Neo4 - -* The following code can be found in `examples/graph_visual_with_neo4j.py` - -```python -import os -import json -from lightrag.utils import xml_to_json -from neo4j import GraphDatabase - -# Constants -WORKING_DIR = "./dickens" -BATCH_SIZE_NODES = 500 -BATCH_SIZE_EDGES = 100 - -# Neo4j connection credentials -NEO4J_URI = "bolt://localhost:7687" -NEO4J_USERNAME = "neo4j" -NEO4J_PASSWORD = "your_password" - -def convert_xml_to_json(xml_path, output_path): - """Converts XML file to JSON and saves the output.""" - if not os.path.exists(xml_path): - print(f"Error: File not found - {xml_path}") - return None - - json_data = xml_to_json(xml_path) - if json_data: - with open(output_path, 'w', encoding='utf-8') as f: - json.dump(json_data, f, ensure_ascii=False, indent=2) - print(f"JSON file created: {output_path}") - return json_data - else: - print("Failed to create JSON data") - return None - -def process_in_batches(tx, query, data, batch_size): - """Process data in batches and execute the given query.""" - for i in range(0, len(data), batch_size): - batch = data[i:i + batch_size] - tx.run(query, {"nodes": batch} if "nodes" in query else {"edges": batch}) - -def main(): - # Paths - xml_file = os.path.join(WORKING_DIR, 'graph_chunk_entity_relation.graphml') - json_file = os.path.join(WORKING_DIR, 'graph_data.json') - - # Convert XML to JSON - json_data = convert_xml_to_json(xml_file, json_file) - if json_data is None: - return - - # Load nodes and edges - nodes = json_data.get('nodes', []) - edges = json_data.get('edges', []) - - # Neo4j queries - create_nodes_query = """ - UNWIND $nodes AS node - MERGE (e:Entity {id: node.id}) - SET e.entity_type = node.entity_type, - e.description = node.description, - e.source_id = node.source_id, - e.displayName = node.id - REMOVE e:Entity - WITH e, node - CALL apoc.create.addLabels(e, [node.entity_type]) YIELD node AS labeledNode - RETURN count(*) - """ - - create_edges_query = """ - UNWIND $edges AS edge - MATCH (source {id: edge.source}) - MATCH (target {id: edge.target}) - WITH source, target, edge, - CASE - WHEN edge.keywords CONTAINS 'lead' THEN 'lead' - WHEN edge.keywords CONTAINS 'participate' THEN 'participate' - WHEN edge.keywords CONTAINS 'uses' THEN 'uses' - WHEN edge.keywords CONTAINS 'located' THEN 'located' - WHEN edge.keywords CONTAINS 'occurs' THEN 'occurs' - ELSE REPLACE(SPLIT(edge.keywords, ',')[0], '\"', '') - END AS relType - CALL apoc.create.relationship(source, relType, { - weight: edge.weight, - description: edge.description, - keywords: edge.keywords, - source_id: edge.source_id - }, target) YIELD rel - RETURN count(*) - """ - - set_displayname_and_labels_query = """ - MATCH (n) - SET n.displayName = n.id - WITH n - CALL apoc.create.setLabels(n, [n.entity_type]) YIELD node - RETURN count(*) - """ - - # Create a Neo4j driver - driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD)) - - try: - # Execute queries in batches - with driver.session() as session: - # Insert nodes in batches - session.execute_write(process_in_batches, create_nodes_query, nodes, BATCH_SIZE_NODES) - - # Insert edges in batches - session.execute_write(process_in_batches, create_edges_query, edges, BATCH_SIZE_EDGES) - - # Set displayName and labels - session.run(set_displayname_and_labels_query) - - except Exception as e: - print(f"Error occurred: {e}") - - finally: - driver.close() - -if __name__ == "__main__": - main() -``` - -
- -
- Graphml 3d visualizer - -LightRag can be installed with Tools support to add extra tools like the graphml 3d visualizer. - -[LightRag Visualizer](lightrag/tools/lightrag_visualizer/README.md) - -
+![iShot_2025-03-23_12.40.08](./README.assets/iShot_2025-03-23_12.40.08.png) ## Evaluation @@ -1386,28 +1215,28 @@ Output your evaluation in the following JSON format: ### Overall Performance Table -| | **Agriculture** | | **CS** | | **Legal** | | **Mix** | | -| --------------------------- | --------------------- | ------------------ | ------------ | ------------------ | --------------- | ------------------ | --------------- | ------------------ | -| | NaiveRAG | **LightRAG** | NaiveRAG | **LightRAG** | NaiveRAG | **LightRAG** | NaiveRAG | **LightRAG** | -| **Comprehensiveness** | 32.4% | **67.6%** | 38.4% | **61.6%** | 16.4% | **83.6%** | 38.8% | **61.2%** | -| **Diversity** | 23.6% | **76.4%** | 38.0% | **62.0%** | 13.6% | **86.4%** | 32.4% | **67.6%** | -| **Empowerment** | 32.4% | **67.6%** | 38.8% | **61.2%** | 16.4% | **83.6%** | 42.8% | **57.2%** | -| **Overall** | 32.4% | **67.6%** | 38.8% | **61.2%** | 15.2% | **84.8%** | 40.0% | **60.0%** | -| | RQ-RAG | **LightRAG** | RQ-RAG | **LightRAG** | RQ-RAG | **LightRAG** | RQ-RAG | **LightRAG** | -| **Comprehensiveness** | 31.6% | **68.4%** | 38.8% | **61.2%** | 15.2% | **84.8%** | 39.2% | **60.8%** | -| **Diversity** | 29.2% | **70.8%** | 39.2% | **60.8%** | 11.6% | **88.4%** | 30.8% | **69.2%** | -| **Empowerment** | 31.6% | **68.4%** | 36.4% | **63.6%** | 15.2% | **84.8%** | 42.4% | **57.6%** | -| **Overall** | 32.4% | **67.6%** | 38.0% | **62.0%** | 14.4% | **85.6%** | 40.0% | **60.0%** | -| | HyDE | **LightRAG** | HyDE | **LightRAG** | HyDE | **LightRAG** | HyDE | **LightRAG** | -| **Comprehensiveness** | 26.0% | **74.0%** | 41.6% | **58.4%** | 26.8% | **73.2%** | 40.4% | **59.6%** | -| **Diversity** | 24.0% | **76.0%** | 38.8% | **61.2%** | 20.0% | **80.0%** | 32.4% | **67.6%** | -| **Empowerment** | 25.2% | **74.8%** | 40.8% | **59.2%** | 26.0% | **74.0%** | 46.0% | **54.0%** | -| **Overall** | 24.8% | **75.2%** | 41.6% | **58.4%** | 26.4% | **73.6%** | 42.4% | **57.6%** | -| | GraphRAG | **LightRAG** | GraphRAG | **LightRAG** | GraphRAG | **LightRAG** | GraphRAG | **LightRAG** | -| **Comprehensiveness** | 45.6% | **54.4%** | 48.4% | **51.6%** | 48.4% | **51.6%** | **50.4%** | 49.6% | -| **Diversity** | 22.8% | **77.2%** | 40.8% | **59.2%** | 26.4% | **73.6%** | 36.0% | **64.0%** | -| **Empowerment** | 41.2% | **58.8%** | 45.2% | **54.8%** | 43.6% | **56.4%** | **50.8%** | 49.2% | -| **Overall** | 45.2% | **54.8%** | 48.0% | **52.0%** | 47.2% | **52.8%** | **50.4%** | 49.6% | +| |**Agriculture**| |**CS**| |**Legal**| |**Mix**| | +|----------------------|---------------|------------|------|------------|---------|------------|-------|------------| +| |NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**|NaiveRAG|**LightRAG**| +|**Comprehensiveness**|32.4%|**67.6%**|38.4%|**61.6%**|16.4%|**83.6%**|38.8%|**61.2%**| +|**Diversity**|23.6%|**76.4%**|38.0%|**62.0%**|13.6%|**86.4%**|32.4%|**67.6%**| +|**Empowerment**|32.4%|**67.6%**|38.8%|**61.2%**|16.4%|**83.6%**|42.8%|**57.2%**| +|**Overall**|32.4%|**67.6%**|38.8%|**61.2%**|15.2%|**84.8%**|40.0%|**60.0%**| +| |RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**|RQ-RAG|**LightRAG**| +|**Comprehensiveness**|31.6%|**68.4%**|38.8%|**61.2%**|15.2%|**84.8%**|39.2%|**60.8%**| +|**Diversity**|29.2%|**70.8%**|39.2%|**60.8%**|11.6%|**88.4%**|30.8%|**69.2%**| +|**Empowerment**|31.6%|**68.4%**|36.4%|**63.6%**|15.2%|**84.8%**|42.4%|**57.6%**| +|**Overall**|32.4%|**67.6%**|38.0%|**62.0%**|14.4%|**85.6%**|40.0%|**60.0%**| +| |HyDE|**LightRAG**|HyDE|**LightRAG**|HyDE|**LightRAG**|HyDE|**LightRAG**| +|**Comprehensiveness**|26.0%|**74.0%**|41.6%|**58.4%**|26.8%|**73.2%**|40.4%|**59.6%**| +|**Diversity**|24.0%|**76.0%**|38.8%|**61.2%**|20.0%|**80.0%**|32.4%|**67.6%**| +|**Empowerment**|25.2%|**74.8%**|40.8%|**59.2%**|26.0%|**74.0%**|46.0%|**54.0%**| +|**Overall**|24.8%|**75.2%**|41.6%|**58.4%**|26.4%|**73.6%**|42.4%|**57.6%**| +| |GraphRAG|**LightRAG**|GraphRAG|**LightRAG**|GraphRAG|**LightRAG**|GraphRAG|**LightRAG**| +|**Comprehensiveness**|45.6%|**54.4%**|48.4%|**51.6%**|48.4%|**51.6%**|**50.4%**|49.6%| +|**Diversity**|22.8%|**77.2%**|40.8%|**59.2%**|26.4%|**73.6%**|36.0%|**64.0%**| +|**Empowerment**|41.2%|**58.8%**|45.2%|**54.8%**|43.6%|**56.4%**|**50.8%**|49.2%| +|**Overall**|45.2%|**54.8%**|48.0%|**52.0%**|47.2%|**52.8%**|**50.4%**|49.6%| ## Reproduce diff --git a/env.example b/env.example index f2a1020e..d23f0107 100644 --- a/env.example +++ b/env.example @@ -13,9 +13,6 @@ # SSL_CERTFILE=/path/to/cert.pem # SSL_KEYFILE=/path/to/key.pem -### Security (empty for no api-key is needed) -# LIGHTRAG_API_KEY=your-secure-api-key-here - ### Directory Configuration # WORKING_DIR= # INPUT_DIR= @@ -39,21 +36,23 @@ # MAX_TOKEN_ENTITY_DESC=4000 ### Settings for document indexing -# SUMMARY_LANGUAGE=English +ENABLE_LLM_CACHE_FOR_EXTRACT=true # Enable LLM cache for entity extraction +SUMMARY_LANGUAGE=English # CHUNK_SIZE=1200 # CHUNK_OVERLAP_SIZE=100 # MAX_TOKEN_SUMMARY=500 # Max tokens for entity or relations summary # MAX_PARALLEL_INSERT=2 # Number of parallel processing documents in one patch -# MAX_ASYNC=4 # Max concurrency requests of LLM -# ENABLE_LLM_CACHE_FOR_EXTRACT=true # Enable LLM cache for entity extraction # EMBEDDING_BATCH_NUM=32 # num of chunks send to Embedding in one request # EMBEDDING_FUNC_MAX_ASYNC=16 # Max concurrency requests for Embedding # MAX_EMBED_TOKENS=8192 ### LLM Configuration (Use valid host. For local services installed with docker, you can use host.docker.internal) -# MAX_TOKENS=32768 # Max tokens send to LLM (less than context size of the model) -# TIMEOUT=150 # Time out in seconds for LLM, None for infinite timeout +TIMEOUT=150 # Time out in seconds for LLM, None for infinite timeout +TEMPERATURE=0.5 +MAX_ASYNC=4 # Max concurrency requests of LLM +MAX_TOKENS=32768 # Max tokens send to LLM (less than context size of the model) + LLM_BINDING=ollama LLM_MODEL=mistral-nemo:latest LLM_BINDING_API_KEY=your_api_key @@ -163,4 +162,7 @@ AUTH_USERNAME=admin # login name AUTH_PASSWORD=admin123 # password TOKEN_SECRET=your-key-for-LightRAG-API-Server # JWT key TOKEN_EXPIRE_HOURS=4 # expire duration -WHITELIST_PATHS=/login,/health # white list + +### API-Key to access LightRAG Server API +# LIGHTRAG_API_KEY=your-secure-api-key-here +# WHITELIST_PATHS=/health,/api/* diff --git a/lightrag/__init__.py b/lightrag/__init__.py index b5ed66b5..9ffbac2a 100644 --- a/lightrag/__init__.py +++ b/lightrag/__init__.py @@ -1,5 +1,5 @@ from .lightrag import LightRAG as LightRAG, QueryParam as QueryParam -__version__ = "1.2.8" +__version__ = "1.2.9" __author__ = "Zirui Guo" __url__ = "https://github.com/HKUDS/LightRAG" diff --git a/lightrag/api/README-zh.md b/lightrag/api/README-zh.md new file mode 100644 index 00000000..839aa2ef --- /dev/null +++ b/lightrag/api/README-zh.md @@ -0,0 +1,559 @@ +# LightRAG 服务器和 Web 界面 + +LightRAG 服务器旨在提供 Web 界面和 API 支持。Web 界面便于文档索引、知识图谱探索和简单的 RAG 查询界面。LightRAG 服务器还提供了与 Ollama 兼容的接口,旨在将 LightRAG 模拟为 Ollama 聊天模型。这使得 AI 聊天机器人(如 Open WebUI)可以轻松访问 LightRAG。 + +![image-20250323122538997](./README.assets/image-20250323122538997.png) + +![image-20250323122754387](./README.assets/image-20250323122754387.png) + +![image-20250323123011220](./README.assets/image-20250323123011220.png) + +## 入门指南 + +### 安装 + +* 从 PyPI 安装 + +```bash +pip install "lightrag-hku[api]" +``` + +* 从源代码安装 + +```bash +# 克隆仓库 +git clone https://github.com/HKUDS/lightrag.git + +# 切换到仓库目录 +cd lightrag + +# 如有必要,创建 Python 虚拟环境 +# 以可编辑模式安装并支持 API +pip install -e ".[api]" +``` + +### 启动 LightRAG 服务器前的准备 + +LightRAG 需要同时集成 LLM(大型语言模型)和嵌入模型以有效执行文档索引和查询操作。在首次部署 LightRAG 服务器之前,必须配置 LLM 和嵌入模型的设置。LightRAG 支持绑定到各种 LLM/嵌入后端: + +* ollama +* lollms +* openai 或 openai 兼容 +* azure_openai + +建议使用环境变量来配置 LightRAG 服务器。项目根目录中有一个名为 `env.example` 的示例环境变量文件。请将此文件复制到启动目录并重命名为 `.env`。之后,您可以在 `.env` 文件中修改与 LLM 和嵌入模型相关的参数。需要注意的是,LightRAG 服务器每次启动时都会将 `.env` 中的环境变量加载到系统环境变量中。由于 LightRAG 服务器会优先使用系统环境变量中的设置,如果您在通过命令行启动 LightRAG 服务器后修改了 `.env` 文件,则需要执行 `source .env` 使新设置生效。 + +以下是 LLM 和嵌入模型的一些常见设置示例: + +* OpenAI LLM + Ollama 嵌入 + +``` +LLM_BINDING=openai +LLM_MODEL=gpt-4o +LLM_BINDING_HOST=https://api.openai.com/v1 +LLM_BINDING_API_KEY=your_api_key +MAX_TOKENS=32768 # 发送给 LLM 的最大 token 数(小于模型上下文大小) + +EMBEDDING_BINDING=ollama +EMBEDDING_BINDING_HOST=http://localhost:11434 +EMBEDDING_MODEL=bge-m3:latest +EMBEDDING_DIM=1024 +# EMBEDDING_BINDING_API_KEY=your_api_key +``` + +* Ollama LLM + Ollama 嵌入 + +``` +LLM_BINDING=ollama +LLM_MODEL=mistral-nemo:latest +LLM_BINDING_HOST=http://localhost:11434 +# LLM_BINDING_API_KEY=your_api_key +MAX_TOKENS=8192 # 发送给 LLM 的最大 token 数(基于您的 Ollama 服务器容量) + +EMBEDDING_BINDING=ollama +EMBEDDING_BINDING_HOST=http://localhost:11434 +EMBEDDING_MODEL=bge-m3:latest +EMBEDDING_DIM=1024 +# EMBEDDING_BINDING_API_KEY=your_api_key +``` + +### 启动 LightRAG 服务器 + +LightRAG 服务器支持两种运行模式: +* 简单高效的 Uvicorn 模式 + +``` +lightrag-server +``` +* 多进程 Gunicorn + Uvicorn 模式(生产模式,不支持 Windows 环境) + +``` +lightrag-gunicorn --workers 4 +``` +`.env` 文件必须放在启动目录中。启动时,LightRAG 服务器将创建一个文档目录(默认为 `./inputs`)和一个数据目录(默认为 `./rag_storage`)。这允许您从不同目录启动多个 LightRAG 服务器实例,每个实例配置为监听不同的网络端口。 + +以下是一些常用的启动参数: + +- `--host`:服务器监听地址(默认:0.0.0.0) +- `--port`:服务器监听端口(默认:9621) +- `--timeout`:LLM 请求超时时间(默认:150 秒) +- `--log-level`:日志级别(默认:INFO) +- --input-dir:指定要扫描文档的目录(默认:./input) + +### 启动时自动扫描 + +当使用 `--auto-scan-at-startup` 参数启动任何服务器时,系统将自动: + +1. 扫描输入目录中的新文件 +2. 为尚未在数据库中的新文档建立索引 +3. 使所有内容立即可用于 RAG 查询 + +> `--input-dir` 参数指定要扫描的输入目录。您可以从 webui 触发输入目录扫描。 + +### Gunicorn + Uvicorn 的多工作进程 + +LightRAG 服务器可以在 `Gunicorn + Uvicorn` 预加载模式下运行。Gunicorn 的多工作进程(多进程)功能可以防止文档索引任务阻塞 RAG 查询。使用 CPU 密集型文档提取工具(如 docling)在纯 Uvicorn 模式下可能会导致整个系统被阻塞。 + +虽然 LightRAG 服务器使用一个工作进程来处理文档索引流程,但通过 Uvicorn 的异步任务支持,可以并行处理多个文件。文档索引速度的瓶颈主要在于 LLM。如果您的 LLM 支持高并发,您可以通过增加 LLM 的并发级别来加速文档索引。以下是几个与并发处理相关的环境变量及其默认值: + +``` +WORKERS=2 # 工作进程数,不大于 (2 x 核心数) + 1 +MAX_PARALLEL_INSERT=2 # 一批中并行处理的文件数 +MAX_ASYNC=4 # LLM 的最大并发请求数 +``` + +### 将 Lightrag 安装为 Linux 服务 + +从示例文件 `lightrag.sevice.example` 创建您的服务文件 `lightrag.sevice`。修改服务文件中的 WorkingDirectory 和 ExecStart: + +```text +Description=LightRAG Ollama Service +WorkingDirectory= +ExecStart=/lightrag/api/lightrag-api +``` + +修改您的服务启动脚本:`lightrag-api`。根据需要更改 python 虚拟环境激活命令: + +```shell +#!/bin/bash + +# 您的 python 虚拟环境激活命令 +source /home/netman/lightrag-xyj/venv/bin/activate +# 启动 lightrag api 服务器 +lightrag-server +``` + +安装 LightRAG 服务。如果您的系统是 Ubuntu,以下命令将生效: + +```shell +sudo cp lightrag.service /etc/systemd/system/ +sudo systemctl daemon-reload +sudo systemctl start lightrag.service +sudo systemctl status lightrag.service +sudo systemctl enable lightrag.service +``` + +## Ollama 模拟 + +我们为 LightRAG 提供了 Ollama 兼容接口,旨在将 LightRAG 模拟为 Ollama 聊天模型。这使得支持 Ollama 的 AI 聊天前端(如 Open WebUI)可以轻松访问 LightRAG。 + +### 将 Open WebUI 连接到 LightRAG + +启动 lightrag-server 后,您可以在 Open WebUI 管理面板中添加 Ollama 类型的连接。然后,一个名为 lightrag:latest 的模型将出现在 Open WebUI 的模型管理界面中。用户随后可以通过聊天界面向 LightRAG 发送查询。对于这种用例,最好将 LightRAG 安装为服务。 + +Open WebUI 使用 LLM 来执行会话标题和会话关键词生成任务。因此,Ollama 聊天补全 API 会检测并将 OpenWebUI 会话相关请求直接转发给底层 LLM。Open WebUI 的截图: + +![image-20250323194750379](./README.assets/image-20250323194750379.png) + +### 在聊天中选择查询模式 + +查询字符串中的查询前缀可以决定使用哪种 LightRAG 查询模式来生成响应。支持的前缀包括: + +``` +/local +/global +/hybrid +/naive +/mix +/bypass +``` + +例如,聊天消息 "/mix 唐僧有几个徒弟" 将触发 LightRAG 的混合模式查询。没有查询前缀的聊天消息默认会触发混合模式查询。 + +"/bypass" 不是 LightRAG 查询模式,它会告诉 API 服务器将查询连同聊天历史直接传递给底层 LLM。因此用户可以使用 LLM 基于聊天历史回答问题。如果您使用 Open WebUI 作为前端,您可以直接切换到普通 LLM 模型,而不是使用 /bypass 前缀。 + +## API 密钥和认证 + +默认情况下,LightRAG 服务器可以在没有任何认证的情况下访问。我们可以使用 API 密钥或账户凭证配置服务器以确保其安全。 + +* API 密钥 + +``` +LIGHTRAG_API_KEY=your-secure-api-key-here +WHITELIST_PATHS=/health,/api/* +``` + +> 健康检查和 Ollama 模拟端点默认不进行 API 密钥检查。 + +* 账户凭证(Web 界面需要登录后才能访问) + +LightRAG API 服务器使用基于 HS256 算法的 JWT 认证。要启用安全访问控制,需要以下环境变量: + +```bash +# JWT 认证 +AUTH_USERNAME=admin # 登录名 +AUTH_PASSWORD=admin123 # 密码 +TOKEN_SECRET=your-key # JWT 密钥 +TOKEN_EXPIRE_HOURS=4 # 过期时间 +``` + +> 目前仅支持配置一个管理员账户和密码。尚未开发和实现完整的账户系统。 + +如果未配置账户凭证,Web 界面将以访客身份访问系统。因此,即使仅配置了 API 密钥,所有 API 仍然可以通过访客账户访问,这仍然不安全。因此,要保护 API,需要同时配置这两种认证方法。 + +## Azure OpenAI 后端配置 + +可以使用以下 Azure CLI 命令创建 Azure OpenAI API(您需要先从 [https://docs.microsoft.com/en-us/cli/azure/install-azure-cli](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) 安装 Azure CLI): + +```bash +# 根据需要更改资源组名称、位置和 OpenAI 资源名称 +RESOURCE_GROUP_NAME=LightRAG +LOCATION=swedencentral +RESOURCE_NAME=LightRAG-OpenAI + +az login +az group create --name $RESOURCE_GROUP_NAME --location $LOCATION +az cognitiveservices account create --name $RESOURCE_NAME --resource-group $RESOURCE_GROUP_NAME --kind OpenAI --sku S0 --location swedencentral +az cognitiveservices account deployment create --resource-group $RESOURCE_GROUP_NAME --model-format OpenAI --name $RESOURCE_NAME --deployment-name gpt-4o --model-name gpt-4o --model-version "2024-08-06" --sku-capacity 100 --sku-name "Standard" +az cognitiveservices account deployment create --resource-group $RESOURCE_GROUP_NAME --model-format OpenAI --name $RESOURCE_NAME --deployment-name text-embedding-3-large --model-name text-embedding-3-large --model-version "1" --sku-capacity 80 --sku-name "Standard" +az cognitiveservices account show --name $RESOURCE_NAME --resource-group $RESOURCE_GROUP_NAME --query "properties.endpoint" +az cognitiveservices account keys list --name $RESOURCE_NAME -g $RESOURCE_GROUP_NAME +``` + +最后一个命令的输出将提供 OpenAI API 的端点和密钥。您可以使用这些值在 `.env` 文件中设置环境变量。 + +``` +# .env 中的 Azure OpenAI 配置 +LLM_BINDING=azure_openai +LLM_BINDING_HOST=your-azure-endpoint +LLM_MODEL=your-model-deployment-name +LLM_BINDING_API_KEY=your-azure-api-key +AZURE_OPENAI_API_VERSION=2024-08-01-preview # 可选,默认为最新版本 +EMBEDDING_BINDING=azure_openai # 如果使用 Azure OpenAI 进行嵌入 +EMBEDDING_MODEL=your-embedding-deployment-name +``` + +## LightRAG 服务器详细配置 + +API 服务器可以通过三种方式配置(优先级从高到低): + +* 命令行参数 +* 环境变量或 .env 文件 +* Config.ini(仅用于存储配置) + +大多数配置都有默认设置,详细信息请查看示例文件:`.env.example`。数据存储配置也可以通过 config.ini 设置。为方便起见,提供了示例文件 `config.ini.example`。 + +### 支持的 LLM 和嵌入后端 + +LightRAG 支持绑定到各种 LLM/嵌入后端: + +* ollama +* lollms +* openai 和 openai 兼容 +* azure_openai + +使用环境变量 `LLM_BINDING` 或 CLI 参数 `--llm-binding` 选择 LLM 后端类型。使用环境变量 `EMBEDDING_BINDING` 或 CLI 参数 `--embedding-binding` 选择嵌入后端类型。 + +### 实体提取配置 +* ENABLE_LLM_CACHE_FOR_EXTRACT:为实体提取启用 LLM 缓存(默认:true) + +在测试环境中将 `ENABLE_LLM_CACHE_FOR_EXTRACT` 设置为 true 以减少 LLM 调用成本是很常见的做法。 + +### 支持的存储类型 + +LightRAG 使用 4 种类型的存储用于不同目的: + +* KV_STORAGE:llm 响应缓存、文本块、文档信息 +* VECTOR_STORAGE:实体向量、关系向量、块向量 +* GRAPH_STORAGE:实体关系图 +* DOC_STATUS_STORAGE:文档索引状态 + +每种存储类型都有几种实现: + +* KV_STORAGE 支持的实现名称 + +``` +JsonKVStorage JsonFile(默认) +MongoKVStorage MogonDB +RedisKVStorage Redis +TiDBKVStorage TiDB +PGKVStorage Postgres +OracleKVStorage Oracle +``` + +* GRAPH_STORAGE 支持的实现名称 + +``` +NetworkXStorage NetworkX(默认) +Neo4JStorage Neo4J +MongoGraphStorage MongoDB +TiDBGraphStorage TiDB +AGEStorage AGE +GremlinStorage Gremlin +PGGraphStorage Postgres +OracleGraphStorage Postgres +``` + +* VECTOR_STORAGE 支持的实现名称 + +``` +NanoVectorDBStorage NanoVector(默认) +MilvusVectorDBStorge Milvus +ChromaVectorDBStorage Chroma +TiDBVectorDBStorage TiDB +PGVectorStorage Postgres +FaissVectorDBStorage Faiss +QdrantVectorDBStorage Qdrant +OracleVectorDBStorage Oracle +MongoVectorDBStorage MongoDB +``` + +* DOC_STATUS_STORAGE 支持的实现名称 + +``` +JsonDocStatusStorage JsonFile(默认) +PGDocStatusStorage Postgres +MongoDocStatusStorage MongoDB +``` + +### 如何选择存储实现 + +您可以通过环境变量选择存储实现。在首次启动 API 服务器之前,您可以将以下环境变量设置为特定的存储实现名称: + +``` +LIGHTRAG_KV_STORAGE=PGKVStorage +LIGHTRAG_VECTOR_STORAGE=PGVectorStorage +LIGHTRAG_GRAPH_STORAGE=PGGraphStorage +LIGHTRAG_DOC_STATUS_STORAGE=PGDocStatusStorage +``` + +在向 LightRAG 添加文档后,您不能更改存储实现选择。目前尚不支持从一个存储实现迁移到另一个存储实现。更多信息请阅读示例 env 文件或 config.ini 文件。 + +### LightRag API 服务器命令行选项 + +| 参数 | 默认值 | 描述 | +|-----------|---------|-------------| +| --host | 0.0.0.0 | 服务器主机 | +| --port | 9621 | 服务器端口 | +| --working-dir | ./rag_storage | RAG 存储的工作目录 | +| --input-dir | ./inputs | 包含输入文档的目录 | +| --max-async | 4 | 最大异步操作数 | +| --max-tokens | 32768 | 最大 token 大小 | +| --timeout | 150 | 超时时间(秒)。None 表示无限超时(不推荐) | +| --log-level | INFO | 日志级别(DEBUG、INFO、WARNING、ERROR、CRITICAL) | +| --verbose | - | 详细调试输出(True、False) | +| --key | None | 用于认证的 API 密钥。保护 lightrag 服务器免受未授权访问 | +| --ssl | False | 启用 HTTPS | +| --ssl-certfile | None | SSL 证书文件路径(如果启用 --ssl 则必需) | +| --ssl-keyfile | None | SSL 私钥文件路径(如果启用 --ssl 则必需) | +| --top-k | 50 | 要检索的 top-k 项目数;在"local"模式下对应实体,在"global"模式下对应关系。 | +| --cosine-threshold | 0.4 | 节点和关系检索的余弦阈值,与 top-k 一起控制节点和关系的检索。 | +| --llm-binding | ollama | LLM 绑定类型(lollms、ollama、openai、openai-ollama、azure_openai) | +| --embedding-binding | ollama | 嵌入绑定类型(lollms、ollama、openai、azure_openai) | +| auto-scan-at-startup | - | 扫描输入目录中的新文件并开始索引 | + +### 使用示例 + +#### 使用 ollama 默认本地服务器作为 llm 和嵌入后端运行 Lightrag 服务器 + +Ollama 是 llm 和嵌入的默认后端,因此默认情况下您可以不带参数运行 lightrag-server,将使用默认值。确保已安装 ollama 并且正在运行,且默认模型已安装在 ollama 上。 + +```bash +# 使用 ollama 运行 lightrag,llm 使用 mistral-nemo:latest,嵌入使用 bge-m3:latest +lightrag-server + +# 使用认证密钥 +lightrag-server --key my-key +``` + +#### 使用 lollms 默认本地服务器作为 llm 和嵌入后端运行 Lightrag 服务器 + +```bash +# 使用 lollms 运行 lightrag,llm 使用 mistral-nemo:latest,嵌入使用 bge-m3:latest +# 在 .env 或 config.ini 中配置 LLM_BINDING=lollms 和 EMBEDDING_BINDING=lollms +lightrag-server + +# 使用认证密钥 +lightrag-server --key my-key +``` + +#### 使用 openai 服务器作为 llm 和嵌入后端运行 Lightrag 服务器 + +```bash +# 使用 openai 运行 lightrag,llm 使用 GPT-4o-mini,嵌入使用 text-embedding-3-small +# 在 .env 或 config.ini 中配置: +# LLM_BINDING=openai +# LLM_MODEL=GPT-4o-mini +# EMBEDDING_BINDING=openai +# EMBEDDING_MODEL=text-embedding-3-small +lightrag-server + +# 使用认证密钥 +lightrag-server --key my-key +``` + +#### 使用 azure openai 服务器作为 llm 和嵌入后端运行 Lightrag 服务器 + +```bash +# 使用 azure_openai 运行 lightrag +# 在 .env 或 config.ini 中配置: +# LLM_BINDING=azure_openai +# LLM_MODEL=your-model +# EMBEDDING_BINDING=azure_openai +# EMBEDDING_MODEL=your-embedding-model +lightrag-server + +# 使用认证密钥 +lightrag-server --key my-key +``` + +**重要说明:** +- 对于 LoLLMs:确保指定的模型已安装在您的 LoLLMs 实例中 +- 对于 Ollama:确保指定的模型已安装在您的 Ollama 实例中 +- 对于 OpenAI:确保您已设置 OPENAI_API_KEY 环境变量 +- 对于 Azure OpenAI:按照先决条件部分所述构建和配置您的服务器 + +要获取任何服务器的帮助,使用 --help 标志: +```bash +lightrag-server --help +``` + +注意:如果您不需要 API 功能,可以使用以下命令安装不带 API 支持的基本包: +```bash +pip install lightrag-hku +``` + +## API 端点 + +所有服务器(LoLLMs、Ollama、OpenAI 和 Azure OpenAI)都为 RAG 功能提供相同的 REST API 端点。当 API 服务器运行时,访问: + +- Swagger UI:http://localhost:9621/docs +- ReDoc:http://localhost:9621/redoc + +您可以使用提供的 curl 命令或通过 Swagger UI 界面测试 API 端点。确保: + +1. 启动适当的后端服务(LoLLMs、Ollama 或 OpenAI) +2. 启动 RAG 服务器 +3. 使用文档管理端点上传一些文档 +4. 使用查询端点查询系统 +5. 如果在输入目录中放入新文件,触发文档扫描 + +### 查询端点 + +#### POST /query +使用不同搜索模式查询 RAG 系统。 + +```bash +curl -X POST "http://localhost:9621/query" \ + -H "Content-Type: application/json" \ + -d '{"query": "您的问题", "mode": "hybrid", ""}' +``` + +#### POST /query/stream +从 RAG 系统流式获取响应。 + +```bash +curl -X POST "http://localhost:9621/query/stream" \ + -H "Content-Type: application/json" \ + -d '{"query": "您的问题", "mode": "hybrid"}' +``` + +### 文档管理端点 + +#### POST /documents/text +直接将文本插入 RAG 系统。 + +```bash +curl -X POST "http://localhost:9621/documents/text" \ + -H "Content-Type: application/json" \ + -d '{"text": "您的文本内容", "description": "可选描述"}' +``` + +#### POST /documents/file +向 RAG 系统上传单个文件。 + +```bash +curl -X POST "http://localhost:9621/documents/file" \ + -F "file=@/path/to/your/document.txt" \ + -F "description=可选描述" +``` + +#### POST /documents/batch +一次上传多个文件。 + +```bash +curl -X POST "http://localhost:9621/documents/batch" \ + -F "files=@/path/to/doc1.txt" \ + -F "files=@/path/to/doc2.txt" +``` + +#### POST /documents/scan + +触发输入目录中新文件的文档扫描。 + +```bash +curl -X POST "http://localhost:9621/documents/scan" --max-time 1800 +``` + +> 根据所有新文件的预计索引时间调整 max-time。 + +#### DELETE /documents + +从 RAG 系统中清除所有文档。 + +```bash +curl -X DELETE "http://localhost:9621/documents" +``` + +### Ollama 模拟端点 + +#### GET /api/version + +获取 Ollama 版本信息。 + +```bash +curl http://localhost:9621/api/version +``` + +#### GET /api/tags + +获取 Ollama 可用模型。 + +```bash +curl http://localhost:9621/api/tags +``` + +#### POST /api/chat + +处理聊天补全请求。通过根据查询前缀选择查询模式将用户查询路由到 LightRAG。检测并将 OpenWebUI 会话相关请求(用于元数据生成任务)直接转发给底层 LLM。 + +```shell +curl -N -X POST http://localhost:9621/api/chat -H "Content-Type: application/json" -d \ + '{"model":"lightrag:latest","messages":[{"role":"user","content":"猪八戒是谁"}],"stream":true}' +``` + +> 有关 Ollama API 的更多信息,请访问:[Ollama API 文档](https://github.com/ollama/ollama/blob/main/docs/api.md) + +#### POST /api/generate + +处理生成补全请求。为了兼容性目的,该请求不由 LightRAG 处理,而是由底层 LLM 模型处理。 + +### 实用工具端点 + +#### GET /health +检查服务器健康状况和配置。 + +```bash +curl "http://localhost:9621/health" + +``` diff --git a/lightrag/api/README.md b/lightrag/api/README.md index 04fcdaf8..e042fd46 100644 --- a/lightrag/api/README.md +++ b/lightrag/api/README.md @@ -153,10 +153,6 @@ sudo systemctl status lightrag.service sudo systemctl enable lightrag.service ``` - - - - ## Ollama Emulation We provide an Ollama-compatible interfaces for LightRAG, aiming to emulate LightRAG as an Ollama chat model. This allows AI chat frontends supporting Ollama, such as Open WebUI, to access LightRAG easily. @@ -196,8 +192,11 @@ By default, the LightRAG Server can be accessed without any authentication. We c ``` LIGHTRAG_API_KEY=your-secure-api-key-here +WHITELIST_PATHS=/health,/api/* ``` +> Health check and Ollama emuluation endpoins is exclude from API-KEY check by default. + * Account credentials (the web UI requires login before access) LightRAG API Server implements JWT-based authentication using HS256 algorithm. To enable secure access control, the following environment variables are required: diff --git a/lightrag/api/__init__.py b/lightrag/api/__init__.py index 005c738a..972fb714 100644 --- a/lightrag/api/__init__.py +++ b/lightrag/api/__init__.py @@ -1 +1 @@ -__api_version__ = "1.2.2" +__api_version__ = "1.2.5" diff --git a/lightrag/api/lightrag_server.py b/lightrag/api/lightrag_server.py index 584d020f..570221f4 100644 --- a/lightrag/api/lightrag_server.py +++ b/lightrag/api/lightrag_server.py @@ -18,7 +18,7 @@ from fastapi.middleware.cors import CORSMiddleware from contextlib import asynccontextmanager from dotenv import load_dotenv from lightrag.api.utils_api import ( - get_api_key_dependency, + get_combined_auth_dependency, parse_args, get_default_host, display_splash_screen, @@ -41,7 +41,6 @@ from lightrag.kg.shared_storage import ( get_namespace_data, get_pipeline_status_lock, initialize_pipeline_status, - get_all_update_flags_status, ) from fastapi.security import OAuth2PasswordRequestForm from .auth import auth_handler @@ -136,19 +135,28 @@ def create_app(args): await rag.finalize_storages() # Initialize FastAPI - app = FastAPI( - title="LightRAG API", - description="API for querying text using LightRAG with separate storage and input directories" + app_kwargs = { + "title": "LightRAG Server API", + "description": "Providing API for LightRAG core, Web UI and Ollama Model Emulation" + "(With authentication)" if api_key else "", - version=__api_version__, - openapi_url="/openapi.json", # Explicitly set OpenAPI schema URL - docs_url="/docs", # Explicitly set docs URL - redoc_url="/redoc", # Explicitly set redoc URL - openapi_tags=[{"name": "api"}], - lifespan=lifespan, - ) + "version": __api_version__, + "openapi_url": "/openapi.json", # Explicitly set OpenAPI schema URL + "docs_url": "/docs", # Explicitly set docs URL + "redoc_url": "/redoc", # Explicitly set redoc URL + "openapi_tags": [{"name": "api"}], + "lifespan": lifespan, + } + + # Configure Swagger UI parameters + # Enable persistAuthorization and tryItOutEnabled for better user experience + app_kwargs["swagger_ui_parameters"] = { + "persistAuthorization": True, + "tryItOutEnabled": True, + } + + app = FastAPI(**app_kwargs) def get_cors_origins(): """Get allowed origins from environment variable @@ -168,8 +176,8 @@ def create_app(args): allow_headers=["*"], ) - # Create the optional API key dependency - optional_api_key = get_api_key_dependency(api_key) + # Create combined auth dependency for all endpoints + combined_auth = get_combined_auth_dependency(api_key) # Create working directory if it doesn't exist Path(args.working_dir).mkdir(parents=True, exist_ok=True) @@ -200,6 +208,7 @@ def create_app(args): kwargs["response_format"] = GPTKeywordExtractionFormat if history_messages is None: history_messages = [] + kwargs["temperature"] = args.temperature return await openai_complete_if_cache( args.llm_model, prompt, @@ -222,6 +231,7 @@ def create_app(args): kwargs["response_format"] = GPTKeywordExtractionFormat if history_messages is None: history_messages = [] + kwargs["temperature"] = args.temperature return await azure_openai_complete_if_cache( args.llm_model, prompt, @@ -302,6 +312,7 @@ def create_app(args): }, namespace_prefix=args.namespace_prefix, auto_manage_storages_states=False, + max_parallel_insert=args.max_parallel_insert, ) else: # azure_openai rag = LightRAG( @@ -331,6 +342,7 @@ def create_app(args): }, namespace_prefix=args.namespace_prefix, auto_manage_storages_states=False, + max_parallel_insert=args.max_parallel_insert, ) # Add routes @@ -339,7 +351,7 @@ def create_app(args): app.include_router(create_graph_routes(rag, api_key)) # Add Ollama API routes - ollama_api = OllamaAPI(rag, top_k=args.top_k) + ollama_api = OllamaAPI(rag, top_k=args.top_k, api_key=api_key) app.include_router(ollama_api.router, prefix="/api") @app.get("/") @@ -347,7 +359,7 @@ def create_app(args): """Redirect root path to /webui""" return RedirectResponse(url="/webui") - @app.get("/auth-status", dependencies=[Depends(optional_api_key)]) + @app.get("/auth-status") async def get_auth_status(): """Get authentication status and guest token if auth is not configured""" username = os.getenv("AUTH_USERNAME") @@ -375,7 +387,7 @@ def create_app(args): "api_version": __api_version__, } - @app.post("/login", dependencies=[Depends(optional_api_key)]) + @app.post("/login") async def login(form_data: OAuth2PasswordRequestForm = Depends()): username = os.getenv("AUTH_USERNAME") password = os.getenv("AUTH_PASSWORD") @@ -411,12 +423,9 @@ def create_app(args): "api_version": __api_version__, } - @app.get("/health", dependencies=[Depends(optional_api_key)]) + @app.get("/health", dependencies=[Depends(combined_auth)]) async def get_status(): """Get current system status""" - # Get update flags status for all namespaces - update_status = await get_all_update_flags_status() - username = os.getenv("AUTH_USERNAME") password = os.getenv("AUTH_PASSWORD") if not (username and password): @@ -444,7 +453,6 @@ def create_app(args): "vector_storage": args.vector_storage, "enable_llm_cache_for_extract": args.enable_llm_cache_for_extract, }, - "update_status": update_status, "core_version": core_version, "api_version": __api_version__, "auth_mode": auth_mode, diff --git a/lightrag/api/routers/document_routes.py b/lightrag/api/routers/document_routes.py index e0c8f545..e2284c11 100644 --- a/lightrag/api/routers/document_routes.py +++ b/lightrag/api/routers/document_routes.py @@ -17,15 +17,13 @@ from pydantic import BaseModel, Field, field_validator from lightrag import LightRAG from lightrag.base import DocProcessingStatus, DocStatus from lightrag.api.utils_api import ( - get_api_key_dependency, + get_combined_auth_dependency, global_args, - get_auth_dependency, ) router = APIRouter( prefix="/documents", tags=["documents"], - dependencies=[Depends(get_auth_dependency())], ) # Temporary file prefix @@ -113,6 +111,7 @@ class PipelineStatusResponse(BaseModel): request_pending: Flag for pending request for processing latest_message: Latest message from pipeline processing history_messages: List of history messages + update_status: Status of update flags for all namespaces """ autoscanned: bool = False @@ -125,6 +124,7 @@ class PipelineStatusResponse(BaseModel): request_pending: bool = False latest_message: str = "" history_messages: Optional[List[str]] = None + update_status: Optional[dict] = None class Config: extra = "allow" # Allow additional fields from the pipeline status @@ -475,8 +475,8 @@ async def run_scanning_process(rag: LightRAG, doc_manager: DocumentManager): if not new_files: return - # Get MAX_PARALLEL_INSERT from global_args - max_parallel = global_args["max_parallel_insert"] + # Get MAX_PARALLEL_INSERT from global_args["main_args"] + max_parallel = global_args["main_args"].max_parallel_insert # Calculate batch size as 2 * MAX_PARALLEL_INSERT batch_size = 2 * max_parallel @@ -505,9 +505,10 @@ async def run_scanning_process(rag: LightRAG, doc_manager: DocumentManager): def create_document_routes( rag: LightRAG, doc_manager: DocumentManager, api_key: Optional[str] = None ): - optional_api_key = get_api_key_dependency(api_key) + # Create combined auth dependency for document routes + combined_auth = get_combined_auth_dependency(api_key) - @router.post("/scan", dependencies=[Depends(optional_api_key)]) + @router.post("/scan", dependencies=[Depends(combined_auth)]) async def scan_for_new_documents(background_tasks: BackgroundTasks): """ Trigger the scanning process for new documents. @@ -523,7 +524,7 @@ def create_document_routes( background_tasks.add_task(run_scanning_process, rag, doc_manager) return {"status": "scanning_started"} - @router.post("/upload", dependencies=[Depends(optional_api_key)]) + @router.post("/upload", dependencies=[Depends(combined_auth)]) async def upload_to_input_dir( background_tasks: BackgroundTasks, file: UploadFile = File(...) ): @@ -568,7 +569,7 @@ def create_document_routes( raise HTTPException(status_code=500, detail=str(e)) @router.post( - "/text", response_model=InsertResponse, dependencies=[Depends(optional_api_key)] + "/text", response_model=InsertResponse, dependencies=[Depends(combined_auth)] ) async def insert_text( request: InsertTextRequest, background_tasks: BackgroundTasks @@ -603,7 +604,7 @@ def create_document_routes( @router.post( "/texts", response_model=InsertResponse, - dependencies=[Depends(optional_api_key)], + dependencies=[Depends(combined_auth)], ) async def insert_texts( request: InsertTextsRequest, background_tasks: BackgroundTasks @@ -636,7 +637,7 @@ def create_document_routes( raise HTTPException(status_code=500, detail=str(e)) @router.post( - "/file", response_model=InsertResponse, dependencies=[Depends(optional_api_key)] + "/file", response_model=InsertResponse, dependencies=[Depends(combined_auth)] ) async def insert_file( background_tasks: BackgroundTasks, file: UploadFile = File(...) @@ -681,7 +682,7 @@ def create_document_routes( @router.post( "/file_batch", response_model=InsertResponse, - dependencies=[Depends(optional_api_key)], + dependencies=[Depends(combined_auth)], ) async def insert_batch( background_tasks: BackgroundTasks, files: List[UploadFile] = File(...) @@ -742,7 +743,7 @@ def create_document_routes( raise HTTPException(status_code=500, detail=str(e)) @router.delete( - "", response_model=InsertResponse, dependencies=[Depends(optional_api_key)] + "", response_model=InsertResponse, dependencies=[Depends(combined_auth)] ) async def clear_documents(): """ @@ -771,7 +772,7 @@ def create_document_routes( @router.get( "/pipeline_status", - dependencies=[Depends(optional_api_key)], + dependencies=[Depends(combined_auth)], response_model=PipelineStatusResponse, ) async def get_pipeline_status() -> PipelineStatusResponse: @@ -798,13 +799,34 @@ def create_document_routes( HTTPException: If an error occurs while retrieving pipeline status (500) """ try: - from lightrag.kg.shared_storage import get_namespace_data + from lightrag.kg.shared_storage import ( + get_namespace_data, + get_all_update_flags_status, + ) pipeline_status = await get_namespace_data("pipeline_status") + # Get update flags status for all namespaces + update_status = await get_all_update_flags_status() + + # Convert MutableBoolean objects to regular boolean values + processed_update_status = {} + for namespace, flags in update_status.items(): + processed_flags = [] + for flag in flags: + # Handle both multiprocess and single process cases + if hasattr(flag, "value"): + processed_flags.append(bool(flag.value)) + else: + processed_flags.append(bool(flag)) + processed_update_status[namespace] = processed_flags + # Convert to regular dict if it's a Manager.dict status_dict = dict(pipeline_status) + # Add processed update_status to the status dictionary + status_dict["update_status"] = processed_update_status + # Convert history_messages to a regular list if it's a Manager.list if "history_messages" in status_dict: status_dict["history_messages"] = list(status_dict["history_messages"]) @@ -819,7 +841,7 @@ def create_document_routes( logger.error(traceback.format_exc()) raise HTTPException(status_code=500, detail=str(e)) - @router.get("", dependencies=[Depends(optional_api_key)]) + @router.get("", dependencies=[Depends(combined_auth)]) async def documents() -> DocsStatusesResponse: """ Get the status of all documents in the system. diff --git a/lightrag/api/routers/graph_routes.py b/lightrag/api/routers/graph_routes.py index 95802185..f9d77ff6 100644 --- a/lightrag/api/routers/graph_routes.py +++ b/lightrag/api/routers/graph_routes.py @@ -5,15 +5,15 @@ This module contains all graph-related routes for the LightRAG API. from typing import Optional from fastapi import APIRouter, Depends -from ..utils_api import get_api_key_dependency, get_auth_dependency +from ..utils_api import get_combined_auth_dependency -router = APIRouter(tags=["graph"], dependencies=[Depends(get_auth_dependency())]) +router = APIRouter(tags=["graph"]) def create_graph_routes(rag, api_key: Optional[str] = None): - optional_api_key = get_api_key_dependency(api_key) + combined_auth = get_combined_auth_dependency(api_key) - @router.get("/graph/label/list", dependencies=[Depends(optional_api_key)]) + @router.get("/graph/label/list", dependencies=[Depends(combined_auth)]) async def get_graph_labels(): """ Get all graph labels @@ -23,7 +23,7 @@ def create_graph_routes(rag, api_key: Optional[str] = None): """ return await rag.get_graph_labels() - @router.get("/graphs", dependencies=[Depends(optional_api_key)]) + @router.get("/graphs", dependencies=[Depends(combined_auth)]) async def get_knowledge_graph( label: str, max_depth: int = 3, min_degree: int = 0, inclusive: bool = False ): diff --git a/lightrag/api/routers/ollama_api.py b/lightrag/api/routers/ollama_api.py index 37d7354e..6d9ea8e6 100644 --- a/lightrag/api/routers/ollama_api.py +++ b/lightrag/api/routers/ollama_api.py @@ -11,7 +11,8 @@ import asyncio from ascii_colors import trace_exception from lightrag import LightRAG, QueryParam from lightrag.utils import encode_string_by_tiktoken -from lightrag.api.utils_api import ollama_server_infos +from lightrag.api.utils_api import ollama_server_infos, get_combined_auth_dependency +from fastapi import Depends # query mode according to query prefix (bypass is not LightRAG quer mode) @@ -122,20 +123,24 @@ def parse_query_mode(query: str) -> tuple[str, SearchMode]: class OllamaAPI: - def __init__(self, rag: LightRAG, top_k: int = 60): + def __init__(self, rag: LightRAG, top_k: int = 60, api_key: Optional[str] = None): self.rag = rag self.ollama_server_infos = ollama_server_infos self.top_k = top_k + self.api_key = api_key self.router = APIRouter(tags=["ollama"]) self.setup_routes() def setup_routes(self): - @self.router.get("/version") + # Create combined auth dependency for Ollama API routes + combined_auth = get_combined_auth_dependency(self.api_key) + + @self.router.get("/version", dependencies=[Depends(combined_auth)]) async def get_version(): """Get Ollama version information""" return OllamaVersionResponse(version="0.5.4") - @self.router.get("/tags") + @self.router.get("/tags", dependencies=[Depends(combined_auth)]) async def get_tags(): """Return available models acting as an Ollama server""" return OllamaTagResponse( @@ -158,7 +163,7 @@ class OllamaAPI: ] ) - @self.router.post("/generate") + @self.router.post("/generate", dependencies=[Depends(combined_auth)]) async def generate(raw_request: Request, request: OllamaGenerateRequest): """Handle generate completion requests acting as an Ollama model For compatibility purpose, the request is not processed by LightRAG, @@ -324,7 +329,7 @@ class OllamaAPI: trace_exception(e) raise HTTPException(status_code=500, detail=str(e)) - @self.router.post("/chat") + @self.router.post("/chat", dependencies=[Depends(combined_auth)]) async def chat(raw_request: Request, request: OllamaChatRequest): """Process chat completion requests acting as an Ollama model Routes user queries through LightRAG by selecting query mode based on prefix indicators. diff --git a/lightrag/api/routers/query_routes.py b/lightrag/api/routers/query_routes.py index 7a5bd8c3..c9648356 100644 --- a/lightrag/api/routers/query_routes.py +++ b/lightrag/api/routers/query_routes.py @@ -8,12 +8,12 @@ from typing import Any, Dict, List, Literal, Optional from fastapi import APIRouter, Depends, HTTPException from lightrag.base import QueryParam -from ..utils_api import get_api_key_dependency, get_auth_dependency +from ..utils_api import get_combined_auth_dependency from pydantic import BaseModel, Field, field_validator from ascii_colors import trace_exception -router = APIRouter(tags=["query"], dependencies=[Depends(get_auth_dependency())]) +router = APIRouter(tags=["query"]) class QueryRequest(BaseModel): @@ -139,10 +139,10 @@ class QueryResponse(BaseModel): def create_query_routes(rag, api_key: Optional[str] = None, top_k: int = 60): - optional_api_key = get_api_key_dependency(api_key) + combined_auth = get_combined_auth_dependency(api_key) @router.post( - "/query", response_model=QueryResponse, dependencies=[Depends(optional_api_key)] + "/query", response_model=QueryResponse, dependencies=[Depends(combined_auth)] ) async def query_text(request: QueryRequest): """ @@ -176,7 +176,7 @@ def create_query_routes(rag, api_key: Optional[str] = None, top_k: int = 60): trace_exception(e) raise HTTPException(status_code=500, detail=str(e)) - @router.post("/query/stream", dependencies=[Depends(optional_api_key)]) + @router.post("/query/stream", dependencies=[Depends(combined_auth)]) async def query_text_stream(request: QueryRequest): """ This endpoint performs a retrieval-augmented generation (RAG) query and streams the response. diff --git a/lightrag/api/utils_api.py b/lightrag/api/utils_api.py index 25136bd2..cb391174 100644 --- a/lightrag/api/utils_api.py +++ b/lightrag/api/utils_api.py @@ -4,22 +4,44 @@ Utility functions for the LightRAG API. import os import argparse -from typing import Optional +from typing import Optional, List, Tuple import sys import logging from ascii_colors import ASCIIColors from lightrag.api import __api_version__ -from fastapi import HTTPException, Security, Depends, Request, status +from fastapi import HTTPException, Security, Request, status from dotenv import load_dotenv from fastapi.security import APIKeyHeader, OAuth2PasswordBearer from starlette.status import HTTP_403_FORBIDDEN from .auth import auth_handler +from ..prompt import PROMPTS # Load environment variables load_dotenv() global_args = {"main_args": None} +# Get whitelist paths from environment variable, only once during initialization +default_whitelist = "/health,/api/*" +whitelist_paths = os.getenv("WHITELIST_PATHS", default_whitelist).split(",") + +# Pre-compile path matching patterns +whitelist_patterns: List[Tuple[str, bool]] = [] +for path in whitelist_paths: + path = path.strip() + if path: + # If path ends with /*, match all paths with that prefix + if path.endswith("/*"): + prefix = path[:-2] + whitelist_patterns.append((prefix, True)) # (prefix, is_prefix_match) + else: + whitelist_patterns.append((path, False)) # (exact_path, is_prefix_match) + +# Global authentication configuration +auth_username = os.getenv("AUTH_USERNAME") +auth_password = os.getenv("AUTH_PASSWORD") +auth_configured = bool(auth_username and auth_password) + class OllamaServerInfos: # Constants for emulated Ollama model information @@ -34,49 +56,114 @@ class OllamaServerInfos: ollama_server_infos = OllamaServerInfos() -def get_auth_dependency(): - # Set default whitelist paths - whitelist = os.getenv("WHITELIST_PATHS", "/login,/health").split(",") +def get_combined_auth_dependency(api_key: Optional[str] = None): + """ + Create a combined authentication dependency that implements authentication logic + based on API key, OAuth2 token, and whitelist paths. - async def dependency( - request: Request, - token: str = Depends(OAuth2PasswordBearer(tokenUrl="login", auto_error=False)), - ): - # Check if authentication is configured - auth_configured = bool( - os.getenv("AUTH_USERNAME") and os.getenv("AUTH_PASSWORD") + Args: + api_key (Optional[str]): API key for validation + + Returns: + Callable: A dependency function that implements the authentication logic + """ + # Use global whitelist_patterns and auth_configured variables + # whitelist_patterns and auth_configured are already initialized at module level + + # Only calculate api_key_configured as it depends on the function parameter + api_key_configured = bool(api_key) + + # Create security dependencies with proper descriptions for Swagger UI + oauth2_scheme = OAuth2PasswordBearer( + tokenUrl="login", auto_error=False, description="OAuth2 Password Authentication" + ) + + # If API key is configured, create an API key header security + api_key_header = None + if api_key_configured: + api_key_header = APIKeyHeader( + name="X-API-Key", auto_error=False, description="API Key Authentication" ) - # If authentication is not configured, skip all validation - if not auth_configured: - return + async def combined_dependency( + request: Request, + token: str = Security(oauth2_scheme), + api_key_header_value: Optional[str] = None + if api_key_header is None + else Security(api_key_header), + ): + # 1. Check if path is in whitelist + path = request.url.path + for pattern, is_prefix in whitelist_patterns: + if (is_prefix and path.startswith(pattern)) or ( + not is_prefix and path == pattern + ): + return # Whitelist path, allow access - # For configured auth, allow whitelist paths without token - if request.url.path in whitelist: - return + # 2. Validate token first if provided in the request (Ensure 401 error if token is invalid) + if token: + try: + token_info = auth_handler.validate_token(token) + # Accept guest token if no auth is configured + if not auth_configured and token_info.get("role") == "guest": + return + # Accept non-guest token if auth is configured + if auth_configured and token_info.get("role") != "guest": + return - # Require token for all other paths when auth is configured - if not token: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, detail="Token required" - ) - - try: - token_info = auth_handler.validate_token(token) - # Reject guest tokens when authentication is configured - if token_info.get("role") == "guest": + # Token validation failed, immediately return 401 error raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail="Authentication required. Guest access not allowed when authentication is configured.", + detail="Invalid token. Please login again.", ) - except Exception: + except HTTPException as e: + # If already a 401 error, re-raise it + if e.status_code == status.HTTP_401_UNAUTHORIZED: + raise + # For other exceptions, continue processing + + # 3. Acept all request if no API protection needed + if not auth_configured and not api_key_configured: + return + + # 4. Validate API key if provided and API-Key authentication is configured + if ( + api_key_configured + and api_key_header_value + and api_key_header_value == api_key + ): + return # API key validation successful + + ### Authentication failed #### + + # if password authentication is configured but not provided, ensure 401 error if auth_configured + if auth_configured and not token: raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token" + status_code=status.HTTP_401_UNAUTHORIZED, + detail="No credentials provided. Please login.", ) - return + # if api key is provided but validation failed + if api_key_header_value: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, + detail="Invalid API Key", + ) - return dependency + # if api_key_configured but not provided + if api_key_configured and not api_key_header_value: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, + detail="API Key required", + ) + + # Otherwise: refuse access and return 403 error + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, + detail="API Key required or login authentication required.", + ) + + return combined_dependency def get_api_key_dependency(api_key: Optional[str]): @@ -90,19 +177,37 @@ def get_api_key_dependency(api_key: Optional[str]): Returns: Callable: A dependency function that validates the API key. """ - if not api_key: + # Use global whitelist_patterns and auth_configured variables + # whitelist_patterns and auth_configured are already initialized at module level + + # Only calculate api_key_configured as it depends on the function parameter + api_key_configured = bool(api_key) + + if not api_key_configured: # If no API key is configured, return a dummy dependency that always succeeds - async def no_auth(): + async def no_auth(request: Request = None, **kwargs): return None return no_auth - # If API key is configured, use proper authentication + # If API key is configured, use proper authentication with Security for Swagger UI api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False) async def api_key_auth( - api_key_header_value: Optional[str] = Security(api_key_header), + request: Request, + api_key_header_value: Optional[str] = Security( + api_key_header, description="API Key for authentication" + ), ): + # Check if request path is in whitelist + path = request.url.path + for pattern, is_prefix in whitelist_patterns: + if (is_prefix and path.startswith(pattern)) or ( + not is_prefix and path == pattern + ): + return # Whitelist path, allow access + + # Non-whitelist path, validate API key if not api_key_header_value: raise HTTPException( status_code=HTTP_403_FORBIDDEN, detail="API Key required" @@ -366,7 +471,7 @@ def parse_args(is_uvicorn_mode: bool = False) -> argparse.Namespace: ) # Get MAX_PARALLEL_INSERT from environment - global_args["max_parallel_insert"] = get_env_value("MAX_PARALLEL_INSERT", 2, int) + args.max_parallel_insert = get_env_value("MAX_PARALLEL_INSERT", 2, int) # Handle openai-ollama special case if args.llm_binding == "openai-ollama": @@ -397,6 +502,9 @@ def parse_args(is_uvicorn_mode: bool = False) -> argparse.Namespace: "ENABLE_LLM_CACHE_FOR_EXTRACT", True, bool ) + # Inject LLM temperature configuration + args.temperature = get_env_value("TEMPERATURE", 0.5, float) + # Select Document loading tool (DOCLING, DEFAULT) args.document_loading_engine = get_env_value("DOCUMENT_LOADING_ENGINE", "DEFAULT") @@ -464,6 +572,12 @@ def display_splash_screen(args: argparse.Namespace) -> None: ASCIIColors.yellow(f"{args.llm_binding_host}") ASCIIColors.white(" ├─ Model: ", end="") ASCIIColors.yellow(f"{args.llm_model}") + ASCIIColors.white(" ├─ Temperature: ", end="") + ASCIIColors.yellow(f"{args.temperature}") + ASCIIColors.white(" ├─ Max Async for LLM: ", end="") + ASCIIColors.yellow(f"{args.max_async}") + ASCIIColors.white(" ├─ Max Tokens: ", end="") + ASCIIColors.yellow(f"{args.max_tokens}") ASCIIColors.white(" └─ Timeout: ", end="") ASCIIColors.yellow(f"{args.timeout if args.timeout else 'None (infinite)'}") @@ -479,13 +593,12 @@ def display_splash_screen(args: argparse.Namespace) -> None: ASCIIColors.yellow(f"{args.embedding_dim}") # RAG Configuration + summary_language = os.getenv("SUMMARY_LANGUAGE", PROMPTS["DEFAULT_LANGUAGE"]) ASCIIColors.magenta("\n⚙️ RAG Configuration:") - ASCIIColors.white(" ├─ Max Async for LLM: ", end="") - ASCIIColors.yellow(f"{args.max_async}") + ASCIIColors.white(" ├─ Summary Language: ", end="") + ASCIIColors.yellow(f"{summary_language}") ASCIIColors.white(" ├─ Max Parallel Insert: ", end="") - ASCIIColors.yellow(f"{global_args['max_parallel_insert']}") - ASCIIColors.white(" ├─ Max Tokens: ", end="") - ASCIIColors.yellow(f"{args.max_tokens}") + ASCIIColors.yellow(f"{args.max_parallel_insert}") ASCIIColors.white(" ├─ Max Embed Tokens: ", end="") ASCIIColors.yellow(f"{args.max_embed_tokens}") ASCIIColors.white(" ├─ Chunk Size: ", end="") diff --git a/lightrag/api/webui/assets/index-CJhG62dt.css b/lightrag/api/webui/assets/index-CJhG62dt.css new file mode 100644 index 00000000..54edd3f6 --- /dev/null +++ b/lightrag/api/webui/assets/index-CJhG62dt.css @@ -0,0 +1 @@ +/*! tailwindcss v4.0.14 | MIT License | https://tailwindcss.com */@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-100:oklch(.936 .032 17.717);--color-red-400:oklch(.704 .191 22.216);--color-red-500:oklch(.637 .237 25.331);--color-red-600:oklch(.577 .245 27.325);--color-red-950:oklch(.258 .092 26.042);--color-amber-100:oklch(.962 .059 95.617);--color-amber-200:oklch(.924 .12 95.746);--color-amber-700:oklch(.555 .163 48.998);--color-amber-800:oklch(.473 .137 46.201);--color-amber-900:oklch(.414 .112 45.904);--color-yellow-600:oklch(.681 .162 75.834);--color-green-500:oklch(.723 .219 149.579);--color-green-600:oklch(.627 .194 149.214);--color-emerald-50:oklch(.979 .021 166.113);--color-emerald-400:oklch(.765 .177 163.223);--color-emerald-700:oklch(.508 .118 165.612);--color-teal-100:oklch(.953 .051 180.801);--color-blue-600:oklch(.546 .245 262.881);--color-blue-700:oklch(.488 .243 264.376);--color-violet-700:oklch(.491 .27 292.581);--color-gray-100:oklch(.967 .003 264.542);--color-gray-200:oklch(.928 .006 264.531);--color-gray-300:oklch(.872 .01 258.338);--color-gray-400:oklch(.707 .022 261.325);--color-gray-500:oklch(.551 .027 264.364);--color-gray-600:oklch(.446 .03 256.802);--color-gray-700:oklch(.373 .034 259.733);--color-gray-800:oklch(.278 .033 256.848);--color-gray-900:oklch(.21 .034 264.665);--color-zinc-50:oklch(.985 0 0);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-lg:32rem;--container-xl:36rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-xs:.125rem;--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-sm:8px;--blur-lg:16px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-font-feature-settings:var(--font-sans--font-feature-settings);--default-font-variation-settings:var(--font-sans--font-variation-settings);--default-mono-font-family:var(--font-mono);--default-mono-font-feature-settings:var(--font-mono--font-feature-settings);--default-mono-font-variation-settings:var(--font-mono--font-variation-settings)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1;color:color-mix(in oklab,currentColor 50%,transparent)}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);outline-color:color-mix(in oklab,var(--ring)50%,transparent)}body{background-color:var(--background);color:var(--foreground)}*{scrollbar-color:initial;scrollbar-width:initial}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing)*2)}.top-4{top:calc(var(--spacing)*4)}.top-\[50\%\]{top:50%}.right-0{right:calc(var(--spacing)*0)}.right-2{right:calc(var(--spacing)*2)}.right-4{right:calc(var(--spacing)*4)}.bottom-0{bottom:calc(var(--spacing)*0)}.bottom-2{bottom:calc(var(--spacing)*2)}.bottom-4{bottom:calc(var(--spacing)*4)}.left-0{left:calc(var(--spacing)*0)}.left-2{left:calc(var(--spacing)*2)}.left-\[50\%\]{left:50%}.left-\[calc\(1rem\+2\.5rem\)\]{left:3.5rem}.z-10{z-index:10}.z-50{z-index:50}.z-60{z-index:60}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.\!m-0{margin:calc(var(--spacing)*0)!important}.m-0{margin:calc(var(--spacing)*0)}.-mx-1{margin-inline:calc(var(--spacing)*-1)}.mx-1{margin-inline:calc(var(--spacing)*1)}.mx-4{margin-inline:calc(var(--spacing)*4)}.my-1{margin-block:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mr-1{margin-right:calc(var(--spacing)*1)}.mr-2{margin-right:calc(var(--spacing)*2)}.mr-4{margin-right:calc(var(--spacing)*4)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\!inline{display:inline!important}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.\!size-full{width:100%!important;height:100%!important}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.size-8{width:calc(var(--spacing)*8);height:calc(var(--spacing)*8)}.size-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.size-full{width:100%;height:100%}.h-1\/2{height:50%}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-11{height:calc(var(--spacing)*11)}.h-12{height:calc(var(--spacing)*12)}.h-24{height:calc(var(--spacing)*24)}.h-52{height:calc(var(--spacing)*52)}.h-\[1px\]{height:1px}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-fit{height:fit-content}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-8{max-height:calc(var(--spacing)*8)}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-96{max-height:calc(var(--spacing)*96)}.max-h-\[60vh\]{max-height:60vh}.max-h-\[300px\]{max-height:300px}.max-h-full{max-height:100%}.min-h-0{min-height:calc(var(--spacing)*0)}.w-2\.5{width:calc(var(--spacing)*2.5)}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-7{width:calc(var(--spacing)*7)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-12{width:calc(var(--spacing)*12)}.w-16{width:calc(var(--spacing)*16)}.w-24{width:calc(var(--spacing)*24)}.w-56{width:calc(var(--spacing)*56)}.w-\[1px\]{width:1px}.w-\[200px\]{width:200px}.w-auto{width:auto}.w-full{width:100%}.w-screen{width:100vw}.max-w-80{max-width:calc(var(--spacing)*80)}.max-w-\[80\%\]{max-width:80%}.max-w-\[480px\]{max-width:480px}.max-w-lg{max-width:var(--container-lg)}.max-w-none{max-width:none}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-24{min-width:calc(var(--spacing)*24)}.min-w-\[8rem\]{min-width:8rem}.min-w-\[180px\]{min-width:180px}.min-w-\[300px\]{min-width:300px}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.caption-bottom{caption-side:bottom}.translate-x-\[-50\%\]{--tw-translate-x:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\[-50\%\]{--tw-translate-y:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-125{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x)var(--tw-scale-y)}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.\[appearance\:textfield\]{-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.place-items-center{place-items:center}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}.gap-px{gap:1px}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}.self-center{align-self:center}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.\!rounded-none{border-radius:0!important}.rounded{border-radius:.25rem}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-l-none{border-top-left-radius:0;border-bottom-left-radius:0}.rounded-tr-none{border-top-right-radius:0}.rounded-br-none{border-bottom-right-radius:0}.border,.border-1{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.\!border-none{--tw-border-style:none!important;border-style:none!important}.border-dashed{--tw-border-style:dashed;border-style:dashed}.\!border-input{border-color:var(--input)!important}.border-border\/40{border-color:color-mix(in oklab,var(--border)40%,transparent)}.border-destructive\/50{border-color:color-mix(in oklab,var(--destructive)50%,transparent)}.border-gray-400{border-color:var(--color-gray-400)}.border-input{border-color:var(--input)}.border-muted-foreground\/25{border-color:color-mix(in oklab,var(--muted-foreground)25%,transparent)}.border-muted-foreground\/50{border-color:color-mix(in oklab,var(--muted-foreground)50%,transparent)}.border-primary{border-color:var(--primary)}.border-transparent{border-color:#0000}.border-t-transparent{border-top-color:#0000}.border-l-transparent{border-left-color:#0000}.\!bg-background{background-color:var(--background)!important}.\!bg-emerald-400{background-color:var(--color-emerald-400)!important}.bg-amber-100{background-color:var(--color-amber-100)}.bg-background{background-color:var(--background)}.bg-background\/60{background-color:color-mix(in oklab,var(--background)60%,transparent)}.bg-background\/80{background-color:color-mix(in oklab,var(--background)80%,transparent)}.bg-background\/95{background-color:color-mix(in oklab,var(--background)95%,transparent)}.bg-black\/10{background-color:color-mix(in oklab,var(--color-black)10%,transparent)}.bg-black\/80{background-color:color-mix(in oklab,var(--color-black)80%,transparent)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-destructive{background-color:var(--destructive)}.bg-foreground\/10{background-color:color-mix(in oklab,var(--foreground)10%,transparent)}.bg-green-500{background-color:var(--color-green-500)}.bg-muted{background-color:var(--muted)}.bg-muted\/50{background-color:color-mix(in oklab,var(--muted)50%,transparent)}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-primary-foreground\/60{background-color:color-mix(in oklab,var(--primary-foreground)60%,transparent)}.bg-primary\/5{background-color:color-mix(in oklab,var(--primary)5%,transparent)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-500{background-color:var(--color-red-500)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-white\/30{background-color:color-mix(in oklab,var(--color-white)30%,transparent)}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-emerald-50{--tw-gradient-from:var(--color-emerald-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-teal-100{--tw-gradient-to:var(--color-teal-100);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.object-cover{object-fit:cover}.\!p-0{padding:calc(var(--spacing)*0)!important}.p-0{padding:calc(var(--spacing)*0)}.p-1{padding:calc(var(--spacing)*1)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.p-16{padding:calc(var(--spacing)*16)}.p-\[1px\]{padding:1px}.px-1{padding-inline:calc(var(--spacing)*1)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-6{padding-block:calc(var(--spacing)*6)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-6{padding-top:calc(var(--spacing)*6)}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-2{padding-right:calc(var(--spacing)*2)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pb-8{padding-bottom:calc(var(--spacing)*8)}.pb-12{padding-bottom:calc(var(--spacing)*12)}.pl-1{padding-left:calc(var(--spacing)*1)}.pl-8{padding-left:calc(var(--spacing)*8)}.text-center{text-align:center}.text-left{text-align:left}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-words{overflow-wrap:break-word}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.\!text-zinc-50{color:var(--color-zinc-50)!important}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-card-foreground{color:var(--card-foreground)}.text-current{color:currentColor}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-emerald-400{color:var(--color-emerald-400)}.text-emerald-700{color:var(--color-emerald-700)}.text-foreground{color:var(--foreground)}.text-foreground\/80{color:color-mix(in oklab,var(--foreground)80%,transparent)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-700{color:var(--color-gray-700)}.text-gray-900{color:var(--color-gray-900)}.text-green-600{color:var(--color-green-600)}.text-muted-foreground{color:var(--muted-foreground)}.text-muted-foreground\/70{color:color-mix(in oklab,var(--muted-foreground)70%,transparent)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-primary\/60{color:color-mix(in oklab,var(--primary)60%,transparent)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-violet-700{color:var(--color-violet-700)}.text-yellow-600{color:var(--color-yellow-600)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_8px_rgba\(0\,0\,0\,0\.2\)\]{--tw-shadow:0 0 8px var(--tw-shadow-color,#0003);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_12px_rgba\(34\,197\,94\,0\.4\)\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#22c55e66);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_12px_rgba\(239\,68\,68\,0\.4\)\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#ef444466);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-lg{--tw-backdrop-blur:blur(var(--blur-lg));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-2000{--tw-duration:2s;transition-duration:2s}.animate-in{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.duration-200{animation-duration:.2s}.duration-300{animation-duration:.3s}.duration-2000{animation-duration:2s}.fade-in-0{--tw-enter-opacity:0}.running{animation-play-state:running}.zoom-in-95{--tw-enter-scale:.95}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--foreground)}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}@media (hover:hover){.hover\:w-fit:hover{width:fit-content}.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-background\/60:hover{background-color:color-mix(in oklab,var(--background)60%,transparent)}.hover\:bg-destructive\/80:hover{background-color:color-mix(in oklab,var(--destructive)80%,transparent)}.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,var(--destructive)90%,transparent)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-muted\/25:hover{background-color:color-mix(in oklab,var(--muted)25%,transparent)}.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab,var(--muted)50%,transparent)}.hover\:bg-primary\/5:hover{background-color:color-mix(in oklab,var(--primary)5%,transparent)}.hover\:bg-primary\/20:hover{background-color:color-mix(in oklab,var(--primary)20%,transparent)}.hover\:bg-primary\/80:hover{background-color:color-mix(in oklab,var(--primary)80%,transparent)}.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--primary)90%,transparent)}.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--secondary)80%,transparent)}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}}.focus\:bg-accent:focus{background-color:var(--accent)}.focus\:text-accent-foreground:focus{color:var(--accent-foreground)}.focus\:ring-0:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\:ring-offset-0:focus{--tw-ring-offset-width:0px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:outline-0:focus{outline-style:var(--tw-outline-style);outline-width:0}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:relative:focus-visible{position:relative}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--ring)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\:right-0:active{right:calc(var(--spacing)*0)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\[disabled\=true\]\:opacity-50[data-disabled=true]{opacity:.5}.data-\[selected\=\'true\'\]\:bg-accent[data-selected=true]{background-color:var(--accent)}.data-\[selected\=true\]\:text-accent-foreground[data-selected=true]{color:var(--accent-foreground)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:-.5rem}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:.5rem}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:-.5rem}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:.5rem}.data-\[state\=active\]\:visible[data-state=active]{visibility:visible}.data-\[state\=active\]\:bg-background[data-state=active]{background-color:var(--background)}.data-\[state\=active\]\:text-foreground[data-state=active]{color:var(--foreground)}.data-\[state\=active\]\:shadow-sm[data-state=active]{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--primary)}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:var(--primary-foreground)}.data-\[state\=closed\]\:animate-out[data-state=closed]{--tw-exit-opacity:initial;--tw-exit-scale:initial;--tw-exit-rotate:initial;--tw-exit-translate-x:initial;--tw-exit-translate-y:initial;animation-name:exit;animation-duration:.15s}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y:-48%}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=inactive\]\:invisible[data-state=inactive]{visibility:hidden}.data-\[state\=open\]\:bg-accent[data-state=open]{background-color:var(--accent)}.data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:var(--muted-foreground)}.data-\[state\=open\]\:animate-in[data-state=open]{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity:0}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y:-48%}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale:.95}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--muted)}@supports ((-webkit-backdrop-filter:var(--tw)) or (backdrop-filter:var(--tw))){.supports-\[backdrop-filter\]\:bg-background\/60{background-color:color-mix(in oklab,var(--background)60%,transparent)}}@media (width>=40rem){.sm\:mt-0{margin-top:calc(var(--spacing)*0)}.sm\:max-w-xl{max-width:var(--container-xl)}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}:where(.sm\:space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}.sm\:rounded-lg{border-radius:var(--radius)}.sm\:px-5{padding-inline:calc(var(--spacing)*5)}.sm\:text-left{text-align:left}}@media (width>=48rem){.md\:inline-block{display:inline-block}.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.dark\:border-destructive:is(.dark *){border-color:var(--destructive)}.dark\:border-gray-600:is(.dark *){border-color:var(--color-gray-600)}.dark\:bg-amber-900:is(.dark *){background-color:var(--color-amber-900)}.dark\:bg-gray-100\/20:is(.dark *){background-color:color-mix(in oklab,var(--color-gray-100)20%,transparent)}.dark\:bg-gray-800\/30:is(.dark *){background-color:color-mix(in oklab,var(--color-gray-800)30%,transparent)}.dark\:bg-red-950:is(.dark *){background-color:var(--color-red-950)}.dark\:from-gray-900:is(.dark *){--tw-gradient-from:var(--color-gray-900);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.dark\:to-gray-800:is(.dark *){--tw-gradient-to:var(--color-gray-800);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.dark\:text-amber-200:is(.dark *){color:var(--color-amber-200)}.dark\:text-gray-300:is(.dark *){color:var(--color-gray-300)}.dark\:text-gray-400:is(.dark *){color:var(--color-gray-400)}.dark\:text-red-400:is(.dark *){color:var(--color-red-400)}@media (hover:hover){.dark\:hover\:bg-gray-700:is(.dark *):hover{background-color:var(--color-gray-700)}}.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-inline:calc(var(--spacing)*2)}.\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-block:calc(var(--spacing)*1.5)}.\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading]{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:var(--muted-foreground)}.\[\&_\[cmdk-group\]\]\:px-2 [cmdk-group]{padding-inline:calc(var(--spacing)*2)}.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden])~[cmdk-group]{padding-top:calc(var(--spacing)*0)}.\[\&_\[cmdk-input-wrapper\]_svg\]\:h-5 [cmdk-input-wrapper] svg{height:calc(var(--spacing)*5)}.\[\&_\[cmdk-input-wrapper\]_svg\]\:w-5 [cmdk-input-wrapper] svg{width:calc(var(--spacing)*5)}.\[\&_\[cmdk-input\]\]\:h-12 [cmdk-input]{height:calc(var(--spacing)*12)}.\[\&_\[cmdk-item\]\]\:px-2 [cmdk-item]{padding-inline:calc(var(--spacing)*2)}.\[\&_\[cmdk-item\]\]\:py-3 [cmdk-item]{padding-block:calc(var(--spacing)*3)}.\[\&_\[cmdk-item\]_svg\]\:h-5 [cmdk-item] svg{height:calc(var(--spacing)*5)}.\[\&_\[cmdk-item\]_svg\]\:w-5 [cmdk-item] svg{width:calc(var(--spacing)*5)}.\[\&_p\]\:leading-relaxed p{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:\:-webkit-inner-spin-button\]\:appearance-none::-webkit-inner-spin-button{-webkit-appearance:none;-moz-appearance:none;appearance:none}.\[\&\:\:-webkit-inner-spin-button\]\:opacity-100::-webkit-inner-spin-button{opacity:1}.\[\&\:\:-webkit-outer-spin-button\]\:appearance-none::-webkit-outer-spin-button{-webkit-appearance:none;-moz-appearance:none;appearance:none}.\[\&\:\:-webkit-outer-spin-button\]\:opacity-100::-webkit-outer-spin-button{opacity:1}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:calc(var(--spacing)*0)}.\[\&\>\[role\=checkbox\]\]\:translate-y-\[2px\]>[role=checkbox]{--tw-translate-y:2px;translate:var(--tw-translate-x)var(--tw-translate-y)}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\[\&\>svg\]\:absolute>svg{position:absolute}.\[\&\>svg\]\:top-4>svg{top:calc(var(--spacing)*4)}.\[\&\>svg\]\:left-4>svg{left:calc(var(--spacing)*4)}.\[\&\>svg\]\:text-destructive>svg{color:var(--destructive)}.\[\&\>svg\]\:text-foreground>svg{color:var(--foreground)}.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div{--tw-translate-y:-3px;translate:var(--tw-translate-x)var(--tw-translate-y)}.\[\&\>svg\~\*\]\:pl-7>svg~*{padding-left:calc(var(--spacing)*7)}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}:root{--background:#fff;--foreground:#09090b;--card:#fff;--card-foreground:#09090b;--popover:#fff;--popover-foreground:#09090b;--primary:#18181b;--primary-foreground:#fafafa;--secondary:#f4f4f5;--secondary-foreground:#18181b;--muted:#f4f4f5;--muted-foreground:#71717a;--accent:#f4f4f5;--accent-foreground:#18181b;--destructive:#ef4444;--destructive-foreground:#fafafa;--border:#e4e4e7;--input:#e4e4e7;--ring:#09090b;--chart-1:#e76e50;--chart-2:#2a9d90;--chart-3:#274754;--chart-4:#e8c468;--chart-5:#f4a462;--radius:.6rem;--sidebar-background:#fafafa;--sidebar-foreground:#3f3f46;--sidebar-primary:#18181b;--sidebar-primary-foreground:#fafafa;--sidebar-accent:#f4f4f5;--sidebar-accent-foreground:#18181b;--sidebar-border:#e5e7eb;--sidebar-ring:#3b82f6}.dark{--background:#09090b;--foreground:#fafafa;--card:#09090b;--card-foreground:#fafafa;--popover:#09090b;--popover-foreground:#fafafa;--primary:#fafafa;--primary-foreground:#18181b;--secondary:#27272a;--secondary-foreground:#fafafa;--muted:#27272a;--muted-foreground:#a1a1aa;--accent:#27272a;--accent-foreground:#fafafa;--destructive:#7f1d1d;--destructive-foreground:#fafafa;--border:#27272a;--input:#27272a;--ring:#d4d4d8;--chart-1:#2662d9;--chart-2:#2eb88a;--chart-3:#e88c30;--chart-4:#af57db;--chart-5:#e23670;--sidebar-background:#18181b;--sidebar-foreground:#f4f4f5;--sidebar-primary:#1d4ed8;--sidebar-primary-foreground:#fff;--sidebar-accent:#27272a;--sidebar-accent-foreground:#f4f4f5;--sidebar-border:#27272a;--sidebar-ring:#3b82f6}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background-color:#ccc;border-radius:5px}::-webkit-scrollbar-track{background-color:#f2f2f2}.dark ::-webkit-scrollbar-thumb{background-color:#e6e6e6}.dark ::-webkit-scrollbar-track{background-color:#000}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0))}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}:root{--sigma-background-color:#fff;--sigma-controls-background-color:#fff;--sigma-controls-background-color-hover:rgba(0,0,0,.2);--sigma-controls-border-color:rgba(0,0,0,.2);--sigma-controls-color:#000;--sigma-controls-zindex:100;--sigma-controls-margin:5px;--sigma-controls-size:30px}div.react-sigma{height:100%;width:100%;position:relative;background:var(--sigma-background-color)}div.sigma-container{height:100%;width:100%}.react-sigma-controls{position:absolute;z-index:var(--sigma-controls-zindex);border:2px solid var(--sigma-controls-border-color);border-radius:4px;color:var(--sigma-controls-color);background-color:var(--sigma-controls-background-color)}.react-sigma-controls.bottom-right{bottom:var(--sigma-controls-margin);right:var(--sigma-controls-margin)}.react-sigma-controls.bottom-left{bottom:var(--sigma-controls-margin);left:var(--sigma-controls-margin)}.react-sigma-controls.top-right{top:var(--sigma-controls-margin);right:var(--sigma-controls-margin)}.react-sigma-controls.top-left{top:var(--sigma-controls-margin);left:var(--sigma-controls-margin)}.react-sigma-controls:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.react-sigma-controls:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.react-sigma-control{width:var(--sigma-controls-size);height:var(--sigma-controls-size);line-height:var(--sigma-controls-size);background-color:var(--sigma-controls-background-color);border-bottom:1px solid var(--sigma-controls-border-color)}.react-sigma-control:last-child{border-bottom:none}.react-sigma-control>*{box-sizing:border-box}.react-sigma-control>button{display:block;border:none;margin:0;padding:0;width:var(--sigma-controls-size);height:var(--sigma-controls-size);line-height:var(--sigma-controls-size);background-position:center;background-size:50%;background-repeat:no-repeat;background-color:var(--sigma-controls-background-color);clip:rect(0,0,0,0)}.react-sigma-control>button:hover{background-color:var(--sigma-controls-background-color-hover)}.react-sigma-search{background-color:var(--sigma-controls-background-color)}.react-sigma-search label{visibility:hidden}.react-sigma-search input{color:var(--sigma-controls-color);background-color:var(--sigma-controls-background-color);font-size:1em;width:100%;margin:0;border:none;padding:var(--sigma-controls-margin);box-sizing:border-box}:root{--sigma-grey-color:#ccc}.react-sigma .option.hoverable{cursor:pointer!important}.react-sigma .text-ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.react-sigma .react-select__clear-indicator{cursor:pointer!important}.react-sigma .text-muted{color:var(--sigma-grey-color)}.react-sigma .text-italic{font-style:italic}.react-sigma .text-center{text-align:center}.react-sigma .graph-search{min-width:250px}.react-sigma .graph-search .option{padding:2px 8px}.react-sigma .graph-search .dropdown-indicator{font-size:1.25em;padding:4px}.react-sigma .graph-search .option.selected{background-color:var(--sigma-grey-color)}.react-sigma .node .render{position:relative;display:inline-block;width:1em;height:1em;border-radius:1em;background-color:var(--sigma-grey-color);margin-right:8px}.react-sigma .node{display:flex;flex-direction:row;align-items:center}.react-sigma .node .render{flex-grow:0;flex-shrink:0;margin-right:0 .25em}.react-sigma .node .label{flex-grow:1;flex-shrink:1}.react-sigma .edge{display:flex;flex-direction:column;align-items:flex-start;flex-grow:0;flex-shrink:0;flex-wrap:nowrap}.react-sigma .edge .node{font-size:.7em}.react-sigma .edge .body{display:flex;flex-direction:row;flex-grow:1;flex-shrink:1;min-height:.6em}.react-sigma .edge .body .render{display:flex;flex-direction:column;margin:0 2px}.react-sigma .edge .body .render .dash,.react-sigma .edge .body .render .dotted{display:inline-block;width:0;margin:0 2px;border:2px solid #ccc;flex-grow:1;flex-shrink:1}.react-sigma .edge .body .render .dotted{border-style:dotted}.react-sigma .edge .body .render .arrow{width:0;height:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.6em solid red;flex-shrink:0;flex-grow:0;border-left-width:.3em;border-right-width:.3em}.react-sigma .edge .body .label{flex-grow:1;flex-shrink:1;text-align:center} diff --git a/lightrag/api/webui/assets/index-Cq65VeVX.css b/lightrag/api/webui/assets/index-Cq65VeVX.css deleted file mode 100644 index da1d0bef..00000000 --- a/lightrag/api/webui/assets/index-Cq65VeVX.css +++ /dev/null @@ -1 +0,0 @@ -/*! tailwindcss v4.0.14 | MIT License | https://tailwindcss.com */@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-100:oklch(.936 .032 17.717);--color-red-400:oklch(.704 .191 22.216);--color-red-500:oklch(.637 .237 25.331);--color-red-600:oklch(.577 .245 27.325);--color-red-700:oklch(.505 .213 27.518);--color-red-950:oklch(.258 .092 26.042);--color-amber-100:oklch(.962 .059 95.617);--color-amber-200:oklch(.924 .12 95.746);--color-amber-700:oklch(.555 .163 48.998);--color-amber-800:oklch(.473 .137 46.201);--color-amber-900:oklch(.414 .112 45.904);--color-yellow-600:oklch(.681 .162 75.834);--color-green-500:oklch(.723 .219 149.579);--color-green-600:oklch(.627 .194 149.214);--color-emerald-50:oklch(.979 .021 166.113);--color-emerald-400:oklch(.765 .177 163.223);--color-emerald-700:oklch(.508 .118 165.612);--color-teal-100:oklch(.953 .051 180.801);--color-blue-600:oklch(.546 .245 262.881);--color-blue-700:oklch(.488 .243 264.376);--color-violet-700:oklch(.491 .27 292.581);--color-gray-100:oklch(.967 .003 264.542);--color-gray-200:oklch(.928 .006 264.531);--color-gray-300:oklch(.872 .01 258.338);--color-gray-400:oklch(.707 .022 261.325);--color-gray-500:oklch(.551 .027 264.364);--color-gray-600:oklch(.446 .03 256.802);--color-gray-700:oklch(.373 .034 259.733);--color-gray-800:oklch(.278 .033 256.848);--color-gray-900:oklch(.21 .034 264.665);--color-zinc-50:oklch(.985 0 0);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-lg:32rem;--container-xl:36rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-xs:.125rem;--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-sm:8px;--blur-lg:16px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-font-feature-settings:var(--font-sans--font-feature-settings);--default-font-variation-settings:var(--font-sans--font-variation-settings);--default-mono-font-family:var(--font-mono);--default-mono-font-feature-settings:var(--font-mono--font-feature-settings);--default-mono-font-variation-settings:var(--font-mono--font-variation-settings)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1;color:color-mix(in oklab,currentColor 50%,transparent)}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);outline-color:color-mix(in oklab,var(--ring)50%,transparent)}body{background-color:var(--background);color:var(--foreground)}*{scrollbar-color:initial;scrollbar-width:initial}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing)*2)}.top-4{top:calc(var(--spacing)*4)}.top-12{top:calc(var(--spacing)*12)}.top-\[50\%\]{top:50%}.right-0{right:calc(var(--spacing)*0)}.right-2{right:calc(var(--spacing)*2)}.right-4{right:calc(var(--spacing)*4)}.bottom-0{bottom:calc(var(--spacing)*0)}.bottom-2{bottom:calc(var(--spacing)*2)}.bottom-4{bottom:calc(var(--spacing)*4)}.left-0{left:calc(var(--spacing)*0)}.left-1\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.left-\[50\%\]{left:50%}.left-\[calc\(1rem\+2\.5rem\)\]{left:3.5rem}.z-10{z-index:10}.z-50{z-index:50}.z-60{z-index:60}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.\!m-0{margin:calc(var(--spacing)*0)!important}.m-0{margin:calc(var(--spacing)*0)}.-mx-1{margin-inline:calc(var(--spacing)*-1)}.mx-1{margin-inline:calc(var(--spacing)*1)}.mx-4{margin-inline:calc(var(--spacing)*4)}.my-1{margin-block:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mr-1{margin-right:calc(var(--spacing)*1)}.mr-2{margin-right:calc(var(--spacing)*2)}.mr-4{margin-right:calc(var(--spacing)*4)}.mr-6{margin-right:calc(var(--spacing)*6)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\!inline{display:inline!important}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.\!size-full{width:100%!important;height:100%!important}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.size-8{width:calc(var(--spacing)*8);height:calc(var(--spacing)*8)}.size-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.size-full{width:100%;height:100%}.h-1\/2{height:50%}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-11{height:calc(var(--spacing)*11)}.h-12{height:calc(var(--spacing)*12)}.h-24{height:calc(var(--spacing)*24)}.h-52{height:calc(var(--spacing)*52)}.h-\[1px\]{height:1px}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-fit{height:fit-content}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-8{max-height:calc(var(--spacing)*8)}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-96{max-height:calc(var(--spacing)*96)}.max-h-\[60vh\]{max-height:60vh}.max-h-\[300px\]{max-height:300px}.max-h-full{max-height:100%}.min-h-0{min-height:calc(var(--spacing)*0)}.w-2\.5{width:calc(var(--spacing)*2.5)}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-7{width:calc(var(--spacing)*7)}.w-8{width:calc(var(--spacing)*8)}.w-9{width:calc(var(--spacing)*9)}.w-12{width:calc(var(--spacing)*12)}.w-16{width:calc(var(--spacing)*16)}.w-24{width:calc(var(--spacing)*24)}.w-56{width:calc(var(--spacing)*56)}.w-\[1px\]{width:1px}.w-auto{width:auto}.w-full{width:100%}.w-screen{width:100vw}.max-w-80{max-width:calc(var(--spacing)*80)}.max-w-\[80\%\]{max-width:80%}.max-w-\[480px\]{max-width:480px}.max-w-lg{max-width:var(--container-lg)}.max-w-none{max-width:none}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-24{min-width:calc(var(--spacing)*24)}.min-w-\[8rem\]{min-width:8rem}.min-w-\[180px\]{min-width:180px}.min-w-\[300px\]{min-width:300px}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.flex-1{flex:1}.flex-auto{flex:auto}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.caption-bottom{caption-side:bottom}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-\[-50\%\]{--tw-translate-x:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-20{--tw-translate-y:calc(var(--spacing)*-20);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-0{--tw-translate-y:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\[-50\%\]{--tw-translate-y:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-125{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x)var(--tw-scale-y)}.transform{transform:var(--tw-rotate-x)var(--tw-rotate-y)var(--tw-rotate-z)var(--tw-skew-x)var(--tw-skew-y)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.\[appearance\:textfield\]{-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.place-items-center{place-items:center}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}.gap-px{gap:1px}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}.self-center{align-self:center}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.\!rounded-none{border-radius:0!important}.rounded{border-radius:.25rem}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-l-none{border-top-left-radius:0;border-bottom-left-radius:0}.rounded-tr-none{border-top-right-radius:0}.rounded-br-none{border-bottom-right-radius:0}.border,.border-1{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.\!border-none{--tw-border-style:none!important;border-style:none!important}.border-dashed{--tw-border-style:dashed;border-style:dashed}.\!border-input{border-color:var(--input)!important}.border-border\/40{border-color:color-mix(in oklab,var(--border)40%,transparent)}.border-destructive\/50{border-color:color-mix(in oklab,var(--destructive)50%,transparent)}.border-gray-400{border-color:var(--color-gray-400)}.border-input{border-color:var(--input)}.border-muted-foreground\/25{border-color:color-mix(in oklab,var(--muted-foreground)25%,transparent)}.border-muted-foreground\/50{border-color:color-mix(in oklab,var(--muted-foreground)50%,transparent)}.border-primary{border-color:var(--primary)}.border-transparent{border-color:#0000}.border-t-transparent{border-top-color:#0000}.border-l-transparent{border-left-color:#0000}.\!bg-background{background-color:var(--background)!important}.\!bg-emerald-400{background-color:var(--color-emerald-400)!important}.bg-amber-100{background-color:var(--color-amber-100)}.bg-background{background-color:var(--background)}.bg-background\/60{background-color:color-mix(in oklab,var(--background)60%,transparent)}.bg-background\/80{background-color:color-mix(in oklab,var(--background)80%,transparent)}.bg-background\/90{background-color:color-mix(in oklab,var(--background)90%,transparent)}.bg-background\/95{background-color:color-mix(in oklab,var(--background)95%,transparent)}.bg-black\/10{background-color:color-mix(in oklab,var(--color-black)10%,transparent)}.bg-black\/80{background-color:color-mix(in oklab,var(--color-black)80%,transparent)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-destructive{background-color:var(--destructive)}.bg-foreground\/10{background-color:color-mix(in oklab,var(--foreground)10%,transparent)}.bg-green-500{background-color:var(--color-green-500)}.bg-muted{background-color:var(--muted)}.bg-muted\/50{background-color:color-mix(in oklab,var(--muted)50%,transparent)}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-primary-foreground\/60{background-color:color-mix(in oklab,var(--primary-foreground)60%,transparent)}.bg-primary\/5{background-color:color-mix(in oklab,var(--primary)5%,transparent)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-700{background-color:var(--color-red-700)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-white\/30{background-color:color-mix(in oklab,var(--color-white)30%,transparent)}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-emerald-50{--tw-gradient-from:var(--color-emerald-50);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-teal-100{--tw-gradient-to:var(--color-teal-100);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.object-cover{object-fit:cover}.\!p-0{padding:calc(var(--spacing)*0)!important}.\!p-2{padding:calc(var(--spacing)*2)!important}.p-0{padding:calc(var(--spacing)*0)}.p-1{padding:calc(var(--spacing)*1)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.p-16{padding:calc(var(--spacing)*16)}.p-\[1px\]{padding:1px}.px-1{padding-inline:calc(var(--spacing)*1)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-6{padding-block:calc(var(--spacing)*6)}.pt-0{padding-top:calc(var(--spacing)*0)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-6{padding-top:calc(var(--spacing)*6)}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-2{padding-right:calc(var(--spacing)*2)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pb-8{padding-bottom:calc(var(--spacing)*8)}.pb-12{padding-bottom:calc(var(--spacing)*12)}.pl-1{padding-left:calc(var(--spacing)*1)}.pl-8{padding-left:calc(var(--spacing)*8)}.text-center{text-align:center}.text-left{text-align:left}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-words{overflow-wrap:break-word}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.\!text-zinc-50{color:var(--color-zinc-50)!important}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-card-foreground{color:var(--card-foreground)}.text-current{color:currentColor}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-emerald-400{color:var(--color-emerald-400)}.text-emerald-700{color:var(--color-emerald-700)}.text-foreground{color:var(--foreground)}.text-foreground\/80{color:color-mix(in oklab,var(--foreground)80%,transparent)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-700{color:var(--color-gray-700)}.text-gray-900{color:var(--color-gray-900)}.text-green-600{color:var(--color-green-600)}.text-muted-foreground{color:var(--muted-foreground)}.text-muted-foreground\/70{color:color-mix(in oklab,var(--muted-foreground)70%,transparent)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-primary\/60{color:color-mix(in oklab,var(--primary)60%,transparent)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-violet-700{color:var(--color-violet-700)}.text-white{color:var(--color-white)}.text-yellow-600{color:var(--color-yellow-600)}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-20{opacity:.2}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_8px_rgba\(0\,0\,0\,0\.2\)\]{--tw-shadow:0 0 8px var(--tw-shadow-color,#0003);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_12px_rgba\(34\,197\,94\,0\.4\)\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#22c55e66);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_12px_rgba\(239\,68\,68\,0\.4\)\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#ef444466);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-lg{--tw-backdrop-blur:blur(var(--blur-lg));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.duration-2000{--tw-duration:2s;transition-duration:2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.animate-in{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.duration-200{animation-duration:.2s}.duration-300{animation-duration:.3s}.duration-500{animation-duration:.5s}.duration-2000{animation-duration:2s}.ease-in-out{animation-timing-function:cubic-bezier(.4,0,.2,1)}.fade-in-0{--tw-enter-opacity:0}.running{animation-play-state:running}.zoom-in-95{--tw-enter-scale:.95}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-transparent::file-selector-button{background-color:#0000}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:text-foreground::file-selector-button{color:var(--foreground)}.placeholder\:text-muted-foreground::placeholder{color:var(--muted-foreground)}@media (hover:hover){.hover\:w-fit:hover{width:fit-content}.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-background\/60:hover{background-color:color-mix(in oklab,var(--background)60%,transparent)}.hover\:bg-destructive\/80:hover{background-color:color-mix(in oklab,var(--destructive)80%,transparent)}.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,var(--destructive)90%,transparent)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-muted\/25:hover{background-color:color-mix(in oklab,var(--muted)25%,transparent)}.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab,var(--muted)50%,transparent)}.hover\:bg-primary\/5:hover{background-color:color-mix(in oklab,var(--primary)5%,transparent)}.hover\:bg-primary\/20:hover{background-color:color-mix(in oklab,var(--primary)20%,transparent)}.hover\:bg-primary\/80:hover{background-color:color-mix(in oklab,var(--primary)80%,transparent)}.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--primary)90%,transparent)}.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--secondary)80%,transparent)}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}}.focus\:bg-accent:focus{background-color:var(--accent)}.focus\:text-accent-foreground:focus{color:var(--accent-foreground)}.focus\:ring-0:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\:ring-offset-0:focus{--tw-ring-offset-width:0px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:outline-0:focus{outline-style:var(--tw-outline-style);outline-width:0}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:relative:focus-visible{position:relative}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentColor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--ring)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\:right-0:active{right:calc(var(--spacing)*0)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\[disabled\=true\]\:opacity-50[data-disabled=true]{opacity:.5}.data-\[selected\=\'true\'\]\:bg-accent[data-selected=true]{background-color:var(--accent)}.data-\[selected\=true\]\:text-accent-foreground[data-selected=true]{color:var(--accent-foreground)}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:-.5rem}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:.5rem}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:-.5rem}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:.5rem}.data-\[state\=active\]\:visible[data-state=active]{visibility:visible}.data-\[state\=active\]\:bg-background[data-state=active]{background-color:var(--background)}.data-\[state\=active\]\:text-foreground[data-state=active]{color:var(--foreground)}.data-\[state\=active\]\:shadow-sm[data-state=active]{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.data-\[state\=checked\]\:bg-primary[data-state=checked]{background-color:var(--primary)}.data-\[state\=checked\]\:text-primary-foreground[data-state=checked]{color:var(--primary-foreground)}.data-\[state\=closed\]\:animate-out[data-state=closed]{--tw-exit-opacity:initial;--tw-exit-scale:initial;--tw-exit-rotate:initial;--tw-exit-translate-x:initial;--tw-exit-translate-y:initial;animation-name:exit;animation-duration:.15s}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y:-48%}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=inactive\]\:invisible[data-state=inactive]{visibility:hidden}.data-\[state\=open\]\:bg-accent[data-state=open]{background-color:var(--accent)}.data-\[state\=open\]\:text-muted-foreground[data-state=open]{color:var(--muted-foreground)}.data-\[state\=open\]\:animate-in[data-state=open]{--tw-enter-opacity:initial;--tw-enter-scale:initial;--tw-enter-rotate:initial;--tw-enter-translate-x:initial;--tw-enter-translate-y:initial;animation-name:enter;animation-duration:.15s}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity:0}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y:-48%}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale:.95}.data-\[state\=selected\]\:bg-muted[data-state=selected]{background-color:var(--muted)}@supports ((-webkit-backdrop-filter:var(--tw)) or (backdrop-filter:var(--tw))){.supports-\[backdrop-filter\]\:bg-background\/60{background-color:color-mix(in oklab,var(--background)60%,transparent)}}@media (width>=40rem){.sm\:mt-0{margin-top:calc(var(--spacing)*0)}.sm\:max-w-xl{max-width:var(--container-xl)}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}:where(.sm\:space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}.sm\:rounded-lg{border-radius:var(--radius)}.sm\:px-5{padding-inline:calc(var(--spacing)*5)}.sm\:text-left{text-align:left}}@media (width>=48rem){.md\:inline-block{display:inline-block}.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.dark\:border-destructive:is(.dark *){border-color:var(--destructive)}.dark\:border-gray-600:is(.dark *){border-color:var(--color-gray-600)}.dark\:bg-amber-900:is(.dark *){background-color:var(--color-amber-900)}.dark\:bg-gray-100\/20:is(.dark *){background-color:color-mix(in oklab,var(--color-gray-100)20%,transparent)}.dark\:bg-gray-800\/30:is(.dark *){background-color:color-mix(in oklab,var(--color-gray-800)30%,transparent)}.dark\:bg-red-950:is(.dark *){background-color:var(--color-red-950)}.dark\:from-gray-900:is(.dark *){--tw-gradient-from:var(--color-gray-900);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.dark\:to-gray-800:is(.dark *){--tw-gradient-to:var(--color-gray-800);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.dark\:text-amber-200:is(.dark *){color:var(--color-amber-200)}.dark\:text-gray-300:is(.dark *){color:var(--color-gray-300)}.dark\:text-gray-400:is(.dark *){color:var(--color-gray-400)}.dark\:text-red-400:is(.dark *){color:var(--color-red-400)}@media (hover:hover){.dark\:hover\:bg-gray-700:is(.dark *):hover{background-color:var(--color-gray-700)}}.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-inline:calc(var(--spacing)*2)}.\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-block:calc(var(--spacing)*1.5)}.\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading]{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:var(--muted-foreground)}.\[\&_\[cmdk-group\]\]\:px-2 [cmdk-group]{padding-inline:calc(var(--spacing)*2)}.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden])~[cmdk-group]{padding-top:calc(var(--spacing)*0)}.\[\&_\[cmdk-input-wrapper\]_svg\]\:h-5 [cmdk-input-wrapper] svg{height:calc(var(--spacing)*5)}.\[\&_\[cmdk-input-wrapper\]_svg\]\:w-5 [cmdk-input-wrapper] svg{width:calc(var(--spacing)*5)}.\[\&_\[cmdk-input\]\]\:h-12 [cmdk-input]{height:calc(var(--spacing)*12)}.\[\&_\[cmdk-item\]\]\:px-2 [cmdk-item]{padding-inline:calc(var(--spacing)*2)}.\[\&_\[cmdk-item\]\]\:py-3 [cmdk-item]{padding-block:calc(var(--spacing)*3)}.\[\&_\[cmdk-item\]_svg\]\:h-5 [cmdk-item] svg{height:calc(var(--spacing)*5)}.\[\&_\[cmdk-item\]_svg\]\:w-5 [cmdk-item] svg{width:calc(var(--spacing)*5)}.\[\&_p\]\:leading-relaxed p{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_tr\]\:border-b tr{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.\[\&_tr\:last-child\]\:border-0 tr:last-child{border-style:var(--tw-border-style);border-width:0}.\[\&\:\:-webkit-inner-spin-button\]\:appearance-none::-webkit-inner-spin-button{-webkit-appearance:none;-moz-appearance:none;appearance:none}.\[\&\:\:-webkit-inner-spin-button\]\:opacity-100::-webkit-inner-spin-button{opacity:1}.\[\&\:\:-webkit-outer-spin-button\]\:appearance-none::-webkit-outer-spin-button{-webkit-appearance:none;-moz-appearance:none;appearance:none}.\[\&\:\:-webkit-outer-spin-button\]\:opacity-100::-webkit-outer-spin-button{opacity:1}.\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role=checkbox]){padding-right:calc(var(--spacing)*0)}.\[\&\>\[role\=checkbox\]\]\:translate-y-\[2px\]>[role=checkbox]{--tw-translate-y:2px;translate:var(--tw-translate-x)var(--tw-translate-y)}.\[\&\>span\]\:line-clamp-1>span{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.\[\&\>svg\]\:absolute>svg{position:absolute}.\[\&\>svg\]\:top-4>svg{top:calc(var(--spacing)*4)}.\[\&\>svg\]\:left-4>svg{left:calc(var(--spacing)*4)}.\[\&\>svg\]\:text-destructive>svg{color:var(--destructive)}.\[\&\>svg\]\:text-foreground>svg{color:var(--foreground)}.\[\&\>svg\+div\]\:translate-y-\[-3px\]>svg+div{--tw-translate-y:-3px;translate:var(--tw-translate-x)var(--tw-translate-y)}.\[\&\>svg\~\*\]\:pl-7>svg~*{padding-left:calc(var(--spacing)*7)}.\[\&\>tr\]\:last\:border-b-0>tr:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}}:root{--background:#fff;--foreground:#09090b;--card:#fff;--card-foreground:#09090b;--popover:#fff;--popover-foreground:#09090b;--primary:#18181b;--primary-foreground:#fafafa;--secondary:#f4f4f5;--secondary-foreground:#18181b;--muted:#f4f4f5;--muted-foreground:#71717a;--accent:#f4f4f5;--accent-foreground:#18181b;--destructive:#ef4444;--destructive-foreground:#fafafa;--border:#e4e4e7;--input:#e4e4e7;--ring:#09090b;--chart-1:#e76e50;--chart-2:#2a9d90;--chart-3:#274754;--chart-4:#e8c468;--chart-5:#f4a462;--radius:.6rem;--sidebar-background:#fafafa;--sidebar-foreground:#3f3f46;--sidebar-primary:#18181b;--sidebar-primary-foreground:#fafafa;--sidebar-accent:#f4f4f5;--sidebar-accent-foreground:#18181b;--sidebar-border:#e5e7eb;--sidebar-ring:#3b82f6}.dark{--background:#09090b;--foreground:#fafafa;--card:#09090b;--card-foreground:#fafafa;--popover:#09090b;--popover-foreground:#fafafa;--primary:#fafafa;--primary-foreground:#18181b;--secondary:#27272a;--secondary-foreground:#fafafa;--muted:#27272a;--muted-foreground:#a1a1aa;--accent:#27272a;--accent-foreground:#fafafa;--destructive:#7f1d1d;--destructive-foreground:#fafafa;--border:#27272a;--input:#27272a;--ring:#d4d4d8;--chart-1:#2662d9;--chart-2:#2eb88a;--chart-3:#e88c30;--chart-4:#af57db;--chart-5:#e23670;--sidebar-background:#18181b;--sidebar-foreground:#f4f4f5;--sidebar-primary:#1d4ed8;--sidebar-primary-foreground:#fff;--sidebar-accent:#27272a;--sidebar-accent-foreground:#f4f4f5;--sidebar-border:#27272a;--sidebar-ring:#3b82f6}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background-color:#ccc;border-radius:5px}::-webkit-scrollbar-track{background-color:#f2f2f2}.dark ::-webkit-scrollbar-thumb{background-color:#e6e6e6}.dark ::-webkit-scrollbar-track{background-color:#000}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0))}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false;initial-value:rotateX(0)}@property --tw-rotate-y{syntax:"*";inherits:false;initial-value:rotateY(0)}@property --tw-rotate-z{syntax:"*";inherits:false;initial-value:rotateZ(0)}@property --tw-skew-x{syntax:"*";inherits:false;initial-value:skewX(0)}@property --tw-skew-y{syntax:"*";inherits:false;initial-value:skewY(0)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}:root{--sigma-background-color:#fff;--sigma-controls-background-color:#fff;--sigma-controls-background-color-hover:rgba(0,0,0,.2);--sigma-controls-border-color:rgba(0,0,0,.2);--sigma-controls-color:#000;--sigma-controls-zindex:100;--sigma-controls-margin:5px;--sigma-controls-size:30px}div.react-sigma{height:100%;width:100%;position:relative;background:var(--sigma-background-color)}div.sigma-container{height:100%;width:100%}.react-sigma-controls{position:absolute;z-index:var(--sigma-controls-zindex);border:2px solid var(--sigma-controls-border-color);border-radius:4px;color:var(--sigma-controls-color);background-color:var(--sigma-controls-background-color)}.react-sigma-controls.bottom-right{bottom:var(--sigma-controls-margin);right:var(--sigma-controls-margin)}.react-sigma-controls.bottom-left{bottom:var(--sigma-controls-margin);left:var(--sigma-controls-margin)}.react-sigma-controls.top-right{top:var(--sigma-controls-margin);right:var(--sigma-controls-margin)}.react-sigma-controls.top-left{top:var(--sigma-controls-margin);left:var(--sigma-controls-margin)}.react-sigma-controls:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.react-sigma-controls:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.react-sigma-control{width:var(--sigma-controls-size);height:var(--sigma-controls-size);line-height:var(--sigma-controls-size);background-color:var(--sigma-controls-background-color);border-bottom:1px solid var(--sigma-controls-border-color)}.react-sigma-control:last-child{border-bottom:none}.react-sigma-control>*{box-sizing:border-box}.react-sigma-control>button{display:block;border:none;margin:0;padding:0;width:var(--sigma-controls-size);height:var(--sigma-controls-size);line-height:var(--sigma-controls-size);background-position:center;background-size:50%;background-repeat:no-repeat;background-color:var(--sigma-controls-background-color);clip:rect(0,0,0,0)}.react-sigma-control>button:hover{background-color:var(--sigma-controls-background-color-hover)}.react-sigma-search{background-color:var(--sigma-controls-background-color)}.react-sigma-search label{visibility:hidden}.react-sigma-search input{color:var(--sigma-controls-color);background-color:var(--sigma-controls-background-color);font-size:1em;width:100%;margin:0;border:none;padding:var(--sigma-controls-margin);box-sizing:border-box}:root{--sigma-grey-color:#ccc}.react-sigma .option.hoverable{cursor:pointer!important}.react-sigma .text-ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.react-sigma .react-select__clear-indicator{cursor:pointer!important}.react-sigma .text-muted{color:var(--sigma-grey-color)}.react-sigma .text-italic{font-style:italic}.react-sigma .text-center{text-align:center}.react-sigma .graph-search{min-width:250px}.react-sigma .graph-search .option{padding:2px 8px}.react-sigma .graph-search .dropdown-indicator{font-size:1.25em;padding:4px}.react-sigma .graph-search .option.selected{background-color:var(--sigma-grey-color)}.react-sigma .node .render{position:relative;display:inline-block;width:1em;height:1em;border-radius:1em;background-color:var(--sigma-grey-color);margin-right:8px}.react-sigma .node{display:flex;flex-direction:row;align-items:center}.react-sigma .node .render{flex-grow:0;flex-shrink:0;margin-right:0 .25em}.react-sigma .node .label{flex-grow:1;flex-shrink:1}.react-sigma .edge{display:flex;flex-direction:column;align-items:flex-start;flex-grow:0;flex-shrink:0;flex-wrap:nowrap}.react-sigma .edge .node{font-size:.7em}.react-sigma .edge .body{display:flex;flex-direction:row;flex-grow:1;flex-shrink:1;min-height:.6em}.react-sigma .edge .body .render{display:flex;flex-direction:column;margin:0 2px}.react-sigma .edge .body .render .dash,.react-sigma .edge .body .render .dotted{display:inline-block;width:0;margin:0 2px;border:2px solid #ccc;flex-grow:1;flex-shrink:1}.react-sigma .edge .body .render .dotted{border-style:dotted}.react-sigma .edge .body .render .arrow{width:0;height:0;border-left:.3em solid transparent;border-right:.3em solid transparent;border-top:.6em solid red;flex-shrink:0;flex-grow:0;border-left-width:.3em;border-right-width:.3em}.react-sigma .edge .body .label{flex-grow:1;flex-shrink:1;text-align:center} diff --git a/lightrag/api/webui/assets/index-DlScqWrq.js b/lightrag/api/webui/assets/index-DUmKHl1m.js similarity index 72% rename from lightrag/api/webui/assets/index-DlScqWrq.js rename to lightrag/api/webui/assets/index-DUmKHl1m.js index d4fac364..4afeb157 100644 --- a/lightrag/api/webui/assets/index-DlScqWrq.js +++ b/lightrag/api/webui/assets/index-DUmKHl1m.js @@ -1,4 +1,4 @@ -var eq=Object.defineProperty;var tq=(e,t,n)=>t in e?eq(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Xr=(e,t,n)=>tq(e,typeof t!="symbol"?t+"":t,n);function nq(e,t){for(var n=0;nr[a]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))r(a);new MutationObserver(a=>{for(const o of a)if(o.type==="childList")for(const s of o.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&r(s)}).observe(document,{childList:!0,subtree:!0});function n(a){const o={};return a.integrity&&(o.integrity=a.integrity),a.referrerPolicy&&(o.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?o.credentials="include":a.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(a){if(a.ep)return;a.ep=!0;const o=n(a);fetch(a.href,o)}})();var df=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function cn(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function rq(e){if(Object.prototype.hasOwnProperty.call(e,"__esModule"))return e;var t=e.default;if(typeof t=="function"){var n=function r(){return this instanceof r?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var a=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,a.get?a:{enumerable:!0,get:function(){return e[r]}})}),n}var jh={exports:{}},Ql={};/** +var X6=Object.defineProperty;var Z6=(e,t,n)=>t in e?X6(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Kr=(e,t,n)=>Z6(e,typeof t!="symbol"?t+"":t,n);function Q6(e,t){for(var n=0;nr[a]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))r(a);new MutationObserver(a=>{for(const o of a)if(o.type==="childList")for(const s of o.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&r(s)}).observe(document,{childList:!0,subtree:!0});function n(a){const o={};return a.integrity&&(o.integrity=a.integrity),a.referrerPolicy&&(o.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?o.credentials="include":a.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(a){if(a.ep)return;a.ep=!0;const o=n(a);fetch(a.href,o)}})();var df=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function cn(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function J6(e){if(Object.prototype.hasOwnProperty.call(e,"__esModule"))return e;var t=e.default;if(typeof t=="function"){var n=function r(){return this instanceof r?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var a=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,a.get?a:{enumerable:!0,get:function(){return e[r]}})}),n}var jh={exports:{}},Ql={};/** * @license React * react-jsx-runtime.production.js * @@ -6,7 +6,7 @@ var eq=Object.defineProperty;var tq=(e,t,n)=>t in e?eq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var GC;function aq(){if(GC)return Ql;GC=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function n(r,a,o){var s=null;if(o!==void 0&&(s=""+o),a.key!==void 0&&(s=""+a.key),"key"in a){o={};for(var u in a)u!=="key"&&(o[u]=a[u])}else o=a;return a=o.ref,{$$typeof:e,type:r,key:s,ref:a!==void 0?a:null,props:o}}return Ql.Fragment=t,Ql.jsx=n,Ql.jsxs=n,Ql}var HC;function oq(){return HC||(HC=1,jh.exports=aq()),jh.exports}var w=oq(),Gh={exports:{}},it={};/** + */var GC;function eq(){if(GC)return Ql;GC=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function n(r,a,o){var s=null;if(o!==void 0&&(s=""+o),a.key!==void 0&&(s=""+a.key),"key"in a){o={};for(var u in a)u!=="key"&&(o[u]=a[u])}else o=a;return a=o.ref,{$$typeof:e,type:r,key:s,ref:a!==void 0?a:null,props:o}}return Ql.Fragment=t,Ql.jsx=n,Ql.jsxs=n,Ql}var HC;function tq(){return HC||(HC=1,jh.exports=eq()),jh.exports}var w=tq(),Gh={exports:{}},it={};/** * @license React * react.production.js * @@ -14,7 +14,7 @@ var eq=Object.defineProperty;var tq=(e,t,n)=>t in e?eq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var $C;function iq(){if($C)return it;$C=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),a=Symbol.for("react.profiler"),o=Symbol.for("react.consumer"),s=Symbol.for("react.context"),u=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),g=Symbol.iterator;function m(I){return I===null||typeof I!="object"?null:(I=g&&I[g]||I["@@iterator"],typeof I=="function"?I:null)}var b={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},y=Object.assign,S={};function k(I,V,B){this.props=I,this.context=V,this.refs=S,this.updater=B||b}k.prototype.isReactComponent={},k.prototype.setState=function(I,V){if(typeof I!="object"&&typeof I!="function"&&I!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,I,V,"setState")},k.prototype.forceUpdate=function(I){this.updater.enqueueForceUpdate(this,I,"forceUpdate")};function R(){}R.prototype=k.prototype;function x(I,V,B){this.props=I,this.context=V,this.refs=S,this.updater=B||b}var A=x.prototype=new R;A.constructor=x,y(A,k.prototype),A.isPureReactComponent=!0;var N=Array.isArray,O={H:null,A:null,T:null,S:null},C=Object.prototype.hasOwnProperty;function _(I,V,B,M,K,ee){return B=ee.ref,{$$typeof:e,type:I,key:V,ref:B!==void 0?B:null,props:ee}}function P(I,V){return _(I.type,V,void 0,void 0,void 0,I.props)}function D(I){return typeof I=="object"&&I!==null&&I.$$typeof===e}function L(I){var V={"=":"=0",":":"=2"};return"$"+I.replace(/[=:]/g,function(B){return V[B]})}var H=/\/+/g;function $(I,V){return typeof I=="object"&&I!==null&&I.key!=null?L(""+I.key):V.toString(36)}function U(){}function W(I){switch(I.status){case"fulfilled":return I.value;case"rejected":throw I.reason;default:switch(typeof I.status=="string"?I.then(U,U):(I.status="pending",I.then(function(V){I.status==="pending"&&(I.status="fulfilled",I.value=V)},function(V){I.status==="pending"&&(I.status="rejected",I.reason=V)})),I.status){case"fulfilled":return I.value;case"rejected":throw I.reason}}throw I}function Z(I,V,B,M,K){var ee=typeof I;(ee==="undefined"||ee==="boolean")&&(I=null);var Q=!1;if(I===null)Q=!0;else switch(ee){case"bigint":case"string":case"number":Q=!0;break;case"object":switch(I.$$typeof){case e:case t:Q=!0;break;case p:return Q=I._init,Z(Q(I._payload),V,B,M,K)}}if(Q)return K=K(I),Q=M===""?"."+$(I,0):M,N(K)?(B="",Q!=null&&(B=Q.replace(H,"$&/")+"/"),Z(K,V,B,"",function(ye){return ye})):K!=null&&(D(K)&&(K=P(K,B+(K.key==null||I&&I.key===K.key?"":(""+K.key).replace(H,"$&/")+"/")+Q)),V.push(K)),1;Q=0;var J=M===""?".":M+":";if(N(I))for(var ae=0;aet in e?eq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var VC;function lq(){return VC||(VC=1,function(e){function t(j,G){var z=j.length;j.push(G);e:for(;0>>1,I=j[Y];if(0>>1;Ya(M,z))Ka(ee,M)?(j[Y]=ee,j[K]=z,Y=K):(j[Y]=M,j[B]=z,Y=B);else if(Ka(ee,z))j[Y]=ee,j[K]=z,Y=K;else break e}}return G}function a(j,G){var z=j.sortIndex-G.sortIndex;return z!==0?z:j.id-G.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var s=Date,u=s.now();e.unstable_now=function(){return s.now()-u}}var c=[],d=[],p=1,g=null,m=3,b=!1,y=!1,S=!1,k=typeof setTimeout=="function"?setTimeout:null,R=typeof clearTimeout=="function"?clearTimeout:null,x=typeof setImmediate<"u"?setImmediate:null;function A(j){for(var G=n(d);G!==null;){if(G.callback===null)r(d);else if(G.startTime<=j)r(d),G.sortIndex=G.expirationTime,t(c,G);else break;G=n(d)}}function N(j){if(S=!1,A(j),!y)if(n(c)!==null)y=!0,W();else{var G=n(d);G!==null&&Z(N,G.startTime-j)}}var O=!1,C=-1,_=5,P=-1;function D(){return!(e.unstable_now()-P<_)}function L(){if(O){var j=e.unstable_now();P=j;var G=!0;try{e:{y=!1,S&&(S=!1,R(C),C=-1),b=!0;var z=m;try{t:{for(A(j),g=n(c);g!==null&&!(g.expirationTime>j&&D());){var Y=g.callback;if(typeof Y=="function"){g.callback=null,m=g.priorityLevel;var I=Y(g.expirationTime<=j);if(j=e.unstable_now(),typeof I=="function"){g.callback=I,A(j),G=!0;break t}g===n(c)&&r(c),A(j)}else r(c);g=n(c)}if(g!==null)G=!0;else{var V=n(d);V!==null&&Z(N,V.startTime-j),G=!1}}break e}finally{g=null,m=z,b=!1}G=void 0}}finally{G?H():O=!1}}}var H;if(typeof x=="function")H=function(){x(L)};else if(typeof MessageChannel<"u"){var $=new MessageChannel,U=$.port2;$.port1.onmessage=L,H=function(){U.postMessage(null)}}else H=function(){k(L,0)};function W(){O||(O=!0,H())}function Z(j,G){C=k(function(){j(e.unstable_now())},G)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(j){j.callback=null},e.unstable_continueExecution=function(){y||b||(y=!0,W())},e.unstable_forceFrameRate=function(j){0>j||125Y?(j.sortIndex=z,t(d,j),n(c)===null&&j===n(d)&&(S?(R(C),C=-1):S=!0,Z(N,z-Y))):(j.sortIndex=I,t(c,j),y||b||(y=!0,W())),j},e.unstable_shouldYield=D,e.unstable_wrapCallback=function(j){var G=m;return function(){var z=m;m=G;try{return j.apply(this,arguments)}finally{m=z}}}}(qh)),qh}var WC;function uq(){return WC||(WC=1,$h.exports=lq()),$h.exports}var Vh={exports:{}},wn={};/** + */var VC;function aq(){return VC||(VC=1,function(e){function t(G,j){var z=G.length;G.push(j);e:for(;0>>1,L=G[Y];if(0>>1;Ya(M,z))Ka(ee,M)?(G[Y]=ee,G[K]=z,Y=K):(G[Y]=M,G[B]=z,Y=B);else if(Ka(ee,z))G[Y]=ee,G[K]=z,Y=K;else break e}}return j}function a(G,j){var z=G.sortIndex-j.sortIndex;return z!==0?z:G.id-j.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var s=Date,u=s.now();e.unstable_now=function(){return s.now()-u}}var c=[],d=[],p=1,g=null,m=3,b=!1,y=!1,S=!1,k=typeof setTimeout=="function"?setTimeout:null,A=typeof clearTimeout=="function"?clearTimeout:null,x=typeof setImmediate<"u"?setImmediate:null;function R(G){for(var j=n(d);j!==null;){if(j.callback===null)r(d);else if(j.startTime<=G)r(d),j.sortIndex=j.expirationTime,t(c,j);else break;j=n(d)}}function N(G){if(S=!1,R(G),!y)if(n(c)!==null)y=!0,W();else{var j=n(d);j!==null&&Q(N,j.startTime-G)}}var O=!1,C=-1,_=5,P=-1;function I(){return!(e.unstable_now()-P<_)}function D(){if(O){var G=e.unstable_now();P=G;var j=!0;try{e:{y=!1,S&&(S=!1,A(C),C=-1),b=!0;var z=m;try{t:{for(R(G),g=n(c);g!==null&&!(g.expirationTime>G&&I());){var Y=g.callback;if(typeof Y=="function"){g.callback=null,m=g.priorityLevel;var L=Y(g.expirationTime<=G);if(G=e.unstable_now(),typeof L=="function"){g.callback=L,R(G),j=!0;break t}g===n(c)&&r(c),R(G)}else r(c);g=n(c)}if(g!==null)j=!0;else{var V=n(d);V!==null&&Q(N,V.startTime-G),j=!1}}break e}finally{g=null,m=z,b=!1}j=void 0}}finally{j?H():O=!1}}}var H;if(typeof x=="function")H=function(){x(D)};else if(typeof MessageChannel<"u"){var $=new MessageChannel,U=$.port2;$.port1.onmessage=D,H=function(){U.postMessage(null)}}else H=function(){k(D,0)};function W(){O||(O=!0,H())}function Q(G,j){C=k(function(){G(e.unstable_now())},j)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(G){G.callback=null},e.unstable_continueExecution=function(){y||b||(y=!0,W())},e.unstable_forceFrameRate=function(G){0>G||125Y?(G.sortIndex=z,t(d,G),n(c)===null&&G===n(d)&&(S?(A(C),C=-1):S=!0,Q(N,z-Y))):(G.sortIndex=L,t(c,G),y||b||(y=!0,W())),G},e.unstable_shouldYield=I,e.unstable_wrapCallback=function(G){var j=m;return function(){var z=m;m=j;try{return G.apply(this,arguments)}finally{m=z}}}}(qh)),qh}var WC;function oq(){return WC||(WC=1,$h.exports=aq()),$h.exports}var Vh={exports:{}},wn={};/** * @license React * react-dom.production.js * @@ -30,7 +30,7 @@ var eq=Object.defineProperty;var tq=(e,t,n)=>t in e?eq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var YC;function cq(){if(YC)return wn;YC=1;var e=h0();function t(c){var d="https://react.dev/errors/"+c;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Vh.exports=cq(),Vh.exports}/** + */var YC;function iq(){if(YC)return wn;YC=1;var e=h0();function t(c){var d="https://react.dev/errors/"+c;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Vh.exports=iq(),Vh.exports}/** * @license React * react-dom-client.production.js * @@ -38,15 +38,15 @@ var eq=Object.defineProperty;var tq=(e,t,n)=>t in e?eq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var XC;function dq(){if(XC)return Jl;XC=1;var e=uq(),t=h0(),n=Oz();function r(i){var l="https://react.dev/errors/"+i;if(1)":-1v||X[h]!==oe[v]){var be=` -`+X[h].replace(" at new "," at ");return i.displayName&&be.includes("")&&(be=be.replace("",i.displayName)),be}while(1<=h&&0<=v);break}}}finally{W=!1,Error.prepareStackTrace=f}return(f=i?i.displayName||i.name:"")?U(f):""}function j(i){switch(i.tag){case 26:case 27:case 5:return U(i.type);case 16:return U("Lazy");case 13:return U("Suspense");case 19:return U("SuspenseList");case 0:case 15:return i=Z(i.type,!1),i;case 11:return i=Z(i.type.render,!1),i;case 1:return i=Z(i.type,!0),i;default:return""}}function G(i){try{var l="";do l+=j(i),i=i.return;while(i);return l}catch(f){return` +`+X[h].replace(" at new "," at ");return i.displayName&&be.includes("")&&(be=be.replace("",i.displayName)),be}while(1<=h&&0<=v);break}}}finally{W=!1,Error.prepareStackTrace=f}return(f=i?i.displayName||i.name:"")?U(f):""}function G(i){switch(i.tag){case 26:case 27:case 5:return U(i.type);case 16:return U("Lazy");case 13:return U("Suspense");case 19:return U("SuspenseList");case 0:case 15:return i=Q(i.type,!1),i;case 11:return i=Q(i.type.render,!1),i;case 1:return i=Q(i.type,!0),i;default:return""}}function j(i){try{var l="";do l+=G(i),i=i.return;while(i);return l}catch(f){return` Error generating stack: `+f.message+` -`+f.stack}}function z(i){var l=i,f=i;if(i.alternate)for(;l.return;)l=l.return;else{i=l;do l=i,(l.flags&4098)!==0&&(f=l.return),i=l.return;while(i)}return l.tag===3?f:null}function Y(i){if(i.tag===13){var l=i.memoizedState;if(l===null&&(i=i.alternate,i!==null&&(l=i.memoizedState)),l!==null)return l.dehydrated}return null}function I(i){if(z(i)!==i)throw Error(r(188))}function V(i){var l=i.alternate;if(!l){if(l=z(i),l===null)throw Error(r(188));return l!==i?null:i}for(var f=i,h=l;;){var v=f.return;if(v===null)break;var T=v.alternate;if(T===null){if(h=v.return,h!==null){f=h;continue}break}if(v.child===T.child){for(T=v.child;T;){if(T===f)return I(v),i;if(T===h)return I(v),l;T=T.sibling}throw Error(r(188))}if(f.return!==h.return)f=v,h=T;else{for(var F=!1,q=v.child;q;){if(q===f){F=!0,f=v,h=T;break}if(q===h){F=!0,h=v,f=T;break}q=q.sibling}if(!F){for(q=T.child;q;){if(q===f){F=!0,f=T,h=v;break}if(q===h){F=!0,h=T,f=v;break}q=q.sibling}if(!F)throw Error(r(189))}}if(f.alternate!==h)throw Error(r(190))}if(f.tag!==3)throw Error(r(188));return f.stateNode.current===f?i:l}function B(i){var l=i.tag;if(l===5||l===26||l===27||l===6)return i;for(i=i.child;i!==null;){if(l=B(i),l!==null)return l;i=i.sibling}return null}var M=Array.isArray,K=n.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ee={pending:!1,data:null,method:null,action:null},Q=[],J=-1;function ae(i){return{current:i}}function ye(i){0>J||(i.current=Q[J],Q[J]=null,J--)}function ie(i,l){J++,Q[J]=i.current,i.current=l}var Ee=ae(null),Se=ae(null),De=ae(null),Ce=ae(null);function we(i,l){switch(ie(De,l),ie(Se,i),ie(Ee,null),i=l.nodeType,i){case 9:case 11:l=(l=l.documentElement)&&(l=l.namespaceURI)?bC(l):0;break;default:if(i=i===8?l.parentNode:l,l=i.tagName,i=i.namespaceURI)i=bC(i),l=yC(i,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}ye(Ee),ie(Ee,l)}function te(){ye(Ee),ye(Se),ye(De)}function fe(i){i.memoizedState!==null&&ie(Ce,i);var l=Ee.current,f=yC(l,i.type);l!==f&&(ie(Se,i),ie(Ee,f))}function Te(i){Se.current===i&&(ye(Ee),ye(Se)),Ce.current===i&&(ye(Ce),Wl._currentValue=ee)}var me=Object.prototype.hasOwnProperty,xe=e.unstable_scheduleCallback,le=e.unstable_cancelCallback,ze=e.unstable_shouldYield,Be=e.unstable_requestPaint,he=e.unstable_now,Ne=e.unstable_getCurrentPriorityLevel,ne=e.unstable_ImmediatePriority,ce=e.unstable_UserBlockingPriority,_e=e.unstable_NormalPriority,Fe=e.unstable_LowPriority,We=e.unstable_IdlePriority,yt=e.log,kt=e.unstable_setDisableYieldValue,ht=null,et=null;function Tt(i){if(et&&typeof et.onCommitFiberRoot=="function")try{et.onCommitFiberRoot(ht,i,void 0,(i.current.flags&128)===128)}catch{}}function ot(i){if(typeof yt=="function"&&kt(i),et&&typeof et.setStrictMode=="function")try{et.setStrictMode(ht,i)}catch{}}var St=Math.clz32?Math.clz32:zt,Ht=Math.log,pn=Math.LN2;function zt(i){return i>>>=0,i===0?32:31-(Ht(i)/pn|0)|0}var or=128,$r=4194304;function Jt(i){var l=i&42;if(l!==0)return l;switch(i&-i){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return i&4194176;case 4194304:case 8388608:case 16777216:case 33554432:return i&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return i}}function fa(i,l){var f=i.pendingLanes;if(f===0)return 0;var h=0,v=i.suspendedLanes,T=i.pingedLanes,F=i.warmLanes;i=i.finishedLanes!==0;var q=f&134217727;return q!==0?(f=q&~v,f!==0?h=Jt(f):(T&=q,T!==0?h=Jt(T):i||(F=q&~F,F!==0&&(h=Jt(F))))):(q=f&~v,q!==0?h=Jt(q):T!==0?h=Jt(T):i||(F=f&~F,F!==0&&(h=Jt(F)))),h===0?0:l!==0&&l!==h&&(l&v)===0&&(v=h&-h,F=l&-l,v>=F||v===32&&(F&4194176)!==0)?l:h}function Xe(i,l){return(i.pendingLanes&~(i.suspendedLanes&~i.pingedLanes)&l)===0}function mt(i,l){switch(i){case 1:case 2:case 4:case 8:return l+250;case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return l+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function _t(){var i=or;return or<<=1,(or&4194176)===0&&(or=128),i}function Dn(){var i=$r;return $r<<=1,($r&62914560)===0&&($r=4194304),i}function _n(i){for(var l=[],f=0;31>f;f++)l.push(i);return l}function Ln(i,l){i.pendingLanes|=l,l!==268435456&&(i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0)}function pa(i,l,f,h,v,T){var F=i.pendingLanes;i.pendingLanes=f,i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0,i.expiredLanes&=f,i.entangledLanes&=f,i.errorRecoveryDisabledLanes&=f,i.shellSuspendCounter=0;var q=i.entanglements,X=i.expirationTimes,oe=i.hiddenUpdates;for(f=F&~f;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),WH=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),yA={},vA={};function YH(i){return me.call(vA,i)?!0:me.call(yA,i)?!1:WH.test(i)?vA[i]=!0:(yA[i]=!0,!1)}function sc(i,l,f){if(YH(l))if(f===null)i.removeAttribute(l);else{switch(typeof f){case"undefined":case"function":case"symbol":i.removeAttribute(l);return;case"boolean":var h=l.toLowerCase().slice(0,5);if(h!=="data-"&&h!=="aria-"){i.removeAttribute(l);return}}i.setAttribute(l,""+f)}}function lc(i,l,f){if(f===null)i.removeAttribute(l);else{switch(typeof f){case"undefined":case"function":case"symbol":case"boolean":i.removeAttribute(l);return}i.setAttribute(l,""+f)}}function ha(i,l,f,h){if(h===null)i.removeAttribute(f);else{switch(typeof h){case"undefined":case"function":case"symbol":case"boolean":i.removeAttribute(f);return}i.setAttributeNS(l,f,""+h)}}function ir(i){switch(typeof i){case"bigint":case"boolean":case"number":case"string":case"undefined":return i;case"object":return i;default:return""}}function SA(i){var l=i.type;return(i=i.nodeName)&&i.toLowerCase()==="input"&&(l==="checkbox"||l==="radio")}function KH(i){var l=SA(i)?"checked":"value",f=Object.getOwnPropertyDescriptor(i.constructor.prototype,l),h=""+i[l];if(!i.hasOwnProperty(l)&&typeof f<"u"&&typeof f.get=="function"&&typeof f.set=="function"){var v=f.get,T=f.set;return Object.defineProperty(i,l,{configurable:!0,get:function(){return v.call(this)},set:function(F){h=""+F,T.call(this,F)}}),Object.defineProperty(i,l,{enumerable:f.enumerable}),{getValue:function(){return h},setValue:function(F){h=""+F},stopTracking:function(){i._valueTracker=null,delete i[l]}}}}function uc(i){i._valueTracker||(i._valueTracker=KH(i))}function EA(i){if(!i)return!1;var l=i._valueTracker;if(!l)return!0;var f=l.getValue(),h="";return i&&(h=SA(i)?i.checked?"true":"false":i.value),i=h,i!==f?(l.setValue(i),!0):!1}function cc(i){if(i=i||(typeof document<"u"?document:void 0),typeof i>"u")return null;try{return i.activeElement||i.body}catch{return i.body}}var XH=/[\n"\\]/g;function sr(i){return i.replace(XH,function(l){return"\\"+l.charCodeAt(0).toString(16)+" "})}function Bp(i,l,f,h,v,T,F,q){i.name="",F!=null&&typeof F!="function"&&typeof F!="symbol"&&typeof F!="boolean"?i.type=F:i.removeAttribute("type"),l!=null?F==="number"?(l===0&&i.value===""||i.value!=l)&&(i.value=""+ir(l)):i.value!==""+ir(l)&&(i.value=""+ir(l)):F!=="submit"&&F!=="reset"||i.removeAttribute("value"),l!=null?Up(i,F,ir(l)):f!=null?Up(i,F,ir(f)):h!=null&&i.removeAttribute("value"),v==null&&T!=null&&(i.defaultChecked=!!T),v!=null&&(i.checked=v&&typeof v!="function"&&typeof v!="symbol"),q!=null&&typeof q!="function"&&typeof q!="symbol"&&typeof q!="boolean"?i.name=""+ir(q):i.removeAttribute("name")}function wA(i,l,f,h,v,T,F,q){if(T!=null&&typeof T!="function"&&typeof T!="symbol"&&typeof T!="boolean"&&(i.type=T),l!=null||f!=null){if(!(T!=="submit"&&T!=="reset"||l!=null))return;f=f!=null?""+ir(f):"",l=l!=null?""+ir(l):f,q||l===i.value||(i.value=l),i.defaultValue=l}h=h??v,h=typeof h!="function"&&typeof h!="symbol"&&!!h,i.checked=q?i.checked:!!h,i.defaultChecked=!!h,F!=null&&typeof F!="function"&&typeof F!="symbol"&&typeof F!="boolean"&&(i.name=F)}function Up(i,l,f){l==="number"&&cc(i.ownerDocument)===i||i.defaultValue===""+f||(i.defaultValue=""+f)}function Ii(i,l,f,h){if(i=i.options,l){l={};for(var v=0;v=dl),MA=" ",PA=!1;function FA(i,l){switch(i){case"keyup":return k$.indexOf(l.keyCode)!==-1;case"keydown":return l.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function zA(i){return i=i.detail,typeof i=="object"&&"data"in i?i.data:null}var Pi=!1;function A$(i,l){switch(i){case"compositionend":return zA(l);case"keypress":return l.which!==32?null:(PA=!0,MA);case"textInput":return i=l.data,i===MA&&PA?null:i;default:return null}}function R$(i,l){if(Pi)return i==="compositionend"||!Zp&&FA(i,l)?(i=_A(),fc=Vp=Xa=null,Pi=!1,i):null;switch(i){case"paste":return null;case"keypress":if(!(l.ctrlKey||l.altKey||l.metaKey)||l.ctrlKey&&l.altKey){if(l.char&&1=l)return{node:f,offset:l-i};i=h}e:{for(;f;){if(f.nextSibling){f=f.nextSibling;break e}f=f.parentNode}f=void 0}f=VA(f)}}function YA(i,l){return i&&l?i===l?!0:i&&i.nodeType===3?!1:l&&l.nodeType===3?YA(i,l.parentNode):"contains"in i?i.contains(l):i.compareDocumentPosition?!!(i.compareDocumentPosition(l)&16):!1:!1}function KA(i){i=i!=null&&i.ownerDocument!=null&&i.ownerDocument.defaultView!=null?i.ownerDocument.defaultView:window;for(var l=cc(i.document);l instanceof i.HTMLIFrameElement;){try{var f=typeof l.contentWindow.location.href=="string"}catch{f=!1}if(f)i=l.contentWindow;else break;l=cc(i.document)}return l}function eg(i){var l=i&&i.nodeName&&i.nodeName.toLowerCase();return l&&(l==="input"&&(i.type==="text"||i.type==="search"||i.type==="tel"||i.type==="url"||i.type==="password")||l==="textarea"||i.contentEditable==="true")}function M$(i,l){var f=KA(l);l=i.focusedElem;var h=i.selectionRange;if(f!==l&&l&&l.ownerDocument&&YA(l.ownerDocument.documentElement,l)){if(h!==null&&eg(l)){if(i=h.start,f=h.end,f===void 0&&(f=i),"selectionStart"in l)l.selectionStart=i,l.selectionEnd=Math.min(f,l.value.length);else if(f=(i=l.ownerDocument||document)&&i.defaultView||window,f.getSelection){f=f.getSelection();var v=l.textContent.length,T=Math.min(h.start,v);h=h.end===void 0?T:Math.min(h.end,v),!f.extend&&T>h&&(v=h,h=T,T=v),v=WA(l,T);var F=WA(l,h);v&&F&&(f.rangeCount!==1||f.anchorNode!==v.node||f.anchorOffset!==v.offset||f.focusNode!==F.node||f.focusOffset!==F.offset)&&(i=i.createRange(),i.setStart(v.node,v.offset),f.removeAllRanges(),T>h?(f.addRange(i),f.extend(F.node,F.offset)):(i.setEnd(F.node,F.offset),f.addRange(i)))}}for(i=[],f=l;f=f.parentNode;)f.nodeType===1&&i.push({element:f,left:f.scrollLeft,top:f.scrollTop});for(typeof l.focus=="function"&&l.focus(),l=0;l=document.documentMode,Fi=null,tg=null,hl=null,ng=!1;function XA(i,l,f){var h=f.window===f?f.document:f.nodeType===9?f:f.ownerDocument;ng||Fi==null||Fi!==cc(h)||(h=Fi,"selectionStart"in h&&eg(h)?h={start:h.selectionStart,end:h.selectionEnd}:(h=(h.ownerDocument&&h.ownerDocument.defaultView||window).getSelection(),h={anchorNode:h.anchorNode,anchorOffset:h.anchorOffset,focusNode:h.focusNode,focusOffset:h.focusOffset}),hl&&gl(hl,h)||(hl=h,h=Jc(tg,"onSelect"),0>=F,v-=F,ma=1<<32-St(l)+v|f<Je?(ln=Ye,Ye=null):ln=Ye.sibling;var wt=de(se,Ye,ue[Je],ke);if(wt===null){Ye===null&&(Ye=ln);break}i&&Ye&&wt.alternate===null&&l(se,Ye),re=T(wt,re,Je),lt===null?je=wt:lt.sibling=wt,lt=wt,Ye=ln}if(Je===ue.length)return f(se,Ye),Et&&Ho(se,Je),je;if(Ye===null){for(;JeJe?(ln=Ye,Ye=null):ln=Ye.sibling;var bo=de(se,Ye,wt.value,ke);if(bo===null){Ye===null&&(Ye=ln);break}i&&Ye&&bo.alternate===null&&l(se,Ye),re=T(bo,re,Je),lt===null?je=bo:lt.sibling=bo,lt=bo,Ye=ln}if(wt.done)return f(se,Ye),Et&&Ho(se,Je),je;if(Ye===null){for(;!wt.done;Je++,wt=ue.next())wt=Ae(se,wt.value,ke),wt!==null&&(re=T(wt,re,Je),lt===null?je=wt:lt.sibling=wt,lt=wt);return Et&&Ho(se,Je),je}for(Ye=h(Ye);!wt.done;Je++,wt=ue.next())wt=ge(Ye,se,Je,wt.value,ke),wt!==null&&(i&&wt.alternate!==null&&Ye.delete(wt.key===null?Je:wt.key),re=T(wt,re,Je),lt===null?je=wt:lt.sibling=wt,lt=wt);return i&&Ye.forEach(function(J6){return l(se,J6)}),Et&&Ho(se,Je),je}function Vt(se,re,ue,ke){if(typeof ue=="object"&&ue!==null&&ue.type===c&&ue.key===null&&(ue=ue.props.children),typeof ue=="object"&&ue!==null){switch(ue.$$typeof){case s:e:{for(var je=ue.key;re!==null;){if(re.key===je){if(je=ue.type,je===c){if(re.tag===7){f(se,re.sibling),ke=v(re,ue.props.children),ke.return=se,se=ke;break e}}else if(re.elementType===je||typeof je=="object"&&je!==null&&je.$$typeof===x&&p1(je)===re.type){f(se,re.sibling),ke=v(re,ue.props),wl(ke,ue),ke.return=se,se=ke;break e}f(se,re);break}else l(se,re);re=re.sibling}ue.type===c?(ke=ei(ue.props.children,se.mode,ke,ue.key),ke.return=se,se=ke):(ke=Hc(ue.type,ue.key,ue.props,null,se.mode,ke),wl(ke,ue),ke.return=se,se=ke)}return F(se);case u:e:{for(je=ue.key;re!==null;){if(re.key===je)if(re.tag===4&&re.stateNode.containerInfo===ue.containerInfo&&re.stateNode.implementation===ue.implementation){f(se,re.sibling),ke=v(re,ue.children||[]),ke.return=se,se=ke;break e}else{f(se,re);break}else l(se,re);re=re.sibling}ke=ah(ue,se.mode,ke),ke.return=se,se=ke}return F(se);case x:return je=ue._init,ue=je(ue._payload),Vt(se,re,ue,ke)}if(M(ue))return qe(se,re,ue,ke);if(C(ue)){if(je=C(ue),typeof je!="function")throw Error(r(150));return ue=je.call(ue),nt(se,re,ue,ke)}if(typeof ue.then=="function")return Vt(se,re,kc(ue),ke);if(ue.$$typeof===b)return Vt(se,re,Uc(se,ue),ke);Tc(se,ue)}return typeof ue=="string"&&ue!==""||typeof ue=="number"||typeof ue=="bigint"?(ue=""+ue,re!==null&&re.tag===6?(f(se,re.sibling),ke=v(re,ue),ke.return=se,se=ke):(f(se,re),ke=rh(ue,se.mode,ke),ke.return=se,se=ke),F(se)):f(se,re)}return function(se,re,ue,ke){try{El=0;var je=Vt(se,re,ue,ke);return Hi=null,je}catch(Ye){if(Ye===vl)throw Ye;var lt=hr(29,Ye,null,se.mode);return lt.lanes=ke,lt.return=se,lt}finally{}}}var qo=g1(!0),h1=g1(!1),$i=ae(null),Ac=ae(0);function m1(i,l){i=Ca,ie(Ac,i),ie($i,l),Ca=i|l.baseLanes}function cg(){ie(Ac,Ca),ie($i,$i.current)}function dg(){Ca=Ac.current,ye($i),ye(Ac)}var fr=ae(null),Vr=null;function Qa(i){var l=i.alternate;ie(en,en.current&1),ie(fr,i),Vr===null&&(l===null||$i.current!==null||l.memoizedState!==null)&&(Vr=i)}function b1(i){if(i.tag===22){if(ie(en,en.current),ie(fr,i),Vr===null){var l=i.alternate;l!==null&&l.memoizedState!==null&&(Vr=i)}}else Ja()}function Ja(){ie(en,en.current),ie(fr,fr.current)}function ya(i){ye(fr),Vr===i&&(Vr=null),ye(en)}var en=ae(0);function Rc(i){for(var l=i;l!==null;){if(l.tag===13){var f=l.memoizedState;if(f!==null&&(f=f.dehydrated,f===null||f.data==="$?"||f.data==="$!"))return l}else if(l.tag===19&&l.memoizedProps.revealOrder!==void 0){if((l.flags&128)!==0)return l}else if(l.child!==null){l.child.return=l,l=l.child;continue}if(l===i)break;for(;l.sibling===null;){if(l.return===null||l.return===i)return null;l=l.return}l.sibling.return=l.return,l=l.sibling}return null}var U$=typeof AbortController<"u"?AbortController:function(){var i=[],l=this.signal={aborted:!1,addEventListener:function(f,h){i.push(h)}};this.abort=function(){l.aborted=!0,i.forEach(function(f){return f()})}},j$=e.unstable_scheduleCallback,G$=e.unstable_NormalPriority,tn={$$typeof:b,Consumer:null,Provider:null,_currentValue:null,_currentValue2:null,_threadCount:0};function fg(){return{controller:new U$,data:new Map,refCount:0}}function xl(i){i.refCount--,i.refCount===0&&j$(G$,function(){i.controller.abort()})}var kl=null,pg=0,qi=0,Vi=null;function H$(i,l){if(kl===null){var f=kl=[];pg=0,qi=vh(),Vi={status:"pending",value:void 0,then:function(h){f.push(h)}}}return pg++,l.then(y1,y1),l}function y1(){if(--pg===0&&kl!==null){Vi!==null&&(Vi.status="fulfilled");var i=kl;kl=null,qi=0,Vi=null;for(var l=0;lT?T:8;var F=D.T,q={};D.T=q,Ng(i,!1,l,f);try{var X=v(),oe=D.S;if(oe!==null&&oe(q,X),X!==null&&typeof X=="object"&&typeof X.then=="function"){var be=$$(X,h);Rl(i,l,be,Zn(i))}else Rl(i,l,h,Zn(i))}catch(Ae){Rl(i,l,{then:function(){},status:"rejected",reason:Ae},Zn())}finally{K.p=T,D.T=F}}function K$(){}function Cg(i,l,f,h){if(i.tag!==5)throw Error(r(476));var v=K1(i).queue;Y1(i,v,l,ee,f===null?K$:function(){return X1(i),f(h)})}function K1(i){var l=i.memoizedState;if(l!==null)return l;l={memoizedState:ee,baseState:ee,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:va,lastRenderedState:ee},next:null};var f={};return l.next={memoizedState:f,baseState:f,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:va,lastRenderedState:f},next:null},i.memoizedState=l,i=i.alternate,i!==null&&(i.memoizedState=l),l}function X1(i){var l=K1(i).next.queue;Rl(i,l,{},Zn())}function _g(){return En(Wl)}function Z1(){return Xt().memoizedState}function Q1(){return Xt().memoizedState}function X$(i){for(var l=i.return;l!==null;){switch(l.tag){case 24:case 3:var f=Zn();i=ao(f);var h=oo(l,i,f);h!==null&&(On(h,l,f),Nl(h,l,f)),l={cache:fg()},i.payload=l;return}l=l.return}}function Z$(i,l,f){var h=Zn();f={lane:h,revertLane:0,action:f,hasEagerState:!1,eagerState:null,next:null},Pc(i)?eR(l,f):(f=og(i,l,f,h),f!==null&&(On(f,i,h),tR(f,l,h)))}function J1(i,l,f){var h=Zn();Rl(i,l,f,h)}function Rl(i,l,f,h){var v={lane:h,revertLane:0,action:f,hasEagerState:!1,eagerState:null,next:null};if(Pc(i))eR(l,v);else{var T=i.alternate;if(i.lanes===0&&(T===null||T.lanes===0)&&(T=l.lastRenderedReducer,T!==null))try{var F=l.lastRenderedState,q=T(F,f);if(v.hasEagerState=!0,v.eagerState=q,Wn(q,F))return vc(i,l,v,0),Dt===null&&yc(),!1}catch{}finally{}if(f=og(i,l,v,h),f!==null)return On(f,i,h),tR(f,l,h),!0}return!1}function Ng(i,l,f,h){if(h={lane:2,revertLane:vh(),action:h,hasEagerState:!1,eagerState:null,next:null},Pc(i)){if(l)throw Error(r(479))}else l=og(i,f,h,2),l!==null&&On(l,i,2)}function Pc(i){var l=i.alternate;return i===st||l!==null&&l===st}function eR(i,l){Wi=_c=!0;var f=i.pending;f===null?l.next=l:(l.next=f.next,f.next=l),i.pending=l}function tR(i,l,f){if((f&4194176)!==0){var h=l.lanes;h&=i.pendingLanes,f|=h,l.lanes=f,Rr(i,f)}}var Wr={readContext:En,use:Ic,useCallback:Wt,useContext:Wt,useEffect:Wt,useImperativeHandle:Wt,useLayoutEffect:Wt,useInsertionEffect:Wt,useMemo:Wt,useReducer:Wt,useRef:Wt,useState:Wt,useDebugValue:Wt,useDeferredValue:Wt,useTransition:Wt,useSyncExternalStore:Wt,useId:Wt};Wr.useCacheRefresh=Wt,Wr.useMemoCache=Wt,Wr.useHostTransitionStatus=Wt,Wr.useFormState=Wt,Wr.useActionState=Wt,Wr.useOptimistic=Wt;var Yo={readContext:En,use:Ic,useCallback:function(i,l){return zn().memoizedState=[i,l===void 0?null:l],i},useContext:En,useEffect:U1,useImperativeHandle:function(i,l,f){f=f!=null?f.concat([i]):null,Lc(4194308,4,H1.bind(null,l,i),f)},useLayoutEffect:function(i,l){return Lc(4194308,4,i,l)},useInsertionEffect:function(i,l){Lc(4,2,i,l)},useMemo:function(i,l){var f=zn();l=l===void 0?null:l;var h=i();if(Wo){ot(!0);try{i()}finally{ot(!1)}}return f.memoizedState=[h,l],h},useReducer:function(i,l,f){var h=zn();if(f!==void 0){var v=f(l);if(Wo){ot(!0);try{f(l)}finally{ot(!1)}}}else v=l;return h.memoizedState=h.baseState=v,i={pending:null,lanes:0,dispatch:null,lastRenderedReducer:i,lastRenderedState:v},h.queue=i,i=i.dispatch=Z$.bind(null,st,i),[h.memoizedState,i]},useRef:function(i){var l=zn();return i={current:i},l.memoizedState=i},useState:function(i){i=xg(i);var l=i.queue,f=J1.bind(null,st,l);return l.dispatch=f,[i.memoizedState,f]},useDebugValue:Ag,useDeferredValue:function(i,l){var f=zn();return Rg(f,i,l)},useTransition:function(){var i=xg(!1);return i=Y1.bind(null,st,i.queue,!0,!1),zn().memoizedState=i,[!1,i]},useSyncExternalStore:function(i,l,f){var h=st,v=zn();if(Et){if(f===void 0)throw Error(r(407));f=f()}else{if(f=l(),Dt===null)throw Error(r(349));(bt&60)!==0||k1(h,l,f)}v.memoizedState=f;var T={value:f,getSnapshot:l};return v.queue=T,U1(A1.bind(null,h,T,i),[i]),h.flags|=2048,Ki(9,T1.bind(null,h,T,f,l),{destroy:void 0},null),f},useId:function(){var i=zn(),l=Dt.identifierPrefix;if(Et){var f=ba,h=ma;f=(h&~(1<<32-St(h)-1)).toString(32)+f,l=":"+l+"R"+f,f=Nc++,0 title"))),mn(T,h,f),T[Sn]=i,an(T),h=T;break e;case"link":var F=CC("link","href",v).get(h+(f.href||""));if(F){for(var q=0;q<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof h.is=="string"?v.createElement("select",{is:h.is}):v.createElement("select"),h.multiple?i.multiple=!0:h.size&&(i.size=h.size);break;default:i=typeof h.is=="string"?v.createElement(f,{is:h.is}):v.createElement(f)}}i[Sn]=l,i[Pn]=h;e:for(v=l.child;v!==null;){if(v.tag===5||v.tag===6)i.appendChild(v.stateNode);else if(v.tag!==4&&v.tag!==27&&v.child!==null){v.child.return=v,v=v.child;continue}if(v===l)break e;for(;v.sibling===null;){if(v.return===null||v.return===l)break e;v=v.return}v.sibling.return=v.return,v=v.sibling}l.stateNode=i;e:switch(mn(i,f,h),f){case"button":case"input":case"select":case"textarea":i=!!h.autoFocus;break e;case"img":i=!0;break e;default:i=!1}i&&Aa(l)}}return Bt(l),l.flags&=-16777217,null;case 6:if(i&&l.stateNode!=null)i.memoizedProps!==h&&Aa(l);else{if(typeof h!="string"&&l.stateNode===null)throw Error(r(166));if(i=De.current,ml(l)){if(i=l.stateNode,f=l.memoizedProps,h=null,v=Nn,v!==null)switch(v.tag){case 27:case 5:h=v.memoizedProps}i[Sn]=l,i=!!(i.nodeValue===f||h!==null&&h.suppressHydrationWarning===!0||mC(i.nodeValue,f)),i||$o(l)}else i=td(i).createTextNode(h),i[Sn]=l,l.stateNode=i}return Bt(l),null;case 13:if(h=l.memoizedState,i===null||i.memoizedState!==null&&i.memoizedState.dehydrated!==null){if(v=ml(l),h!==null&&h.dehydrated!==null){if(i===null){if(!v)throw Error(r(318));if(v=l.memoizedState,v=v!==null?v.dehydrated:null,!v)throw Error(r(317));v[Sn]=l}else bl(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;Bt(l),v=!1}else _r!==null&&(fh(_r),_r=null),v=!0;if(!v)return l.flags&256?(ya(l),l):(ya(l),null)}if(ya(l),(l.flags&128)!==0)return l.lanes=f,l;if(f=h!==null,i=i!==null&&i.memoizedState!==null,f){h=l.child,v=null,h.alternate!==null&&h.alternate.memoizedState!==null&&h.alternate.memoizedState.cachePool!==null&&(v=h.alternate.memoizedState.cachePool.pool);var T=null;h.memoizedState!==null&&h.memoizedState.cachePool!==null&&(T=h.memoizedState.cachePool.pool),T!==v&&(h.flags|=2048)}return f!==i&&f&&(l.child.flags|=8192),$c(l,l.updateQueue),Bt(l),null;case 4:return te(),i===null&&xh(l.stateNode.containerInfo),Bt(l),null;case 10:return wa(l.type),Bt(l),null;case 19:if(ye(en),v=l.memoizedState,v===null)return Bt(l),null;if(h=(l.flags&128)!==0,T=v.rendering,T===null)if(h)Fl(v,!1);else{if(qt!==0||i!==null&&(i.flags&128)!==0)for(i=l.child;i!==null;){if(T=Rc(i),T!==null){for(l.flags|=128,Fl(v,!1),i=T.updateQueue,l.updateQueue=i,$c(l,i),l.subtreeFlags=0,i=f,f=l.child;f!==null;)$R(f,i),f=f.sibling;return ie(en,en.current&1|2),l.child}i=i.sibling}v.tail!==null&&he()>qc&&(l.flags|=128,h=!0,Fl(v,!1),l.lanes=4194304)}else{if(!h)if(i=Rc(T),i!==null){if(l.flags|=128,h=!0,i=i.updateQueue,l.updateQueue=i,$c(l,i),Fl(v,!0),v.tail===null&&v.tailMode==="hidden"&&!T.alternate&&!Et)return Bt(l),null}else 2*he()-v.renderingStartTime>qc&&f!==536870912&&(l.flags|=128,h=!0,Fl(v,!1),l.lanes=4194304);v.isBackwards?(T.sibling=l.child,l.child=T):(i=v.last,i!==null?i.sibling=T:l.child=T,v.last=T)}return v.tail!==null?(l=v.tail,v.rendering=l,v.tail=l.sibling,v.renderingStartTime=he(),l.sibling=null,i=en.current,ie(en,h?i&1|2:i&1),l):(Bt(l),null);case 22:case 23:return ya(l),dg(),h=l.memoizedState!==null,i!==null?i.memoizedState!==null!==h&&(l.flags|=8192):h&&(l.flags|=8192),h?(f&536870912)!==0&&(l.flags&128)===0&&(Bt(l),l.subtreeFlags&6&&(l.flags|=8192)):Bt(l),f=l.updateQueue,f!==null&&$c(l,f.retryQueue),f=null,i!==null&&i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(f=i.memoizedState.cachePool.pool),h=null,l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(h=l.memoizedState.cachePool.pool),h!==f&&(l.flags|=2048),i!==null&&ye(Vo),null;case 24:return f=null,i!==null&&(f=i.memoizedState.cache),l.memoizedState.cache!==f&&(l.flags|=2048),wa(tn),Bt(l),null;case 25:return null}throw Error(r(156,l.tag))}function a6(i,l){switch(sg(l),l.tag){case 1:return i=l.flags,i&65536?(l.flags=i&-65537|128,l):null;case 3:return wa(tn),te(),i=l.flags,(i&65536)!==0&&(i&128)===0?(l.flags=i&-65537|128,l):null;case 26:case 27:case 5:return Te(l),null;case 13:if(ya(l),i=l.memoizedState,i!==null&&i.dehydrated!==null){if(l.alternate===null)throw Error(r(340));bl()}return i=l.flags,i&65536?(l.flags=i&-65537|128,l):null;case 19:return ye(en),null;case 4:return te(),null;case 10:return wa(l.type),null;case 22:case 23:return ya(l),dg(),i!==null&&ye(Vo),i=l.flags,i&65536?(l.flags=i&-65537|128,l):null;case 24:return wa(tn),null;case 25:return null;default:return null}}function WR(i,l){switch(sg(l),l.tag){case 3:wa(tn),te();break;case 26:case 27:case 5:Te(l);break;case 4:te();break;case 13:ya(l);break;case 19:ye(en);break;case 10:wa(l.type);break;case 22:case 23:ya(l),dg(),i!==null&&ye(Vo);break;case 24:wa(tn)}}var o6={getCacheForType:function(i){var l=En(tn),f=l.data.get(i);return f===void 0&&(f=i(),l.data.set(i,f)),f}},i6=typeof WeakMap=="function"?WeakMap:Map,Ut=0,Dt=null,ct=null,bt=0,Lt=0,Xn=null,Ra=!1,Ji=!1,oh=!1,Ca=0,qt=0,co=0,ti=0,ih=0,mr=0,es=0,zl=null,Yr=null,sh=!1,lh=0,qc=1/0,Vc=null,fo=null,Wc=!1,ni=null,Bl=0,uh=0,ch=null,Ul=0,dh=null;function Zn(){if((Ut&2)!==0&&bt!==0)return bt&-bt;if(D.T!==null){var i=qi;return i!==0?i:vh()}return gA()}function YR(){mr===0&&(mr=(bt&536870912)===0||Et?_t():536870912);var i=fr.current;return i!==null&&(i.flags|=32),mr}function On(i,l,f){(i===Dt&&Lt===2||i.cancelPendingCommit!==null)&&(ts(i,0),_a(i,bt,mr,!1)),Ln(i,f),((Ut&2)===0||i!==Dt)&&(i===Dt&&((Ut&2)===0&&(ti|=f),qt===4&&_a(i,bt,mr,!1)),Kr(i))}function KR(i,l,f){if((Ut&6)!==0)throw Error(r(327));var h=!f&&(l&60)===0&&(l&i.expiredLanes)===0||Xe(i,l),v=h?u6(i,l):hh(i,l,!0),T=h;do{if(v===0){Ji&&!h&&_a(i,l,0,!1);break}else if(v===6)_a(i,l,0,!Ra);else{if(f=i.current.alternate,T&&!s6(f)){v=hh(i,l,!1),T=!1;continue}if(v===2){if(T=l,i.errorRecoveryDisabledLanes&T)var F=0;else F=i.pendingLanes&-536870913,F=F!==0?F:F&536870912?536870912:0;if(F!==0){l=F;e:{var q=i;v=zl;var X=q.current.memoizedState.isDehydrated;if(X&&(ts(q,F).flags|=256),F=hh(q,F,!1),F!==2){if(oh&&!X){q.errorRecoveryDisabledLanes|=T,ti|=T,v=4;break e}T=Yr,Yr=v,T!==null&&fh(T)}v=F}if(T=!1,v!==2)continue}}if(v===1){ts(i,0),_a(i,l,0,!0);break}e:{switch(h=i,v){case 0:case 1:throw Error(r(345));case 4:if((l&4194176)===l){_a(h,l,mr,!Ra);break e}break;case 2:Yr=null;break;case 3:case 5:break;default:throw Error(r(329))}if(h.finishedWork=f,h.finishedLanes=l,(l&62914560)===l&&(T=lh+300-he(),10f?32:f,D.T=null,ni===null)var T=!1;else{f=ch,ch=null;var F=ni,q=Bl;if(ni=null,Bl=0,(Ut&6)!==0)throw Error(r(331));var X=Ut;if(Ut|=4,GR(F.current),BR(F,F.current,q,f),Ut=X,jl(0,!1),et&&typeof et.onPostCommitFiberRoot=="function")try{et.onPostCommitFiberRoot(ht,F)}catch{}T=!0}return T}finally{K.p=v,D.T=h,aC(i,l)}}return!1}function oC(i,l,f){l=ur(f,l),l=Dg(i.stateNode,l,2),i=oo(i,l,2),i!==null&&(Ln(i,2),Kr(i))}function Nt(i,l,f){if(i.tag===3)oC(i,i,f);else for(;l!==null;){if(l.tag===3){oC(l,i,f);break}else if(l.tag===1){var h=l.stateNode;if(typeof l.type.getDerivedStateFromError=="function"||typeof h.componentDidCatch=="function"&&(fo===null||!fo.has(h))){i=ur(f,i),f=lR(2),h=oo(l,f,2),h!==null&&(uR(f,h,l,i),Ln(h,2),Kr(h));break}}l=l.return}}function mh(i,l,f){var h=i.pingCache;if(h===null){h=i.pingCache=new i6;var v=new Set;h.set(l,v)}else v=h.get(l),v===void 0&&(v=new Set,h.set(l,v));v.has(f)||(oh=!0,v.add(f),i=f6.bind(null,i,l,f),l.then(i,i))}function f6(i,l,f){var h=i.pingCache;h!==null&&h.delete(l),i.pingedLanes|=i.suspendedLanes&f,i.warmLanes&=~f,Dt===i&&(bt&f)===f&&(qt===4||qt===3&&(bt&62914560)===bt&&300>he()-lh?(Ut&2)===0&&ts(i,0):ih|=f,es===bt&&(es=0)),Kr(i)}function iC(i,l){l===0&&(l=Dn()),i=Za(i,l),i!==null&&(Ln(i,l),Kr(i))}function p6(i){var l=i.memoizedState,f=0;l!==null&&(f=l.retryLane),iC(i,f)}function g6(i,l){var f=0;switch(i.tag){case 13:var h=i.stateNode,v=i.memoizedState;v!==null&&(f=v.retryLane);break;case 19:h=i.stateNode;break;case 22:h=i.stateNode._retryCache;break;default:throw Error(r(314))}h!==null&&h.delete(l),iC(i,f)}function h6(i,l){return xe(i,l)}var Xc=null,as=null,bh=!1,Zc=!1,yh=!1,ri=0;function Kr(i){i!==as&&i.next===null&&(as===null?Xc=as=i:as=as.next=i),Zc=!0,bh||(bh=!0,b6(m6))}function jl(i,l){if(!yh&&Zc){yh=!0;do for(var f=!1,h=Xc;h!==null;){if(i!==0){var v=h.pendingLanes;if(v===0)var T=0;else{var F=h.suspendedLanes,q=h.pingedLanes;T=(1<<31-St(42|i)+1)-1,T&=v&~(F&~q),T=T&201326677?T&201326677|1:T?T|2:0}T!==0&&(f=!0,uC(h,T))}else T=bt,T=fa(h,h===Dt?T:0),(T&3)===0||Xe(h,T)||(f=!0,uC(h,T));h=h.next}while(f);yh=!1}}function m6(){Zc=bh=!1;var i=0;ri!==0&&(T6()&&(i=ri),ri=0);for(var l=he(),f=null,h=Xc;h!==null;){var v=h.next,T=sC(h,l);T===0?(h.next=null,f===null?Xc=v:f.next=v,v===null&&(as=f)):(f=h,(i!==0||(T&3)!==0)&&(Zc=!0)),h=v}jl(i)}function sC(i,l){for(var f=i.suspendedLanes,h=i.pingedLanes,v=i.expirationTimes,T=i.pendingLanes&-62914561;0"u"?null:document;function kC(i,l,f){var h=is;if(h&&typeof l=="string"&&l){var v=sr(l);v='link[rel="'+i+'"][href="'+v+'"]',typeof f=="string"&&(v+='[crossorigin="'+f+'"]'),xC.has(v)||(xC.add(v),i={rel:i,crossOrigin:f,href:l},h.querySelector(v)===null&&(l=h.createElement("link"),mn(l,"link",i),an(l),h.head.appendChild(l)))}}function D6(i){Na.D(i),kC("dns-prefetch",i,null)}function L6(i,l){Na.C(i,l),kC("preconnect",i,l)}function M6(i,l,f){Na.L(i,l,f);var h=is;if(h&&i&&l){var v='link[rel="preload"][as="'+sr(l)+'"]';l==="image"&&f&&f.imageSrcSet?(v+='[imagesrcset="'+sr(f.imageSrcSet)+'"]',typeof f.imageSizes=="string"&&(v+='[imagesizes="'+sr(f.imageSizes)+'"]')):v+='[href="'+sr(i)+'"]';var T=v;switch(l){case"style":T=ss(i);break;case"script":T=ls(i)}br.has(T)||(i=L({rel:"preload",href:l==="image"&&f&&f.imageSrcSet?void 0:i,as:l},f),br.set(T,i),h.querySelector(v)!==null||l==="style"&&h.querySelector($l(T))||l==="script"&&h.querySelector(ql(T))||(l=h.createElement("link"),mn(l,"link",i),an(l),h.head.appendChild(l)))}}function P6(i,l){Na.m(i,l);var f=is;if(f&&i){var h=l&&typeof l.as=="string"?l.as:"script",v='link[rel="modulepreload"][as="'+sr(h)+'"][href="'+sr(i)+'"]',T=v;switch(h){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":T=ls(i)}if(!br.has(T)&&(i=L({rel:"modulepreload",href:i},l),br.set(T,i),f.querySelector(v)===null)){switch(h){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(f.querySelector(ql(T)))return}h=f.createElement("link"),mn(h,"link",i),an(h),f.head.appendChild(h)}}}function F6(i,l,f){Na.S(i,l,f);var h=is;if(h&&i){var v=Ni(h).hoistableStyles,T=ss(i);l=l||"default";var F=v.get(T);if(!F){var q={loading:0,preload:null};if(F=h.querySelector($l(T)))q.loading=5;else{i=L({rel:"stylesheet",href:i,"data-precedence":l},f),(f=br.get(T))&&Ih(i,f);var X=F=h.createElement("link");an(X),mn(X,"link",i),X._p=new Promise(function(oe,be){X.onload=oe,X.onerror=be}),X.addEventListener("load",function(){q.loading|=1}),X.addEventListener("error",function(){q.loading|=2}),q.loading|=4,rd(F,l,h)}F={type:"stylesheet",instance:F,count:1,state:q},v.set(T,F)}}}function z6(i,l){Na.X(i,l);var f=is;if(f&&i){var h=Ni(f).hoistableScripts,v=ls(i),T=h.get(v);T||(T=f.querySelector(ql(v)),T||(i=L({src:i,async:!0},l),(l=br.get(v))&&Dh(i,l),T=f.createElement("script"),an(T),mn(T,"link",i),f.head.appendChild(T)),T={type:"script",instance:T,count:1,state:null},h.set(v,T))}}function B6(i,l){Na.M(i,l);var f=is;if(f&&i){var h=Ni(f).hoistableScripts,v=ls(i),T=h.get(v);T||(T=f.querySelector(ql(v)),T||(i=L({src:i,async:!0,type:"module"},l),(l=br.get(v))&&Dh(i,l),T=f.createElement("script"),an(T),mn(T,"link",i),f.head.appendChild(T)),T={type:"script",instance:T,count:1,state:null},h.set(v,T))}}function TC(i,l,f,h){var v=(v=De.current)?nd(v):null;if(!v)throw Error(r(446));switch(i){case"meta":case"title":return null;case"style":return typeof f.precedence=="string"&&typeof f.href=="string"?(l=ss(f.href),f=Ni(v).hoistableStyles,h=f.get(l),h||(h={type:"style",instance:null,count:0,state:null},f.set(l,h)),h):{type:"void",instance:null,count:0,state:null};case"link":if(f.rel==="stylesheet"&&typeof f.href=="string"&&typeof f.precedence=="string"){i=ss(f.href);var T=Ni(v).hoistableStyles,F=T.get(i);if(F||(v=v.ownerDocument||v,F={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},T.set(i,F),(T=v.querySelector($l(i)))&&!T._p&&(F.instance=T,F.state.loading=5),br.has(i)||(f={rel:"preload",as:"style",href:f.href,crossOrigin:f.crossOrigin,integrity:f.integrity,media:f.media,hrefLang:f.hrefLang,referrerPolicy:f.referrerPolicy},br.set(i,f),T||U6(v,i,f,F.state))),l&&h===null)throw Error(r(528,""));return F}if(l&&h!==null)throw Error(r(529,""));return null;case"script":return l=f.async,f=f.src,typeof f=="string"&&l&&typeof l!="function"&&typeof l!="symbol"?(l=ls(f),f=Ni(v).hoistableScripts,h=f.get(l),h||(h={type:"script",instance:null,count:0,state:null},f.set(l,h)),h):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,i))}}function ss(i){return'href="'+sr(i)+'"'}function $l(i){return'link[rel="stylesheet"]['+i+"]"}function AC(i){return L({},i,{"data-precedence":i.precedence,precedence:null})}function U6(i,l,f,h){i.querySelector('link[rel="preload"][as="style"]['+l+"]")?h.loading=1:(l=i.createElement("link"),h.preload=l,l.addEventListener("load",function(){return h.loading|=1}),l.addEventListener("error",function(){return h.loading|=2}),mn(l,"link",f),an(l),i.head.appendChild(l))}function ls(i){return'[src="'+sr(i)+'"]'}function ql(i){return"script[async]"+i}function RC(i,l,f){if(l.count++,l.instance===null)switch(l.type){case"style":var h=i.querySelector('style[data-href~="'+sr(f.href)+'"]');if(h)return l.instance=h,an(h),h;var v=L({},f,{"data-href":f.href,"data-precedence":f.precedence,href:null,precedence:null});return h=(i.ownerDocument||i).createElement("style"),an(h),mn(h,"style",v),rd(h,f.precedence,i),l.instance=h;case"stylesheet":v=ss(f.href);var T=i.querySelector($l(v));if(T)return l.state.loading|=4,l.instance=T,an(T),T;h=AC(f),(v=br.get(v))&&Ih(h,v),T=(i.ownerDocument||i).createElement("link"),an(T);var F=T;return F._p=new Promise(function(q,X){F.onload=q,F.onerror=X}),mn(T,"link",h),l.state.loading|=4,rd(T,f.precedence,i),l.instance=T;case"script":return T=ls(f.src),(v=i.querySelector(ql(T)))?(l.instance=v,an(v),v):(h=f,(v=br.get(T))&&(h=L({},f),Dh(h,v)),i=i.ownerDocument||i,v=i.createElement("script"),an(v),mn(v,"link",h),i.head.appendChild(v),l.instance=v);case"void":return null;default:throw Error(r(443,l.type))}else l.type==="stylesheet"&&(l.state.loading&4)===0&&(h=l.instance,l.state.loading|=4,rd(h,f.precedence,i));return l.instance}function rd(i,l,f){for(var h=f.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),v=h.length?h[h.length-1]:null,T=v,F=0;F title"):null)}function j6(i,l,f){if(f===1||l.itemProp!=null)return!1;switch(i){case"meta":case"title":return!0;case"style":if(typeof l.precedence!="string"||typeof l.href!="string"||l.href==="")break;return!0;case"link":if(typeof l.rel!="string"||typeof l.href!="string"||l.href===""||l.onLoad||l.onError)break;switch(l.rel){case"stylesheet":return i=l.disabled,typeof l.precedence=="string"&&i==null;default:return!0}case"script":if(l.async&&typeof l.async!="function"&&typeof l.async!="symbol"&&!l.onLoad&&!l.onError&&l.src&&typeof l.src=="string")return!0}return!1}function NC(i){return!(i.type==="stylesheet"&&(i.state.loading&3)===0)}var Vl=null;function G6(){}function H6(i,l,f){if(Vl===null)throw Error(r(475));var h=Vl;if(l.type==="stylesheet"&&(typeof f.media!="string"||matchMedia(f.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var v=ss(f.href),T=i.querySelector($l(v));if(T){i=T._p,i!==null&&typeof i=="object"&&typeof i.then=="function"&&(h.count++,h=od.bind(h),i.then(h,h)),l.state.loading|=4,l.instance=T,an(T);return}T=i.ownerDocument||i,f=AC(f),(v=br.get(v))&&Ih(f,v),T=T.createElement("link"),an(T);var F=T;F._p=new Promise(function(q,X){F.onload=q,F.onerror=X}),mn(T,"link",f),l.instance=T}h.stylesheets===null&&(h.stylesheets=new Map),h.stylesheets.set(l,i),(i=l.state.preload)&&(l.state.loading&3)===0&&(h.count++,l=od.bind(h),i.addEventListener("load",l),i.addEventListener("error",l))}}function $6(){if(Vl===null)throw Error(r(475));var i=Vl;return i.stylesheets&&i.count===0&&Lh(i,i.stylesheets),0"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Hh.exports=dq(),Hh.exports}var pq=fq(),eu={},QC;function gq(){if(QC)return eu;QC=1,Object.defineProperty(eu,"__esModule",{value:!0}),eu.parse=s,eu.serialize=d;const e=/^[\u0021-\u003A\u003C\u003E-\u007E]+$/,t=/^[\u0021-\u003A\u003C-\u007E]*$/,n=/^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i,r=/^[\u0020-\u003A\u003D-\u007E]*$/,a=Object.prototype.toString,o=(()=>{const m=function(){};return m.prototype=Object.create(null),m})();function s(m,b){const y=new o,S=m.length;if(S<2)return y;const k=(b==null?void 0:b.decode)||p;let R=0;do{const x=m.indexOf("=",R);if(x===-1)break;const A=m.indexOf(";",R),N=A===-1?S:A;if(x>N){R=m.lastIndexOf(";",x-1)+1;continue}const O=u(m,R,x),C=c(m,x,O),_=m.slice(O,C);if(y[_]===void 0){let P=u(m,x+1,N),D=c(m,N,P);const L=k(m.slice(P,D));y[_]=L}R=N+1}while(Ry;){const S=m.charCodeAt(--b);if(S!==32&&S!==9)return b+1}return y}function d(m,b,y){const S=(y==null?void 0:y.encode)||encodeURIComponent;if(!e.test(m))throw new TypeError(`argument name is invalid: ${m}`);const k=S(b);if(!t.test(k))throw new TypeError(`argument val is invalid: ${b}`);let R=m+"="+k;if(!y)return R;if(y.maxAge!==void 0){if(!Number.isInteger(y.maxAge))throw new TypeError(`option maxAge is invalid: ${y.maxAge}`);R+="; Max-Age="+y.maxAge}if(y.domain){if(!n.test(y.domain))throw new TypeError(`option domain is invalid: ${y.domain}`);R+="; Domain="+y.domain}if(y.path){if(!r.test(y.path))throw new TypeError(`option path is invalid: ${y.path}`);R+="; Path="+y.path}if(y.expires){if(!g(y.expires)||!Number.isFinite(y.expires.valueOf()))throw new TypeError(`option expires is invalid: ${y.expires}`);R+="; Expires="+y.expires.toUTCString()}if(y.httpOnly&&(R+="; HttpOnly"),y.secure&&(R+="; Secure"),y.partitioned&&(R+="; Partitioned"),y.priority)switch(typeof y.priority=="string"?y.priority.toLowerCase():void 0){case"low":R+="; Priority=Low";break;case"medium":R+="; Priority=Medium";break;case"high":R+="; Priority=High";break;default:throw new TypeError(`option priority is invalid: ${y.priority}`)}if(y.sameSite)switch(typeof y.sameSite=="string"?y.sameSite.toLowerCase():y.sameSite){case!0:case"strict":R+="; SameSite=Strict";break;case"lax":R+="; SameSite=Lax";break;case"none":R+="; SameSite=None";break;default:throw new TypeError(`option sameSite is invalid: ${y.sameSite}`)}return R}function p(m){if(m.indexOf("%")===-1)return m;try{return decodeURIComponent(m)}catch{return m}}function g(m){return a.call(m)==="[object Date]"}return eu}gq();/** +`+f.stack}}function z(i){var l=i,f=i;if(i.alternate)for(;l.return;)l=l.return;else{i=l;do l=i,(l.flags&4098)!==0&&(f=l.return),i=l.return;while(i)}return l.tag===3?f:null}function Y(i){if(i.tag===13){var l=i.memoizedState;if(l===null&&(i=i.alternate,i!==null&&(l=i.memoizedState)),l!==null)return l.dehydrated}return null}function L(i){if(z(i)!==i)throw Error(r(188))}function V(i){var l=i.alternate;if(!l){if(l=z(i),l===null)throw Error(r(188));return l!==i?null:i}for(var f=i,h=l;;){var v=f.return;if(v===null)break;var T=v.alternate;if(T===null){if(h=v.return,h!==null){f=h;continue}break}if(v.child===T.child){for(T=v.child;T;){if(T===f)return L(v),i;if(T===h)return L(v),l;T=T.sibling}throw Error(r(188))}if(f.return!==h.return)f=v,h=T;else{for(var F=!1,q=v.child;q;){if(q===f){F=!0,f=v,h=T;break}if(q===h){F=!0,h=v,f=T;break}q=q.sibling}if(!F){for(q=T.child;q;){if(q===f){F=!0,f=T,h=v;break}if(q===h){F=!0,h=T,f=v;break}q=q.sibling}if(!F)throw Error(r(189))}}if(f.alternate!==h)throw Error(r(190))}if(f.tag!==3)throw Error(r(188));return f.stateNode.current===f?i:l}function B(i){var l=i.tag;if(l===5||l===26||l===27||l===6)return i;for(i=i.child;i!==null;){if(l=B(i),l!==null)return l;i=i.sibling}return null}var M=Array.isArray,K=n.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,ee={pending:!1,data:null,method:null,action:null},Z=[],J=-1;function ae(i){return{current:i}}function ye(i){0>J||(i.current=Z[J],Z[J]=null,J--)}function ie(i,l){J++,Z[J]=i.current,i.current=l}var Ee=ae(null),Se=ae(null),De=ae(null),Ce=ae(null);function we(i,l){switch(ie(De,l),ie(Se,i),ie(Ee,null),i=l.nodeType,i){case 9:case 11:l=(l=l.documentElement)&&(l=l.namespaceURI)?bC(l):0;break;default:if(i=i===8?l.parentNode:l,l=i.tagName,i=i.namespaceURI)i=bC(i),l=yC(i,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}ye(Ee),ie(Ee,l)}function te(){ye(Ee),ye(Se),ye(De)}function fe(i){i.memoizedState!==null&&ie(Ce,i);var l=Ee.current,f=yC(l,i.type);l!==f&&(ie(Se,i),ie(Ee,f))}function Te(i){Se.current===i&&(ye(Ee),ye(Se)),Ce.current===i&&(ye(Ce),Wl._currentValue=ee)}var me=Object.prototype.hasOwnProperty,xe=e.unstable_scheduleCallback,le=e.unstable_cancelCallback,ze=e.unstable_shouldYield,Be=e.unstable_requestPaint,he=e.unstable_now,Ne=e.unstable_getCurrentPriorityLevel,ne=e.unstable_ImmediatePriority,ce=e.unstable_UserBlockingPriority,_e=e.unstable_NormalPriority,Pe=e.unstable_LowPriority,We=e.unstable_IdlePriority,yt=e.log,kt=e.unstable_setDisableYieldValue,ht=null,et=null;function Tt(i){if(et&&typeof et.onCommitFiberRoot=="function")try{et.onCommitFiberRoot(ht,i,void 0,(i.current.flags&128)===128)}catch{}}function ot(i){if(typeof yt=="function"&&kt(i),et&&typeof et.setStrictMode=="function")try{et.setStrictMode(ht,i)}catch{}}var vt=Math.clz32?Math.clz32:Ft,Ht=Math.log,pn=Math.LN2;function Ft(i){return i>>>=0,i===0?32:31-(Ht(i)/pn|0)|0}var ar=128,Hr=4194304;function Jt(i){var l=i&42;if(l!==0)return l;switch(i&-i){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return i&4194176;case 4194304:case 8388608:case 16777216:case 33554432:return i&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return i}}function fa(i,l){var f=i.pendingLanes;if(f===0)return 0;var h=0,v=i.suspendedLanes,T=i.pingedLanes,F=i.warmLanes;i=i.finishedLanes!==0;var q=f&134217727;return q!==0?(f=q&~v,f!==0?h=Jt(f):(T&=q,T!==0?h=Jt(T):i||(F=q&~F,F!==0&&(h=Jt(F))))):(q=f&~v,q!==0?h=Jt(q):T!==0?h=Jt(T):i||(F=f&~F,F!==0&&(h=Jt(F)))),h===0?0:l!==0&&l!==h&&(l&v)===0&&(v=h&-h,F=l&-l,v>=F||v===32&&(F&4194176)!==0)?l:h}function Xe(i,l){return(i.pendingLanes&~(i.suspendedLanes&~i.pingedLanes)&l)===0}function mt(i,l){switch(i){case 1:case 2:case 4:case 8:return l+250;case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return l+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function _t(){var i=ar;return ar<<=1,(ar&4194176)===0&&(ar=128),i}function Dn(){var i=Hr;return Hr<<=1,(Hr&62914560)===0&&(Hr=4194304),i}function _n(i){for(var l=[],f=0;31>f;f++)l.push(i);return l}function Ln(i,l){i.pendingLanes|=l,l!==268435456&&(i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0)}function pa(i,l,f,h,v,T){var F=i.pendingLanes;i.pendingLanes=f,i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0,i.expiredLanes&=f,i.entangledLanes&=f,i.errorRecoveryDisabledLanes&=f,i.shellSuspendCounter=0;var q=i.entanglements,X=i.expirationTimes,oe=i.hiddenUpdates;for(f=F&~f;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),HH=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),yA={},vA={};function $H(i){return me.call(vA,i)?!0:me.call(yA,i)?!1:HH.test(i)?vA[i]=!0:(yA[i]=!0,!1)}function sc(i,l,f){if($H(l))if(f===null)i.removeAttribute(l);else{switch(typeof f){case"undefined":case"function":case"symbol":i.removeAttribute(l);return;case"boolean":var h=l.toLowerCase().slice(0,5);if(h!=="data-"&&h!=="aria-"){i.removeAttribute(l);return}}i.setAttribute(l,""+f)}}function lc(i,l,f){if(f===null)i.removeAttribute(l);else{switch(typeof f){case"undefined":case"function":case"symbol":case"boolean":i.removeAttribute(l);return}i.setAttribute(l,""+f)}}function ha(i,l,f,h){if(h===null)i.removeAttribute(f);else{switch(typeof h){case"undefined":case"function":case"symbol":case"boolean":i.removeAttribute(f);return}i.setAttributeNS(l,f,""+h)}}function or(i){switch(typeof i){case"bigint":case"boolean":case"number":case"string":case"undefined":return i;case"object":return i;default:return""}}function SA(i){var l=i.type;return(i=i.nodeName)&&i.toLowerCase()==="input"&&(l==="checkbox"||l==="radio")}function qH(i){var l=SA(i)?"checked":"value",f=Object.getOwnPropertyDescriptor(i.constructor.prototype,l),h=""+i[l];if(!i.hasOwnProperty(l)&&typeof f<"u"&&typeof f.get=="function"&&typeof f.set=="function"){var v=f.get,T=f.set;return Object.defineProperty(i,l,{configurable:!0,get:function(){return v.call(this)},set:function(F){h=""+F,T.call(this,F)}}),Object.defineProperty(i,l,{enumerable:f.enumerable}),{getValue:function(){return h},setValue:function(F){h=""+F},stopTracking:function(){i._valueTracker=null,delete i[l]}}}}function uc(i){i._valueTracker||(i._valueTracker=qH(i))}function EA(i){if(!i)return!1;var l=i._valueTracker;if(!l)return!0;var f=l.getValue(),h="";return i&&(h=SA(i)?i.checked?"true":"false":i.value),i=h,i!==f?(l.setValue(i),!0):!1}function cc(i){if(i=i||(typeof document<"u"?document:void 0),typeof i>"u")return null;try{return i.activeElement||i.body}catch{return i.body}}var VH=/[\n"\\]/g;function ir(i){return i.replace(VH,function(l){return"\\"+l.charCodeAt(0).toString(16)+" "})}function Bp(i,l,f,h,v,T,F,q){i.name="",F!=null&&typeof F!="function"&&typeof F!="symbol"&&typeof F!="boolean"?i.type=F:i.removeAttribute("type"),l!=null?F==="number"?(l===0&&i.value===""||i.value!=l)&&(i.value=""+or(l)):i.value!==""+or(l)&&(i.value=""+or(l)):F!=="submit"&&F!=="reset"||i.removeAttribute("value"),l!=null?Up(i,F,or(l)):f!=null?Up(i,F,or(f)):h!=null&&i.removeAttribute("value"),v==null&&T!=null&&(i.defaultChecked=!!T),v!=null&&(i.checked=v&&typeof v!="function"&&typeof v!="symbol"),q!=null&&typeof q!="function"&&typeof q!="symbol"&&typeof q!="boolean"?i.name=""+or(q):i.removeAttribute("name")}function wA(i,l,f,h,v,T,F,q){if(T!=null&&typeof T!="function"&&typeof T!="symbol"&&typeof T!="boolean"&&(i.type=T),l!=null||f!=null){if(!(T!=="submit"&&T!=="reset"||l!=null))return;f=f!=null?""+or(f):"",l=l!=null?""+or(l):f,q||l===i.value||(i.value=l),i.defaultValue=l}h=h??v,h=typeof h!="function"&&typeof h!="symbol"&&!!h,i.checked=q?i.checked:!!h,i.defaultChecked=!!h,F!=null&&typeof F!="function"&&typeof F!="symbol"&&typeof F!="boolean"&&(i.name=F)}function Up(i,l,f){l==="number"&&cc(i.ownerDocument)===i||i.defaultValue===""+f||(i.defaultValue=""+f)}function Ii(i,l,f,h){if(i=i.options,l){l={};for(var v=0;v=dl),MA=" ",PA=!1;function FA(i,l){switch(i){case"keyup":return S$.indexOf(l.keyCode)!==-1;case"keydown":return l.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function zA(i){return i=i.detail,typeof i=="object"&&"data"in i?i.data:null}var Pi=!1;function w$(i,l){switch(i){case"compositionend":return zA(l);case"keypress":return l.which!==32?null:(PA=!0,MA);case"textInput":return i=l.data,i===MA&&PA?null:i;default:return null}}function x$(i,l){if(Pi)return i==="compositionend"||!Zp&&FA(i,l)?(i=_A(),fc=Vp=Xa=null,Pi=!1,i):null;switch(i){case"paste":return null;case"keypress":if(!(l.ctrlKey||l.altKey||l.metaKey)||l.ctrlKey&&l.altKey){if(l.char&&1=l)return{node:f,offset:l-i};i=h}e:{for(;f;){if(f.nextSibling){f=f.nextSibling;break e}f=f.parentNode}f=void 0}f=VA(f)}}function YA(i,l){return i&&l?i===l?!0:i&&i.nodeType===3?!1:l&&l.nodeType===3?YA(i,l.parentNode):"contains"in i?i.contains(l):i.compareDocumentPosition?!!(i.compareDocumentPosition(l)&16):!1:!1}function KA(i){i=i!=null&&i.ownerDocument!=null&&i.ownerDocument.defaultView!=null?i.ownerDocument.defaultView:window;for(var l=cc(i.document);l instanceof i.HTMLIFrameElement;){try{var f=typeof l.contentWindow.location.href=="string"}catch{f=!1}if(f)i=l.contentWindow;else break;l=cc(i.document)}return l}function eg(i){var l=i&&i.nodeName&&i.nodeName.toLowerCase();return l&&(l==="input"&&(i.type==="text"||i.type==="search"||i.type==="tel"||i.type==="url"||i.type==="password")||l==="textarea"||i.contentEditable==="true")}function O$(i,l){var f=KA(l);l=i.focusedElem;var h=i.selectionRange;if(f!==l&&l&&l.ownerDocument&&YA(l.ownerDocument.documentElement,l)){if(h!==null&&eg(l)){if(i=h.start,f=h.end,f===void 0&&(f=i),"selectionStart"in l)l.selectionStart=i,l.selectionEnd=Math.min(f,l.value.length);else if(f=(i=l.ownerDocument||document)&&i.defaultView||window,f.getSelection){f=f.getSelection();var v=l.textContent.length,T=Math.min(h.start,v);h=h.end===void 0?T:Math.min(h.end,v),!f.extend&&T>h&&(v=h,h=T,T=v),v=WA(l,T);var F=WA(l,h);v&&F&&(f.rangeCount!==1||f.anchorNode!==v.node||f.anchorOffset!==v.offset||f.focusNode!==F.node||f.focusOffset!==F.offset)&&(i=i.createRange(),i.setStart(v.node,v.offset),f.removeAllRanges(),T>h?(f.addRange(i),f.extend(F.node,F.offset)):(i.setEnd(F.node,F.offset),f.addRange(i)))}}for(i=[],f=l;f=f.parentNode;)f.nodeType===1&&i.push({element:f,left:f.scrollLeft,top:f.scrollTop});for(typeof l.focus=="function"&&l.focus(),l=0;l=document.documentMode,Fi=null,tg=null,hl=null,ng=!1;function XA(i,l,f){var h=f.window===f?f.document:f.nodeType===9?f:f.ownerDocument;ng||Fi==null||Fi!==cc(h)||(h=Fi,"selectionStart"in h&&eg(h)?h={start:h.selectionStart,end:h.selectionEnd}:(h=(h.ownerDocument&&h.ownerDocument.defaultView||window).getSelection(),h={anchorNode:h.anchorNode,anchorOffset:h.anchorOffset,focusNode:h.focusNode,focusOffset:h.focusOffset}),hl&&gl(hl,h)||(hl=h,h=Jc(tg,"onSelect"),0>=F,v-=F,ma=1<<32-vt(l)+v|f<Je?(ln=Ye,Ye=null):ln=Ye.sibling;var Et=de(se,Ye,ue[Je],ke);if(Et===null){Ye===null&&(Ye=ln);break}i&&Ye&&Et.alternate===null&&l(se,Ye),re=T(Et,re,Je),lt===null?je=Et:lt.sibling=Et,lt=Et,Ye=ln}if(Je===ue.length)return f(se,Ye),St&&Ho(se,Je),je;if(Ye===null){for(;JeJe?(ln=Ye,Ye=null):ln=Ye.sibling;var bo=de(se,Ye,Et.value,ke);if(bo===null){Ye===null&&(Ye=ln);break}i&&Ye&&bo.alternate===null&&l(se,Ye),re=T(bo,re,Je),lt===null?je=bo:lt.sibling=bo,lt=bo,Ye=ln}if(Et.done)return f(se,Ye),St&&Ho(se,Je),je;if(Ye===null){for(;!Et.done;Je++,Et=ue.next())Et=Ae(se,Et.value,ke),Et!==null&&(re=T(Et,re,Je),lt===null?je=Et:lt.sibling=Et,lt=Et);return St&&Ho(se,Je),je}for(Ye=h(Ye);!Et.done;Je++,Et=ue.next())Et=ge(Ye,se,Je,Et.value,ke),Et!==null&&(i&&Et.alternate!==null&&Ye.delete(Et.key===null?Je:Et.key),re=T(Et,re,Je),lt===null?je=Et:lt.sibling=Et,lt=Et);return i&&Ye.forEach(function(K6){return l(se,K6)}),St&&Ho(se,Je),je}function Vt(se,re,ue,ke){if(typeof ue=="object"&&ue!==null&&ue.type===c&&ue.key===null&&(ue=ue.props.children),typeof ue=="object"&&ue!==null){switch(ue.$$typeof){case s:e:{for(var je=ue.key;re!==null;){if(re.key===je){if(je=ue.type,je===c){if(re.tag===7){f(se,re.sibling),ke=v(re,ue.props.children),ke.return=se,se=ke;break e}}else if(re.elementType===je||typeof je=="object"&&je!==null&&je.$$typeof===x&&p1(je)===re.type){f(se,re.sibling),ke=v(re,ue.props),wl(ke,ue),ke.return=se,se=ke;break e}f(se,re);break}else l(se,re);re=re.sibling}ue.type===c?(ke=ei(ue.props.children,se.mode,ke,ue.key),ke.return=se,se=ke):(ke=Hc(ue.type,ue.key,ue.props,null,se.mode,ke),wl(ke,ue),ke.return=se,se=ke)}return F(se);case u:e:{for(je=ue.key;re!==null;){if(re.key===je)if(re.tag===4&&re.stateNode.containerInfo===ue.containerInfo&&re.stateNode.implementation===ue.implementation){f(se,re.sibling),ke=v(re,ue.children||[]),ke.return=se,se=ke;break e}else{f(se,re);break}else l(se,re);re=re.sibling}ke=ah(ue,se.mode,ke),ke.return=se,se=ke}return F(se);case x:return je=ue._init,ue=je(ue._payload),Vt(se,re,ue,ke)}if(M(ue))return qe(se,re,ue,ke);if(C(ue)){if(je=C(ue),typeof je!="function")throw Error(r(150));return ue=je.call(ue),nt(se,re,ue,ke)}if(typeof ue.then=="function")return Vt(se,re,kc(ue),ke);if(ue.$$typeof===b)return Vt(se,re,Uc(se,ue),ke);Tc(se,ue)}return typeof ue=="string"&&ue!==""||typeof ue=="number"||typeof ue=="bigint"?(ue=""+ue,re!==null&&re.tag===6?(f(se,re.sibling),ke=v(re,ue),ke.return=se,se=ke):(f(se,re),ke=rh(ue,se.mode,ke),ke.return=se,se=ke),F(se)):f(se,re)}return function(se,re,ue,ke){try{El=0;var je=Vt(se,re,ue,ke);return Hi=null,je}catch(Ye){if(Ye===vl)throw Ye;var lt=gr(29,Ye,null,se.mode);return lt.lanes=ke,lt.return=se,lt}finally{}}}var qo=g1(!0),h1=g1(!1),$i=ae(null),Ac=ae(0);function m1(i,l){i=Ca,ie(Ac,i),ie($i,l),Ca=i|l.baseLanes}function cg(){ie(Ac,Ca),ie($i,$i.current)}function dg(){Ca=Ac.current,ye($i),ye(Ac)}var dr=ae(null),qr=null;function Qa(i){var l=i.alternate;ie(en,en.current&1),ie(dr,i),qr===null&&(l===null||$i.current!==null||l.memoizedState!==null)&&(qr=i)}function b1(i){if(i.tag===22){if(ie(en,en.current),ie(dr,i),qr===null){var l=i.alternate;l!==null&&l.memoizedState!==null&&(qr=i)}}else Ja()}function Ja(){ie(en,en.current),ie(dr,dr.current)}function ya(i){ye(dr),qr===i&&(qr=null),ye(en)}var en=ae(0);function Rc(i){for(var l=i;l!==null;){if(l.tag===13){var f=l.memoizedState;if(f!==null&&(f=f.dehydrated,f===null||f.data==="$?"||f.data==="$!"))return l}else if(l.tag===19&&l.memoizedProps.revealOrder!==void 0){if((l.flags&128)!==0)return l}else if(l.child!==null){l.child.return=l,l=l.child;continue}if(l===i)break;for(;l.sibling===null;){if(l.return===null||l.return===i)return null;l=l.return}l.sibling.return=l.return,l=l.sibling}return null}var P$=typeof AbortController<"u"?AbortController:function(){var i=[],l=this.signal={aborted:!1,addEventListener:function(f,h){i.push(h)}};this.abort=function(){l.aborted=!0,i.forEach(function(f){return f()})}},F$=e.unstable_scheduleCallback,z$=e.unstable_NormalPriority,tn={$$typeof:b,Consumer:null,Provider:null,_currentValue:null,_currentValue2:null,_threadCount:0};function fg(){return{controller:new P$,data:new Map,refCount:0}}function xl(i){i.refCount--,i.refCount===0&&F$(z$,function(){i.controller.abort()})}var kl=null,pg=0,qi=0,Vi=null;function B$(i,l){if(kl===null){var f=kl=[];pg=0,qi=vh(),Vi={status:"pending",value:void 0,then:function(h){f.push(h)}}}return pg++,l.then(y1,y1),l}function y1(){if(--pg===0&&kl!==null){Vi!==null&&(Vi.status="fulfilled");var i=kl;kl=null,qi=0,Vi=null;for(var l=0;lT?T:8;var F=I.T,q={};I.T=q,Ng(i,!1,l,f);try{var X=v(),oe=I.S;if(oe!==null&&oe(q,X),X!==null&&typeof X=="object"&&typeof X.then=="function"){var be=U$(X,h);Rl(i,l,be,Zn(i))}else Rl(i,l,h,Zn(i))}catch(Ae){Rl(i,l,{then:function(){},status:"rejected",reason:Ae},Zn())}finally{K.p=T,I.T=F}}function q$(){}function Cg(i,l,f,h){if(i.tag!==5)throw Error(r(476));var v=K1(i).queue;Y1(i,v,l,ee,f===null?q$:function(){return X1(i),f(h)})}function K1(i){var l=i.memoizedState;if(l!==null)return l;l={memoizedState:ee,baseState:ee,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:va,lastRenderedState:ee},next:null};var f={};return l.next={memoizedState:f,baseState:f,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:va,lastRenderedState:f},next:null},i.memoizedState=l,i=i.alternate,i!==null&&(i.memoizedState=l),l}function X1(i){var l=K1(i).next.queue;Rl(i,l,{},Zn())}function _g(){return En(Wl)}function Z1(){return Xt().memoizedState}function Q1(){return Xt().memoizedState}function V$(i){for(var l=i.return;l!==null;){switch(l.tag){case 24:case 3:var f=Zn();i=ao(f);var h=oo(l,i,f);h!==null&&(On(h,l,f),Nl(h,l,f)),l={cache:fg()},i.payload=l;return}l=l.return}}function W$(i,l,f){var h=Zn();f={lane:h,revertLane:0,action:f,hasEagerState:!1,eagerState:null,next:null},Pc(i)?eR(l,f):(f=og(i,l,f,h),f!==null&&(On(f,i,h),tR(f,l,h)))}function J1(i,l,f){var h=Zn();Rl(i,l,f,h)}function Rl(i,l,f,h){var v={lane:h,revertLane:0,action:f,hasEagerState:!1,eagerState:null,next:null};if(Pc(i))eR(l,v);else{var T=i.alternate;if(i.lanes===0&&(T===null||T.lanes===0)&&(T=l.lastRenderedReducer,T!==null))try{var F=l.lastRenderedState,q=T(F,f);if(v.hasEagerState=!0,v.eagerState=q,Wn(q,F))return vc(i,l,v,0),Dt===null&&yc(),!1}catch{}finally{}if(f=og(i,l,v,h),f!==null)return On(f,i,h),tR(f,l,h),!0}return!1}function Ng(i,l,f,h){if(h={lane:2,revertLane:vh(),action:h,hasEagerState:!1,eagerState:null,next:null},Pc(i)){if(l)throw Error(r(479))}else l=og(i,f,h,2),l!==null&&On(l,i,2)}function Pc(i){var l=i.alternate;return i===st||l!==null&&l===st}function eR(i,l){Wi=_c=!0;var f=i.pending;f===null?l.next=l:(l.next=f.next,f.next=l),i.pending=l}function tR(i,l,f){if((f&4194176)!==0){var h=l.lanes;h&=i.pendingLanes,f|=h,l.lanes=f,Ar(i,f)}}var Vr={readContext:En,use:Ic,useCallback:Wt,useContext:Wt,useEffect:Wt,useImperativeHandle:Wt,useLayoutEffect:Wt,useInsertionEffect:Wt,useMemo:Wt,useReducer:Wt,useRef:Wt,useState:Wt,useDebugValue:Wt,useDeferredValue:Wt,useTransition:Wt,useSyncExternalStore:Wt,useId:Wt};Vr.useCacheRefresh=Wt,Vr.useMemoCache=Wt,Vr.useHostTransitionStatus=Wt,Vr.useFormState=Wt,Vr.useActionState=Wt,Vr.useOptimistic=Wt;var Yo={readContext:En,use:Ic,useCallback:function(i,l){return zn().memoizedState=[i,l===void 0?null:l],i},useContext:En,useEffect:U1,useImperativeHandle:function(i,l,f){f=f!=null?f.concat([i]):null,Lc(4194308,4,H1.bind(null,l,i),f)},useLayoutEffect:function(i,l){return Lc(4194308,4,i,l)},useInsertionEffect:function(i,l){Lc(4,2,i,l)},useMemo:function(i,l){var f=zn();l=l===void 0?null:l;var h=i();if(Wo){ot(!0);try{i()}finally{ot(!1)}}return f.memoizedState=[h,l],h},useReducer:function(i,l,f){var h=zn();if(f!==void 0){var v=f(l);if(Wo){ot(!0);try{f(l)}finally{ot(!1)}}}else v=l;return h.memoizedState=h.baseState=v,i={pending:null,lanes:0,dispatch:null,lastRenderedReducer:i,lastRenderedState:v},h.queue=i,i=i.dispatch=W$.bind(null,st,i),[h.memoizedState,i]},useRef:function(i){var l=zn();return i={current:i},l.memoizedState=i},useState:function(i){i=xg(i);var l=i.queue,f=J1.bind(null,st,l);return l.dispatch=f,[i.memoizedState,f]},useDebugValue:Ag,useDeferredValue:function(i,l){var f=zn();return Rg(f,i,l)},useTransition:function(){var i=xg(!1);return i=Y1.bind(null,st,i.queue,!0,!1),zn().memoizedState=i,[!1,i]},useSyncExternalStore:function(i,l,f){var h=st,v=zn();if(St){if(f===void 0)throw Error(r(407));f=f()}else{if(f=l(),Dt===null)throw Error(r(349));(bt&60)!==0||k1(h,l,f)}v.memoizedState=f;var T={value:f,getSnapshot:l};return v.queue=T,U1(A1.bind(null,h,T,i),[i]),h.flags|=2048,Ki(9,T1.bind(null,h,T,f,l),{destroy:void 0},null),f},useId:function(){var i=zn(),l=Dt.identifierPrefix;if(St){var f=ba,h=ma;f=(h&~(1<<32-vt(h)-1)).toString(32)+f,l=":"+l+"R"+f,f=Nc++,0 title"))),mn(T,h,f),T[Sn]=i,an(T),h=T;break e;case"link":var F=CC("link","href",v).get(h+(f.href||""));if(F){for(var q=0;q<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof h.is=="string"?v.createElement("select",{is:h.is}):v.createElement("select"),h.multiple?i.multiple=!0:h.size&&(i.size=h.size);break;default:i=typeof h.is=="string"?v.createElement(f,{is:h.is}):v.createElement(f)}}i[Sn]=l,i[Pn]=h;e:for(v=l.child;v!==null;){if(v.tag===5||v.tag===6)i.appendChild(v.stateNode);else if(v.tag!==4&&v.tag!==27&&v.child!==null){v.child.return=v,v=v.child;continue}if(v===l)break e;for(;v.sibling===null;){if(v.return===null||v.return===l)break e;v=v.return}v.sibling.return=v.return,v=v.sibling}l.stateNode=i;e:switch(mn(i,f,h),f){case"button":case"input":case"select":case"textarea":i=!!h.autoFocus;break e;case"img":i=!0;break e;default:i=!1}i&&Aa(l)}}return zt(l),l.flags&=-16777217,null;case 6:if(i&&l.stateNode!=null)i.memoizedProps!==h&&Aa(l);else{if(typeof h!="string"&&l.stateNode===null)throw Error(r(166));if(i=De.current,ml(l)){if(i=l.stateNode,f=l.memoizedProps,h=null,v=Nn,v!==null)switch(v.tag){case 27:case 5:h=v.memoizedProps}i[Sn]=l,i=!!(i.nodeValue===f||h!==null&&h.suppressHydrationWarning===!0||mC(i.nodeValue,f)),i||$o(l)}else i=td(i).createTextNode(h),i[Sn]=l,l.stateNode=i}return zt(l),null;case 13:if(h=l.memoizedState,i===null||i.memoizedState!==null&&i.memoizedState.dehydrated!==null){if(v=ml(l),h!==null&&h.dehydrated!==null){if(i===null){if(!v)throw Error(r(318));if(v=l.memoizedState,v=v!==null?v.dehydrated:null,!v)throw Error(r(317));v[Sn]=l}else bl(),(l.flags&128)===0&&(l.memoizedState=null),l.flags|=4;zt(l),v=!1}else Cr!==null&&(fh(Cr),Cr=null),v=!0;if(!v)return l.flags&256?(ya(l),l):(ya(l),null)}if(ya(l),(l.flags&128)!==0)return l.lanes=f,l;if(f=h!==null,i=i!==null&&i.memoizedState!==null,f){h=l.child,v=null,h.alternate!==null&&h.alternate.memoizedState!==null&&h.alternate.memoizedState.cachePool!==null&&(v=h.alternate.memoizedState.cachePool.pool);var T=null;h.memoizedState!==null&&h.memoizedState.cachePool!==null&&(T=h.memoizedState.cachePool.pool),T!==v&&(h.flags|=2048)}return f!==i&&f&&(l.child.flags|=8192),$c(l,l.updateQueue),zt(l),null;case 4:return te(),i===null&&xh(l.stateNode.containerInfo),zt(l),null;case 10:return wa(l.type),zt(l),null;case 19:if(ye(en),v=l.memoizedState,v===null)return zt(l),null;if(h=(l.flags&128)!==0,T=v.rendering,T===null)if(h)Fl(v,!1);else{if(qt!==0||i!==null&&(i.flags&128)!==0)for(i=l.child;i!==null;){if(T=Rc(i),T!==null){for(l.flags|=128,Fl(v,!1),i=T.updateQueue,l.updateQueue=i,$c(l,i),l.subtreeFlags=0,i=f,f=l.child;f!==null;)$R(f,i),f=f.sibling;return ie(en,en.current&1|2),l.child}i=i.sibling}v.tail!==null&&he()>qc&&(l.flags|=128,h=!0,Fl(v,!1),l.lanes=4194304)}else{if(!h)if(i=Rc(T),i!==null){if(l.flags|=128,h=!0,i=i.updateQueue,l.updateQueue=i,$c(l,i),Fl(v,!0),v.tail===null&&v.tailMode==="hidden"&&!T.alternate&&!St)return zt(l),null}else 2*he()-v.renderingStartTime>qc&&f!==536870912&&(l.flags|=128,h=!0,Fl(v,!1),l.lanes=4194304);v.isBackwards?(T.sibling=l.child,l.child=T):(i=v.last,i!==null?i.sibling=T:l.child=T,v.last=T)}return v.tail!==null?(l=v.tail,v.rendering=l,v.tail=l.sibling,v.renderingStartTime=he(),l.sibling=null,i=en.current,ie(en,h?i&1|2:i&1),l):(zt(l),null);case 22:case 23:return ya(l),dg(),h=l.memoizedState!==null,i!==null?i.memoizedState!==null!==h&&(l.flags|=8192):h&&(l.flags|=8192),h?(f&536870912)!==0&&(l.flags&128)===0&&(zt(l),l.subtreeFlags&6&&(l.flags|=8192)):zt(l),f=l.updateQueue,f!==null&&$c(l,f.retryQueue),f=null,i!==null&&i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(f=i.memoizedState.cachePool.pool),h=null,l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(h=l.memoizedState.cachePool.pool),h!==f&&(l.flags|=2048),i!==null&&ye(Vo),null;case 24:return f=null,i!==null&&(f=i.memoizedState.cache),l.memoizedState.cache!==f&&(l.flags|=2048),wa(tn),zt(l),null;case 25:return null}throw Error(r(156,l.tag))}function e6(i,l){switch(sg(l),l.tag){case 1:return i=l.flags,i&65536?(l.flags=i&-65537|128,l):null;case 3:return wa(tn),te(),i=l.flags,(i&65536)!==0&&(i&128)===0?(l.flags=i&-65537|128,l):null;case 26:case 27:case 5:return Te(l),null;case 13:if(ya(l),i=l.memoizedState,i!==null&&i.dehydrated!==null){if(l.alternate===null)throw Error(r(340));bl()}return i=l.flags,i&65536?(l.flags=i&-65537|128,l):null;case 19:return ye(en),null;case 4:return te(),null;case 10:return wa(l.type),null;case 22:case 23:return ya(l),dg(),i!==null&&ye(Vo),i=l.flags,i&65536?(l.flags=i&-65537|128,l):null;case 24:return wa(tn),null;case 25:return null;default:return null}}function WR(i,l){switch(sg(l),l.tag){case 3:wa(tn),te();break;case 26:case 27:case 5:Te(l);break;case 4:te();break;case 13:ya(l);break;case 19:ye(en);break;case 10:wa(l.type);break;case 22:case 23:ya(l),dg(),i!==null&&ye(Vo);break;case 24:wa(tn)}}var t6={getCacheForType:function(i){var l=En(tn),f=l.data.get(i);return f===void 0&&(f=i(),l.data.set(i,f)),f}},n6=typeof WeakMap=="function"?WeakMap:Map,Bt=0,Dt=null,ct=null,bt=0,Lt=0,Xn=null,Ra=!1,Ji=!1,oh=!1,Ca=0,qt=0,co=0,ti=0,ih=0,hr=0,es=0,zl=null,Wr=null,sh=!1,lh=0,qc=1/0,Vc=null,fo=null,Wc=!1,ni=null,Bl=0,uh=0,ch=null,Ul=0,dh=null;function Zn(){if((Bt&2)!==0&&bt!==0)return bt&-bt;if(I.T!==null){var i=qi;return i!==0?i:vh()}return gA()}function YR(){hr===0&&(hr=(bt&536870912)===0||St?_t():536870912);var i=dr.current;return i!==null&&(i.flags|=32),hr}function On(i,l,f){(i===Dt&&Lt===2||i.cancelPendingCommit!==null)&&(ts(i,0),_a(i,bt,hr,!1)),Ln(i,f),((Bt&2)===0||i!==Dt)&&(i===Dt&&((Bt&2)===0&&(ti|=f),qt===4&&_a(i,bt,hr,!1)),Yr(i))}function KR(i,l,f){if((Bt&6)!==0)throw Error(r(327));var h=!f&&(l&60)===0&&(l&i.expiredLanes)===0||Xe(i,l),v=h?o6(i,l):hh(i,l,!0),T=h;do{if(v===0){Ji&&!h&&_a(i,l,0,!1);break}else if(v===6)_a(i,l,0,!Ra);else{if(f=i.current.alternate,T&&!r6(f)){v=hh(i,l,!1),T=!1;continue}if(v===2){if(T=l,i.errorRecoveryDisabledLanes&T)var F=0;else F=i.pendingLanes&-536870913,F=F!==0?F:F&536870912?536870912:0;if(F!==0){l=F;e:{var q=i;v=zl;var X=q.current.memoizedState.isDehydrated;if(X&&(ts(q,F).flags|=256),F=hh(q,F,!1),F!==2){if(oh&&!X){q.errorRecoveryDisabledLanes|=T,ti|=T,v=4;break e}T=Wr,Wr=v,T!==null&&fh(T)}v=F}if(T=!1,v!==2)continue}}if(v===1){ts(i,0),_a(i,l,0,!0);break}e:{switch(h=i,v){case 0:case 1:throw Error(r(345));case 4:if((l&4194176)===l){_a(h,l,hr,!Ra);break e}break;case 2:Wr=null;break;case 3:case 5:break;default:throw Error(r(329))}if(h.finishedWork=f,h.finishedLanes=l,(l&62914560)===l&&(T=lh+300-he(),10f?32:f,I.T=null,ni===null)var T=!1;else{f=ch,ch=null;var F=ni,q=Bl;if(ni=null,Bl=0,(Bt&6)!==0)throw Error(r(331));var X=Bt;if(Bt|=4,GR(F.current),BR(F,F.current,q,f),Bt=X,jl(0,!1),et&&typeof et.onPostCommitFiberRoot=="function")try{et.onPostCommitFiberRoot(ht,F)}catch{}T=!0}return T}finally{K.p=v,I.T=h,aC(i,l)}}return!1}function oC(i,l,f){l=lr(f,l),l=Dg(i.stateNode,l,2),i=oo(i,l,2),i!==null&&(Ln(i,2),Yr(i))}function Nt(i,l,f){if(i.tag===3)oC(i,i,f);else for(;l!==null;){if(l.tag===3){oC(l,i,f);break}else if(l.tag===1){var h=l.stateNode;if(typeof l.type.getDerivedStateFromError=="function"||typeof h.componentDidCatch=="function"&&(fo===null||!fo.has(h))){i=lr(f,i),f=lR(2),h=oo(l,f,2),h!==null&&(uR(f,h,l,i),Ln(h,2),Yr(h));break}}l=l.return}}function mh(i,l,f){var h=i.pingCache;if(h===null){h=i.pingCache=new n6;var v=new Set;h.set(l,v)}else v=h.get(l),v===void 0&&(v=new Set,h.set(l,v));v.has(f)||(oh=!0,v.add(f),i=l6.bind(null,i,l,f),l.then(i,i))}function l6(i,l,f){var h=i.pingCache;h!==null&&h.delete(l),i.pingedLanes|=i.suspendedLanes&f,i.warmLanes&=~f,Dt===i&&(bt&f)===f&&(qt===4||qt===3&&(bt&62914560)===bt&&300>he()-lh?(Bt&2)===0&&ts(i,0):ih|=f,es===bt&&(es=0)),Yr(i)}function iC(i,l){l===0&&(l=Dn()),i=Za(i,l),i!==null&&(Ln(i,l),Yr(i))}function u6(i){var l=i.memoizedState,f=0;l!==null&&(f=l.retryLane),iC(i,f)}function c6(i,l){var f=0;switch(i.tag){case 13:var h=i.stateNode,v=i.memoizedState;v!==null&&(f=v.retryLane);break;case 19:h=i.stateNode;break;case 22:h=i.stateNode._retryCache;break;default:throw Error(r(314))}h!==null&&h.delete(l),iC(i,f)}function d6(i,l){return xe(i,l)}var Xc=null,as=null,bh=!1,Zc=!1,yh=!1,ri=0;function Yr(i){i!==as&&i.next===null&&(as===null?Xc=as=i:as=as.next=i),Zc=!0,bh||(bh=!0,p6(f6))}function jl(i,l){if(!yh&&Zc){yh=!0;do for(var f=!1,h=Xc;h!==null;){if(i!==0){var v=h.pendingLanes;if(v===0)var T=0;else{var F=h.suspendedLanes,q=h.pingedLanes;T=(1<<31-vt(42|i)+1)-1,T&=v&~(F&~q),T=T&201326677?T&201326677|1:T?T|2:0}T!==0&&(f=!0,uC(h,T))}else T=bt,T=fa(h,h===Dt?T:0),(T&3)===0||Xe(h,T)||(f=!0,uC(h,T));h=h.next}while(f);yh=!1}}function f6(){Zc=bh=!1;var i=0;ri!==0&&(E6()&&(i=ri),ri=0);for(var l=he(),f=null,h=Xc;h!==null;){var v=h.next,T=sC(h,l);T===0?(h.next=null,f===null?Xc=v:f.next=v,v===null&&(as=f)):(f=h,(i!==0||(T&3)!==0)&&(Zc=!0)),h=v}jl(i)}function sC(i,l){for(var f=i.suspendedLanes,h=i.pingedLanes,v=i.expirationTimes,T=i.pendingLanes&-62914561;0"u"?null:document;function kC(i,l,f){var h=is;if(h&&typeof l=="string"&&l){var v=ir(l);v='link[rel="'+i+'"][href="'+v+'"]',typeof f=="string"&&(v+='[crossorigin="'+f+'"]'),xC.has(v)||(xC.add(v),i={rel:i,crossOrigin:f,href:l},h.querySelector(v)===null&&(l=h.createElement("link"),mn(l,"link",i),an(l),h.head.appendChild(l)))}}function _6(i){Na.D(i),kC("dns-prefetch",i,null)}function N6(i,l){Na.C(i,l),kC("preconnect",i,l)}function O6(i,l,f){Na.L(i,l,f);var h=is;if(h&&i&&l){var v='link[rel="preload"][as="'+ir(l)+'"]';l==="image"&&f&&f.imageSrcSet?(v+='[imagesrcset="'+ir(f.imageSrcSet)+'"]',typeof f.imageSizes=="string"&&(v+='[imagesizes="'+ir(f.imageSizes)+'"]')):v+='[href="'+ir(i)+'"]';var T=v;switch(l){case"style":T=ss(i);break;case"script":T=ls(i)}mr.has(T)||(i=D({rel:"preload",href:l==="image"&&f&&f.imageSrcSet?void 0:i,as:l},f),mr.set(T,i),h.querySelector(v)!==null||l==="style"&&h.querySelector($l(T))||l==="script"&&h.querySelector(ql(T))||(l=h.createElement("link"),mn(l,"link",i),an(l),h.head.appendChild(l)))}}function I6(i,l){Na.m(i,l);var f=is;if(f&&i){var h=l&&typeof l.as=="string"?l.as:"script",v='link[rel="modulepreload"][as="'+ir(h)+'"][href="'+ir(i)+'"]',T=v;switch(h){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":T=ls(i)}if(!mr.has(T)&&(i=D({rel:"modulepreload",href:i},l),mr.set(T,i),f.querySelector(v)===null)){switch(h){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(f.querySelector(ql(T)))return}h=f.createElement("link"),mn(h,"link",i),an(h),f.head.appendChild(h)}}}function D6(i,l,f){Na.S(i,l,f);var h=is;if(h&&i){var v=Ni(h).hoistableStyles,T=ss(i);l=l||"default";var F=v.get(T);if(!F){var q={loading:0,preload:null};if(F=h.querySelector($l(T)))q.loading=5;else{i=D({rel:"stylesheet",href:i,"data-precedence":l},f),(f=mr.get(T))&&Ih(i,f);var X=F=h.createElement("link");an(X),mn(X,"link",i),X._p=new Promise(function(oe,be){X.onload=oe,X.onerror=be}),X.addEventListener("load",function(){q.loading|=1}),X.addEventListener("error",function(){q.loading|=2}),q.loading|=4,rd(F,l,h)}F={type:"stylesheet",instance:F,count:1,state:q},v.set(T,F)}}}function L6(i,l){Na.X(i,l);var f=is;if(f&&i){var h=Ni(f).hoistableScripts,v=ls(i),T=h.get(v);T||(T=f.querySelector(ql(v)),T||(i=D({src:i,async:!0},l),(l=mr.get(v))&&Dh(i,l),T=f.createElement("script"),an(T),mn(T,"link",i),f.head.appendChild(T)),T={type:"script",instance:T,count:1,state:null},h.set(v,T))}}function M6(i,l){Na.M(i,l);var f=is;if(f&&i){var h=Ni(f).hoistableScripts,v=ls(i),T=h.get(v);T||(T=f.querySelector(ql(v)),T||(i=D({src:i,async:!0,type:"module"},l),(l=mr.get(v))&&Dh(i,l),T=f.createElement("script"),an(T),mn(T,"link",i),f.head.appendChild(T)),T={type:"script",instance:T,count:1,state:null},h.set(v,T))}}function TC(i,l,f,h){var v=(v=De.current)?nd(v):null;if(!v)throw Error(r(446));switch(i){case"meta":case"title":return null;case"style":return typeof f.precedence=="string"&&typeof f.href=="string"?(l=ss(f.href),f=Ni(v).hoistableStyles,h=f.get(l),h||(h={type:"style",instance:null,count:0,state:null},f.set(l,h)),h):{type:"void",instance:null,count:0,state:null};case"link":if(f.rel==="stylesheet"&&typeof f.href=="string"&&typeof f.precedence=="string"){i=ss(f.href);var T=Ni(v).hoistableStyles,F=T.get(i);if(F||(v=v.ownerDocument||v,F={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},T.set(i,F),(T=v.querySelector($l(i)))&&!T._p&&(F.instance=T,F.state.loading=5),mr.has(i)||(f={rel:"preload",as:"style",href:f.href,crossOrigin:f.crossOrigin,integrity:f.integrity,media:f.media,hrefLang:f.hrefLang,referrerPolicy:f.referrerPolicy},mr.set(i,f),T||P6(v,i,f,F.state))),l&&h===null)throw Error(r(528,""));return F}if(l&&h!==null)throw Error(r(529,""));return null;case"script":return l=f.async,f=f.src,typeof f=="string"&&l&&typeof l!="function"&&typeof l!="symbol"?(l=ls(f),f=Ni(v).hoistableScripts,h=f.get(l),h||(h={type:"script",instance:null,count:0,state:null},f.set(l,h)),h):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,i))}}function ss(i){return'href="'+ir(i)+'"'}function $l(i){return'link[rel="stylesheet"]['+i+"]"}function AC(i){return D({},i,{"data-precedence":i.precedence,precedence:null})}function P6(i,l,f,h){i.querySelector('link[rel="preload"][as="style"]['+l+"]")?h.loading=1:(l=i.createElement("link"),h.preload=l,l.addEventListener("load",function(){return h.loading|=1}),l.addEventListener("error",function(){return h.loading|=2}),mn(l,"link",f),an(l),i.head.appendChild(l))}function ls(i){return'[src="'+ir(i)+'"]'}function ql(i){return"script[async]"+i}function RC(i,l,f){if(l.count++,l.instance===null)switch(l.type){case"style":var h=i.querySelector('style[data-href~="'+ir(f.href)+'"]');if(h)return l.instance=h,an(h),h;var v=D({},f,{"data-href":f.href,"data-precedence":f.precedence,href:null,precedence:null});return h=(i.ownerDocument||i).createElement("style"),an(h),mn(h,"style",v),rd(h,f.precedence,i),l.instance=h;case"stylesheet":v=ss(f.href);var T=i.querySelector($l(v));if(T)return l.state.loading|=4,l.instance=T,an(T),T;h=AC(f),(v=mr.get(v))&&Ih(h,v),T=(i.ownerDocument||i).createElement("link"),an(T);var F=T;return F._p=new Promise(function(q,X){F.onload=q,F.onerror=X}),mn(T,"link",h),l.state.loading|=4,rd(T,f.precedence,i),l.instance=T;case"script":return T=ls(f.src),(v=i.querySelector(ql(T)))?(l.instance=v,an(v),v):(h=f,(v=mr.get(T))&&(h=D({},f),Dh(h,v)),i=i.ownerDocument||i,v=i.createElement("script"),an(v),mn(v,"link",h),i.head.appendChild(v),l.instance=v);case"void":return null;default:throw Error(r(443,l.type))}else l.type==="stylesheet"&&(l.state.loading&4)===0&&(h=l.instance,l.state.loading|=4,rd(h,f.precedence,i));return l.instance}function rd(i,l,f){for(var h=f.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),v=h.length?h[h.length-1]:null,T=v,F=0;F title"):null)}function F6(i,l,f){if(f===1||l.itemProp!=null)return!1;switch(i){case"meta":case"title":return!0;case"style":if(typeof l.precedence!="string"||typeof l.href!="string"||l.href==="")break;return!0;case"link":if(typeof l.rel!="string"||typeof l.href!="string"||l.href===""||l.onLoad||l.onError)break;switch(l.rel){case"stylesheet":return i=l.disabled,typeof l.precedence=="string"&&i==null;default:return!0}case"script":if(l.async&&typeof l.async!="function"&&typeof l.async!="symbol"&&!l.onLoad&&!l.onError&&l.src&&typeof l.src=="string")return!0}return!1}function NC(i){return!(i.type==="stylesheet"&&(i.state.loading&3)===0)}var Vl=null;function z6(){}function B6(i,l,f){if(Vl===null)throw Error(r(475));var h=Vl;if(l.type==="stylesheet"&&(typeof f.media!="string"||matchMedia(f.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var v=ss(f.href),T=i.querySelector($l(v));if(T){i=T._p,i!==null&&typeof i=="object"&&typeof i.then=="function"&&(h.count++,h=od.bind(h),i.then(h,h)),l.state.loading|=4,l.instance=T,an(T);return}T=i.ownerDocument||i,f=AC(f),(v=mr.get(v))&&Ih(f,v),T=T.createElement("link"),an(T);var F=T;F._p=new Promise(function(q,X){F.onload=q,F.onerror=X}),mn(T,"link",f),l.instance=T}h.stylesheets===null&&(h.stylesheets=new Map),h.stylesheets.set(l,i),(i=l.state.preload)&&(l.state.loading&3)===0&&(h.count++,l=od.bind(h),i.addEventListener("load",l),i.addEventListener("error",l))}}function U6(){if(Vl===null)throw Error(r(475));var i=Vl;return i.stylesheets&&i.count===0&&Lh(i,i.stylesheets),0"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Hh.exports=sq(),Hh.exports}var uq=lq(),eu={},QC;function cq(){if(QC)return eu;QC=1,Object.defineProperty(eu,"__esModule",{value:!0}),eu.parse=s,eu.serialize=d;const e=/^[\u0021-\u003A\u003C\u003E-\u007E]+$/,t=/^[\u0021-\u003A\u003C-\u007E]*$/,n=/^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i,r=/^[\u0020-\u003A\u003D-\u007E]*$/,a=Object.prototype.toString,o=(()=>{const m=function(){};return m.prototype=Object.create(null),m})();function s(m,b){const y=new o,S=m.length;if(S<2)return y;const k=(b==null?void 0:b.decode)||p;let A=0;do{const x=m.indexOf("=",A);if(x===-1)break;const R=m.indexOf(";",A),N=R===-1?S:R;if(x>N){A=m.lastIndexOf(";",x-1)+1;continue}const O=u(m,A,x),C=c(m,x,O),_=m.slice(O,C);if(y[_]===void 0){let P=u(m,x+1,N),I=c(m,N,P);const D=k(m.slice(P,I));y[_]=D}A=N+1}while(Ay;){const S=m.charCodeAt(--b);if(S!==32&&S!==9)return b+1}return y}function d(m,b,y){const S=(y==null?void 0:y.encode)||encodeURIComponent;if(!e.test(m))throw new TypeError(`argument name is invalid: ${m}`);const k=S(b);if(!t.test(k))throw new TypeError(`argument val is invalid: ${b}`);let A=m+"="+k;if(!y)return A;if(y.maxAge!==void 0){if(!Number.isInteger(y.maxAge))throw new TypeError(`option maxAge is invalid: ${y.maxAge}`);A+="; Max-Age="+y.maxAge}if(y.domain){if(!n.test(y.domain))throw new TypeError(`option domain is invalid: ${y.domain}`);A+="; Domain="+y.domain}if(y.path){if(!r.test(y.path))throw new TypeError(`option path is invalid: ${y.path}`);A+="; Path="+y.path}if(y.expires){if(!g(y.expires)||!Number.isFinite(y.expires.valueOf()))throw new TypeError(`option expires is invalid: ${y.expires}`);A+="; Expires="+y.expires.toUTCString()}if(y.httpOnly&&(A+="; HttpOnly"),y.secure&&(A+="; Secure"),y.partitioned&&(A+="; Partitioned"),y.priority)switch(typeof y.priority=="string"?y.priority.toLowerCase():void 0){case"low":A+="; Priority=Low";break;case"medium":A+="; Priority=Medium";break;case"high":A+="; Priority=High";break;default:throw new TypeError(`option priority is invalid: ${y.priority}`)}if(y.sameSite)switch(typeof y.sameSite=="string"?y.sameSite.toLowerCase():y.sameSite){case!0:case"strict":A+="; SameSite=Strict";break;case"lax":A+="; SameSite=Lax";break;case"none":A+="; SameSite=None";break;default:throw new TypeError(`option sameSite is invalid: ${y.sameSite}`)}return A}function p(m){if(m.indexOf("%")===-1)return m;try{return decodeURIComponent(m)}catch{return m}}function g(m){return a.call(m)==="[object Date]"}return eu}cq();/** * react-router v7.4.0 * * Copyright (c) Remix Software Inc. @@ -55,204 +55,19 @@ Error generating stack: `+f.message+` * LICENSE.md file in the root directory of this source tree. * * @license MIT - */var JC="popstate";function hq(e={}){function t(a,o){let{pathname:s="/",search:u="",hash:c=""}=wi(a.location.hash.substring(1));return!s.startsWith("/")&&!s.startsWith(".")&&(s="/"+s),Zx("",{pathname:s,search:u,hash:c},o.state&&o.state.usr||null,o.state&&o.state.key||"default")}function n(a,o){let s=a.document.querySelector("base"),u="";if(s&&s.getAttribute("href")){let c=a.location.href,d=c.indexOf("#");u=d===-1?c:c.slice(0,d)}return u+"#"+(typeof o=="string"?o:wu(o))}function r(a,o){Br(a.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(o)})`)}return bq(t,n,r,e)}function Gt(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function Br(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function mq(){return Math.random().toString(36).substring(2,10)}function e_(e,t){return{usr:e.state,key:e.key,idx:t}}function Zx(e,t,n=null,r){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?wi(t):t,state:n,key:t&&t.key||r||mq()}}function wu({pathname:e="/",search:t="",hash:n=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function wi(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function bq(e,t,n,r={}){let{window:a=document.defaultView,v5Compat:o=!1}=r,s=a.history,u="POP",c=null,d=p();d==null&&(d=0,s.replaceState({...s.state,idx:d},""));function p(){return(s.state||{idx:null}).idx}function g(){u="POP";let k=p(),R=k==null?null:k-d;d=k,c&&c({action:u,location:S.location,delta:R})}function m(k,R){u="PUSH";let x=Zx(S.location,k,R);n&&n(x,k),d=p()+1;let A=e_(x,d),N=S.createHref(x);try{s.pushState(A,"",N)}catch(O){if(O instanceof DOMException&&O.name==="DataCloneError")throw O;a.location.assign(N)}o&&c&&c({action:u,location:S.location,delta:1})}function b(k,R){u="REPLACE";let x=Zx(S.location,k,R);n&&n(x,k),d=p();let A=e_(x,d),N=S.createHref(x);s.replaceState(A,"",N),o&&c&&c({action:u,location:S.location,delta:0})}function y(k){let R=a.location.origin!=="null"?a.location.origin:a.location.href,x=typeof k=="string"?k:wu(k);return x=x.replace(/ $/,"%20"),Gt(R,`No window.location.(origin|href) available to create URL for href: ${x}`),new URL(x,R)}let S={get action(){return u},get location(){return e(a,s)},listen(k){if(c)throw new Error("A history only accepts one active listener");return a.addEventListener(JC,g),c=k,()=>{a.removeEventListener(JC,g),c=null}},createHref(k){return t(a,k)},createURL:y,encodeLocation(k){let R=y(k);return{pathname:R.pathname,search:R.search,hash:R.hash}},push:m,replace:b,go(k){return s.go(k)}};return S}function Iz(e,t,n="/"){return yq(e,t,n,!1)}function yq(e,t,n,r){let a=typeof t=="string"?wi(t):t,o=Ua(a.pathname||"/",n);if(o==null)return null;let s=Dz(e);vq(s);let u=null;for(let c=0;u==null&&c{let c={relativePath:u===void 0?o.path||"":u,caseSensitive:o.caseSensitive===!0,childrenIndex:s,route:o};c.relativePath.startsWith("/")&&(Gt(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length));let d=za([r,c.relativePath]),p=n.concat(c);o.children&&o.children.length>0&&(Gt(o.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${d}".`),Dz(o.children,t,p,d)),!(o.path==null&&!o.index)&&t.push({path:d,score:Aq(d,o.index),routesMeta:p})};return e.forEach((o,s)=>{var u;if(o.path===""||!((u=o.path)!=null&&u.includes("?")))a(o,s);else for(let c of Lz(o.path))a(o,s,c)}),t}function Lz(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,a=n.endsWith("?"),o=n.replace(/\?$/,"");if(r.length===0)return a?[o,""]:[o];let s=Lz(r.join("/")),u=[];return u.push(...s.map(c=>c===""?o:[o,c].join("/"))),a&&u.push(...s),u.map(c=>e.startsWith("/")&&c===""?"/":c)}function vq(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:Rq(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var Sq=/^:[\w-]+$/,Eq=3,wq=2,xq=1,kq=10,Tq=-2,t_=e=>e==="*";function Aq(e,t){let n=e.split("/"),r=n.length;return n.some(t_)&&(r+=Tq),t&&(r+=wq),n.filter(a=>!t_(a)).reduce((a,o)=>a+(Sq.test(o)?Eq:o===""?xq:kq),r)}function Rq(e,t){return e.length===t.length&&e.slice(0,-1).every((r,a)=>r===t[a])?e[e.length-1]-t[t.length-1]:0}function Cq(e,t,n=!1){let{routesMeta:r}=e,a={},o="/",s=[];for(let u=0;u{if(p==="*"){let y=u[m]||"";s=o.slice(0,o.length-y.length).replace(/(.)\/+$/,"$1")}const b=u[m];return g&&!b?d[p]=void 0:d[p]=(b||"").replace(/%2F/g,"/"),d},{}),pathname:o,pathnameBase:s,pattern:e}}function _q(e,t=!1,n=!0){Br(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let r=[],a="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(s,u,c)=>(r.push({paramName:u,isOptional:c!=null}),c?"/?([^\\/]+)?":"/([^\\/]+)"));return e.endsWith("*")?(r.push({paramName:"*"}),a+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?a+="\\/*$":e!==""&&e!=="/"&&(a+="(?:(?=\\/|$))"),[new RegExp(a,t?void 0:"i"),r]}function Nq(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return Br(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function Ua(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}function Oq(e,t="/"){let{pathname:n,search:r="",hash:a=""}=typeof e=="string"?wi(e):e;return{pathname:n?n.startsWith("/")?n:Iq(n,t):t,search:Mq(r),hash:Pq(a)}}function Iq(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(a=>{a===".."?n.length>1&&n.pop():a!=="."&&n.push(a)}),n.length>1?n.join("/"):"/"}function Wh(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function Dq(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function Mz(e){let t=Dq(e);return t.map((n,r)=>r===t.length-1?n.pathname:n.pathnameBase)}function Pz(e,t,n,r=!1){let a;typeof e=="string"?a=wi(e):(a={...e},Gt(!a.pathname||!a.pathname.includes("?"),Wh("?","pathname","search",a)),Gt(!a.pathname||!a.pathname.includes("#"),Wh("#","pathname","hash",a)),Gt(!a.search||!a.search.includes("#"),Wh("#","search","hash",a)));let o=e===""||a.pathname==="",s=o?"/":a.pathname,u;if(s==null)u=n;else{let g=t.length-1;if(!r&&s.startsWith("..")){let m=s.split("/");for(;m[0]==="..";)m.shift(),g-=1;a.pathname=m.join("/")}u=g>=0?t[g]:"/"}let c=Oq(a,u),d=s&&s!=="/"&&s.endsWith("/"),p=(o||s===".")&&n.endsWith("/");return!c.pathname.endsWith("/")&&(d||p)&&(c.pathname+="/"),c}var za=e=>e.join("/").replace(/\/\/+/g,"/"),Lq=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),Mq=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,Pq=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e;function Fq(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}var Fz=["POST","PUT","PATCH","DELETE"];new Set(Fz);var zq=["GET",...Fz];new Set(zq);var js=E.createContext(null);js.displayName="DataRouter";var $f=E.createContext(null);$f.displayName="DataRouterState";var zz=E.createContext({isTransitioning:!1});zz.displayName="ViewTransition";var Bq=E.createContext(new Map);Bq.displayName="Fetchers";var Uq=E.createContext(null);Uq.displayName="Await";var ia=E.createContext(null);ia.displayName="Navigation";var Bu=E.createContext(null);Bu.displayName="Location";var qa=E.createContext({outlet:null,matches:[],isDataRoute:!1});qa.displayName="Route";var m0=E.createContext(null);m0.displayName="RouteError";function jq(e,{relative:t}={}){Gt(Uu(),"useHref() may be used only in the context of a component.");let{basename:n,navigator:r}=E.useContext(ia),{hash:a,pathname:o,search:s}=ju(e,{relative:t}),u=o;return n!=="/"&&(u=o==="/"?n:za([n,o])),r.createHref({pathname:u,search:s,hash:a})}function Uu(){return E.useContext(Bu)!=null}function xi(){return Gt(Uu(),"useLocation() may be used only in the context of a component."),E.useContext(Bu).location}var Bz="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Uz(e){E.useContext(ia).static||E.useLayoutEffect(e)}function b0(){let{isDataRoute:e}=E.useContext(qa);return e?e9():Gq()}function Gq(){Gt(Uu(),"useNavigate() may be used only in the context of a component.");let e=E.useContext(js),{basename:t,navigator:n}=E.useContext(ia),{matches:r}=E.useContext(qa),{pathname:a}=xi(),o=JSON.stringify(Mz(r)),s=E.useRef(!1);return Uz(()=>{s.current=!0}),E.useCallback((c,d={})=>{if(Br(s.current,Bz),!s.current)return;if(typeof c=="number"){n.go(c);return}let p=Pz(c,JSON.parse(o),a,d.relative==="path");e==null&&t!=="/"&&(p.pathname=p.pathname==="/"?t:za([t,p.pathname])),(d.replace?n.replace:n.push)(p,d.state,d)},[t,n,o,a,e])}E.createContext(null);function ju(e,{relative:t}={}){let{matches:n}=E.useContext(qa),{pathname:r}=xi(),a=JSON.stringify(Mz(n));return E.useMemo(()=>Pz(e,JSON.parse(a),r,t==="path"),[e,a,r,t])}function Hq(e,t){return jz(e,t)}function jz(e,t,n,r){var x;Gt(Uu(),"useRoutes() may be used only in the context of a component.");let{navigator:a,static:o}=E.useContext(ia),{matches:s}=E.useContext(qa),u=s[s.length-1],c=u?u.params:{},d=u?u.pathname:"/",p=u?u.pathnameBase:"/",g=u&&u.route;{let A=g&&g.path||"";Gz(d,!g||A.endsWith("*")||A.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${d}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + */var JC="popstate";function dq(e={}){function t(a,o){let{pathname:s="/",search:u="",hash:c=""}=wi(a.location.hash.substring(1));return!s.startsWith("/")&&!s.startsWith(".")&&(s="/"+s),Zx("",{pathname:s,search:u,hash:c},o.state&&o.state.usr||null,o.state&&o.state.key||"default")}function n(a,o){let s=a.document.querySelector("base"),u="";if(s&&s.getAttribute("href")){let c=a.location.href,d=c.indexOf("#");u=d===-1?c:c.slice(0,d)}return u+"#"+(typeof o=="string"?o:wu(o))}function r(a,o){zr(a.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(o)})`)}return pq(t,n,r,e)}function Gt(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function zr(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function fq(){return Math.random().toString(36).substring(2,10)}function e_(e,t){return{usr:e.state,key:e.key,idx:t}}function Zx(e,t,n=null,r){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?wi(t):t,state:n,key:t&&t.key||r||fq()}}function wu({pathname:e="/",search:t="",hash:n=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function wi(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function pq(e,t,n,r={}){let{window:a=document.defaultView,v5Compat:o=!1}=r,s=a.history,u="POP",c=null,d=p();d==null&&(d=0,s.replaceState({...s.state,idx:d},""));function p(){return(s.state||{idx:null}).idx}function g(){u="POP";let k=p(),A=k==null?null:k-d;d=k,c&&c({action:u,location:S.location,delta:A})}function m(k,A){u="PUSH";let x=Zx(S.location,k,A);n&&n(x,k),d=p()+1;let R=e_(x,d),N=S.createHref(x);try{s.pushState(R,"",N)}catch(O){if(O instanceof DOMException&&O.name==="DataCloneError")throw O;a.location.assign(N)}o&&c&&c({action:u,location:S.location,delta:1})}function b(k,A){u="REPLACE";let x=Zx(S.location,k,A);n&&n(x,k),d=p();let R=e_(x,d),N=S.createHref(x);s.replaceState(R,"",N),o&&c&&c({action:u,location:S.location,delta:0})}function y(k){let A=a.location.origin!=="null"?a.location.origin:a.location.href,x=typeof k=="string"?k:wu(k);return x=x.replace(/ $/,"%20"),Gt(A,`No window.location.(origin|href) available to create URL for href: ${x}`),new URL(x,A)}let S={get action(){return u},get location(){return e(a,s)},listen(k){if(c)throw new Error("A history only accepts one active listener");return a.addEventListener(JC,g),c=k,()=>{a.removeEventListener(JC,g),c=null}},createHref(k){return t(a,k)},createURL:y,encodeLocation(k){let A=y(k);return{pathname:A.pathname,search:A.search,hash:A.hash}},push:m,replace:b,go(k){return s.go(k)}};return S}function Iz(e,t,n="/"){return gq(e,t,n,!1)}function gq(e,t,n,r){let a=typeof t=="string"?wi(t):t,o=Ua(a.pathname||"/",n);if(o==null)return null;let s=Dz(e);hq(s);let u=null;for(let c=0;u==null&&c{let c={relativePath:u===void 0?o.path||"":u,caseSensitive:o.caseSensitive===!0,childrenIndex:s,route:o};c.relativePath.startsWith("/")&&(Gt(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length));let d=za([r,c.relativePath]),p=n.concat(c);o.children&&o.children.length>0&&(Gt(o.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${d}".`),Dz(o.children,t,p,d)),!(o.path==null&&!o.index)&&t.push({path:d,score:wq(d,o.index),routesMeta:p})};return e.forEach((o,s)=>{var u;if(o.path===""||!((u=o.path)!=null&&u.includes("?")))a(o,s);else for(let c of Lz(o.path))a(o,s,c)}),t}function Lz(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,a=n.endsWith("?"),o=n.replace(/\?$/,"");if(r.length===0)return a?[o,""]:[o];let s=Lz(r.join("/")),u=[];return u.push(...s.map(c=>c===""?o:[o,c].join("/"))),a&&u.push(...s),u.map(c=>e.startsWith("/")&&c===""?"/":c)}function hq(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:xq(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var mq=/^:[\w-]+$/,bq=3,yq=2,vq=1,Sq=10,Eq=-2,t_=e=>e==="*";function wq(e,t){let n=e.split("/"),r=n.length;return n.some(t_)&&(r+=Eq),t&&(r+=yq),n.filter(a=>!t_(a)).reduce((a,o)=>a+(mq.test(o)?bq:o===""?vq:Sq),r)}function xq(e,t){return e.length===t.length&&e.slice(0,-1).every((r,a)=>r===t[a])?e[e.length-1]-t[t.length-1]:0}function kq(e,t,n=!1){let{routesMeta:r}=e,a={},o="/",s=[];for(let u=0;u{if(p==="*"){let y=u[m]||"";s=o.slice(0,o.length-y.length).replace(/(.)\/+$/,"$1")}const b=u[m];return g&&!b?d[p]=void 0:d[p]=(b||"").replace(/%2F/g,"/"),d},{}),pathname:o,pathnameBase:s,pattern:e}}function Tq(e,t=!1,n=!0){zr(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let r=[],a="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(s,u,c)=>(r.push({paramName:u,isOptional:c!=null}),c?"/?([^\\/]+)?":"/([^\\/]+)"));return e.endsWith("*")?(r.push({paramName:"*"}),a+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?a+="\\/*$":e!==""&&e!=="/"&&(a+="(?:(?=\\/|$))"),[new RegExp(a,t?void 0:"i"),r]}function Aq(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return zr(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function Ua(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}function Rq(e,t="/"){let{pathname:n,search:r="",hash:a=""}=typeof e=="string"?wi(e):e;return{pathname:n?n.startsWith("/")?n:Cq(n,t):t,search:Oq(r),hash:Iq(a)}}function Cq(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(a=>{a===".."?n.length>1&&n.pop():a!=="."&&n.push(a)}),n.length>1?n.join("/"):"/"}function Wh(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function _q(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function Mz(e){let t=_q(e);return t.map((n,r)=>r===t.length-1?n.pathname:n.pathnameBase)}function Pz(e,t,n,r=!1){let a;typeof e=="string"?a=wi(e):(a={...e},Gt(!a.pathname||!a.pathname.includes("?"),Wh("?","pathname","search",a)),Gt(!a.pathname||!a.pathname.includes("#"),Wh("#","pathname","hash",a)),Gt(!a.search||!a.search.includes("#"),Wh("#","search","hash",a)));let o=e===""||a.pathname==="",s=o?"/":a.pathname,u;if(s==null)u=n;else{let g=t.length-1;if(!r&&s.startsWith("..")){let m=s.split("/");for(;m[0]==="..";)m.shift(),g-=1;a.pathname=m.join("/")}u=g>=0?t[g]:"/"}let c=Rq(a,u),d=s&&s!=="/"&&s.endsWith("/"),p=(o||s===".")&&n.endsWith("/");return!c.pathname.endsWith("/")&&(d||p)&&(c.pathname+="/"),c}var za=e=>e.join("/").replace(/\/\/+/g,"/"),Nq=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),Oq=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,Iq=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e;function Dq(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}var Fz=["POST","PUT","PATCH","DELETE"];new Set(Fz);var Lq=["GET",...Fz];new Set(Lq);var js=E.createContext(null);js.displayName="DataRouter";var $f=E.createContext(null);$f.displayName="DataRouterState";var zz=E.createContext({isTransitioning:!1});zz.displayName="ViewTransition";var Mq=E.createContext(new Map);Mq.displayName="Fetchers";var Pq=E.createContext(null);Pq.displayName="Await";var ia=E.createContext(null);ia.displayName="Navigation";var Bu=E.createContext(null);Bu.displayName="Location";var qa=E.createContext({outlet:null,matches:[],isDataRoute:!1});qa.displayName="Route";var m0=E.createContext(null);m0.displayName="RouteError";function Fq(e,{relative:t}={}){Gt(Uu(),"useHref() may be used only in the context of a component.");let{basename:n,navigator:r}=E.useContext(ia),{hash:a,pathname:o,search:s}=ju(e,{relative:t}),u=o;return n!=="/"&&(u=o==="/"?n:za([n,o])),r.createHref({pathname:u,search:s,hash:a})}function Uu(){return E.useContext(Bu)!=null}function xi(){return Gt(Uu(),"useLocation() may be used only in the context of a component."),E.useContext(Bu).location}var Bz="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Uz(e){E.useContext(ia).static||E.useLayoutEffect(e)}function b0(){let{isDataRoute:e}=E.useContext(qa);return e?Xq():zq()}function zq(){Gt(Uu(),"useNavigate() may be used only in the context of a component.");let e=E.useContext(js),{basename:t,navigator:n}=E.useContext(ia),{matches:r}=E.useContext(qa),{pathname:a}=xi(),o=JSON.stringify(Mz(r)),s=E.useRef(!1);return Uz(()=>{s.current=!0}),E.useCallback((c,d={})=>{if(zr(s.current,Bz),!s.current)return;if(typeof c=="number"){n.go(c);return}let p=Pz(c,JSON.parse(o),a,d.relative==="path");e==null&&t!=="/"&&(p.pathname=p.pathname==="/"?t:za([t,p.pathname])),(d.replace?n.replace:n.push)(p,d.state,d)},[t,n,o,a,e])}E.createContext(null);function ju(e,{relative:t}={}){let{matches:n}=E.useContext(qa),{pathname:r}=xi(),a=JSON.stringify(Mz(n));return E.useMemo(()=>Pz(e,JSON.parse(a),r,t==="path"),[e,a,r,t])}function Bq(e,t){return jz(e,t)}function jz(e,t,n,r){var x;Gt(Uu(),"useRoutes() may be used only in the context of a component.");let{navigator:a,static:o}=E.useContext(ia),{matches:s}=E.useContext(qa),u=s[s.length-1],c=u?u.params:{},d=u?u.pathname:"/",p=u?u.pathnameBase:"/",g=u&&u.route;{let R=g&&g.path||"";Gz(d,!g||R.endsWith("*")||R.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${d}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. -Please change the parent to .`)}let m=xi(),b;if(t){let A=typeof t=="string"?wi(t):t;Gt(p==="/"||((x=A.pathname)==null?void 0:x.startsWith(p)),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${p}" but pathname "${A.pathname}" was given in the \`location\` prop.`),b=A}else b=m;let y=b.pathname||"/",S=y;if(p!=="/"){let A=p.replace(/^\//,"").split("/");S="/"+y.replace(/^\//,"").split("/").slice(A.length).join("/")}let k=!o&&n&&n.matches&&n.matches.length>0?n.matches:Iz(e,{pathname:S});Br(g||k!=null,`No routes matched location "${b.pathname}${b.search}${b.hash}" `),Br(k==null||k[k.length-1].route.element!==void 0||k[k.length-1].route.Component!==void 0||k[k.length-1].route.lazy!==void 0,`Matched leaf route at location "${b.pathname}${b.search}${b.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let R=Yq(k&&k.map(A=>Object.assign({},A,{params:Object.assign({},c,A.params),pathname:za([p,a.encodeLocation?a.encodeLocation(A.pathname).pathname:A.pathname]),pathnameBase:A.pathnameBase==="/"?p:za([p,a.encodeLocation?a.encodeLocation(A.pathnameBase).pathname:A.pathnameBase])})),s,n,r);return t&&R?E.createElement(Bu.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...b},navigationType:"POP"}},R):R}function $q(){let e=Jq(),t=Fq(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r="rgba(200,200,200, 0.5)",a={padding:"0.5rem",backgroundColor:r},o={padding:"2px 4px",backgroundColor:r},s=null;return console.error("Error handled by React Router default ErrorBoundary:",e),s=E.createElement(E.Fragment,null,E.createElement("p",null,"💿 Hey developer 👋"),E.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",E.createElement("code",{style:o},"ErrorBoundary")," or"," ",E.createElement("code",{style:o},"errorElement")," prop on your route.")),E.createElement(E.Fragment,null,E.createElement("h2",null,"Unexpected Application Error!"),E.createElement("h3",{style:{fontStyle:"italic"}},t),n?E.createElement("pre",{style:a},n):null,s)}var qq=E.createElement($q,null),Vq=class extends E.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!=="idle"&&e.revalidation==="idle"?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error!==void 0?e.error:t.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){console.error("React Router caught the following error during render",e,t)}render(){return this.state.error!==void 0?E.createElement(qa.Provider,{value:this.props.routeContext},E.createElement(m0.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function Wq({routeContext:e,match:t,children:n}){let r=E.useContext(js);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),E.createElement(qa.Provider,{value:e},n)}function Yq(e,t=[],n=null,r=null){if(e==null){if(!n)return null;if(n.errors)e=n.matches;else if(t.length===0&&!n.initialized&&n.matches.length>0)e=n.matches;else return null}let a=e,o=n==null?void 0:n.errors;if(o!=null){let c=a.findIndex(d=>d.route.id&&(o==null?void 0:o[d.route.id])!==void 0);Gt(c>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(o).join(",")}`),a=a.slice(0,Math.min(a.length,c+1))}let s=!1,u=-1;if(n)for(let c=0;c=0?a=a.slice(0,u+1):a=[a[0]];break}}}return a.reduceRight((c,d,p)=>{let g,m=!1,b=null,y=null;n&&(g=o&&d.route.id?o[d.route.id]:void 0,b=d.route.errorElement||qq,s&&(u<0&&p===0?(Gz("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),m=!0,y=null):u===p&&(m=!0,y=d.route.hydrateFallbackElement||null)));let S=t.concat(a.slice(0,p+1)),k=()=>{let R;return g?R=b:m?R=y:d.route.Component?R=E.createElement(d.route.Component,null):d.route.element?R=d.route.element:R=c,E.createElement(Wq,{match:d,routeContext:{outlet:c,matches:S,isDataRoute:n!=null},children:R})};return n&&(d.route.ErrorBoundary||d.route.errorElement||p===0)?E.createElement(Vq,{location:n.location,revalidation:n.revalidation,component:b,error:g,children:k(),routeContext:{outlet:null,matches:S,isDataRoute:!0}}):k()},null)}function y0(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Kq(e){let t=E.useContext(js);return Gt(t,y0(e)),t}function Xq(e){let t=E.useContext($f);return Gt(t,y0(e)),t}function Zq(e){let t=E.useContext(qa);return Gt(t,y0(e)),t}function v0(e){let t=Zq(e),n=t.matches[t.matches.length-1];return Gt(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function Qq(){return v0("useRouteId")}function Jq(){var r;let e=E.useContext(m0),t=Xq("useRouteError"),n=v0("useRouteError");return e!==void 0?e:(r=t.errors)==null?void 0:r[n]}function e9(){let{router:e}=Kq("useNavigate"),t=v0("useNavigate"),n=E.useRef(!1);return Uz(()=>{n.current=!0}),E.useCallback(async(a,o={})=>{Br(n.current,Bz),n.current&&(typeof a=="number"?e.navigate(a):await e.navigate(a,{fromRouteId:t,...o}))},[e,t])}var n_={};function Gz(e,t,n){!t&&!n_[e]&&(n_[e]=!0,Br(!1,n))}E.memo(t9);function t9({routes:e,future:t,state:n}){return jz(e,void 0,n,t)}function Qx(e){Gt(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function n9({basename:e="/",children:t=null,location:n,navigationType:r="POP",navigator:a,static:o=!1}){Gt(!Uu(),"You cannot render a inside another . You should never have more than one in your app.");let s=e.replace(/^\/*/,"/"),u=E.useMemo(()=>({basename:s,navigator:a,static:o,future:{}}),[s,a,o]);typeof n=="string"&&(n=wi(n));let{pathname:c="/",search:d="",hash:p="",state:g=null,key:m="default"}=n,b=E.useMemo(()=>{let y=Ua(c,s);return y==null?null:{location:{pathname:y,search:d,hash:p,state:g,key:m},navigationType:r}},[s,c,d,p,g,m,r]);return Br(b!=null,` is not able to match the URL "${c}${d}${p}" because it does not start with the basename, so the won't render anything.`),b==null?null:E.createElement(ia.Provider,{value:u},E.createElement(Bu.Provider,{children:t,value:b}))}function r9({children:e,location:t}){return Hq(Jx(e),t)}function Jx(e,t=[]){let n=[];return E.Children.forEach(e,(r,a)=>{if(!E.isValidElement(r))return;let o=[...t,a];if(r.type===E.Fragment){n.push.apply(n,Jx(r.props.children,o));return}Gt(r.type===Qx,`[${typeof r.type=="string"?r.type:r.type.name}] is not a component. All component children of must be a or `),Gt(!r.props.index||!r.props.children,"An index route cannot have child routes.");let s={id:r.props.id||o.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,loader:r.props.loader,action:r.props.action,hydrateFallbackElement:r.props.hydrateFallbackElement,HydrateFallback:r.props.HydrateFallback,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.hasErrorBoundary===!0||r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(s.children=Jx(r.props.children,o)),n.push(s)}),n}var qd="get",Vd="application/x-www-form-urlencoded";function qf(e){return e!=null&&typeof e.tagName=="string"}function a9(e){return qf(e)&&e.tagName.toLowerCase()==="button"}function o9(e){return qf(e)&&e.tagName.toLowerCase()==="form"}function i9(e){return qf(e)&&e.tagName.toLowerCase()==="input"}function s9(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function l9(e,t){return e.button===0&&(!t||t==="_self")&&!s9(e)}var gd=null;function u9(){if(gd===null)try{new FormData(document.createElement("form"),0),gd=!1}catch{gd=!0}return gd}var c9=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Yh(e){return e!=null&&!c9.has(e)?(Br(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${Vd}"`),null):e}function d9(e,t){let n,r,a,o,s;if(o9(e)){let u=e.getAttribute("action");r=u?Ua(u,t):null,n=e.getAttribute("method")||qd,a=Yh(e.getAttribute("enctype"))||Vd,o=new FormData(e)}else if(a9(e)||i9(e)&&(e.type==="submit"||e.type==="image")){let u=e.form;if(u==null)throw new Error('Cannot submit a - + + + {message && ( +
+ {message} +
+ )} + ) diff --git a/lightrag_webui/src/components/MessageAlert.tsx b/lightrag_webui/src/components/MessageAlert.tsx deleted file mode 100644 index cd23bbd9..00000000 --- a/lightrag_webui/src/components/MessageAlert.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Alert, AlertDescription, AlertTitle } from '@/components/ui/Alert' -import { useBackendState } from '@/stores/state' -import { useEffect, useState } from 'react' -import { cn } from '@/lib/utils' - -// import Button from '@/components/ui/Button' -// import { controlButtonVariant } from '@/lib/constants' - -import { AlertCircle } from 'lucide-react' - -const MessageAlert = () => { - const health = useBackendState.use.health() - const message = useBackendState.use.message() - const messageTitle = useBackendState.use.messageTitle() - const [isMounted, setIsMounted] = useState(false) - - useEffect(() => { - setTimeout(() => { - setIsMounted(true) - }, 50) - }, []) - - return ( - - {!health && ( -
- -
- )} -
- {messageTitle} - {message} -
- {/*
-
- -
*/} - - ) -} - -export default MessageAlert diff --git a/lightrag_webui/src/components/graph/StatusCard.tsx b/lightrag_webui/src/components/status/StatusCard.tsx similarity index 100% rename from lightrag_webui/src/components/graph/StatusCard.tsx rename to lightrag_webui/src/components/status/StatusCard.tsx diff --git a/lightrag_webui/src/components/graph/StatusIndicator.tsx b/lightrag_webui/src/components/status/StatusIndicator.tsx similarity index 97% rename from lightrag_webui/src/components/graph/StatusIndicator.tsx rename to lightrag_webui/src/components/status/StatusIndicator.tsx index d7a1831f..263bb99e 100644 --- a/lightrag_webui/src/components/graph/StatusIndicator.tsx +++ b/lightrag_webui/src/components/status/StatusIndicator.tsx @@ -2,7 +2,7 @@ import { cn } from '@/lib/utils' import { useBackendState } from '@/stores/state' import { useEffect, useState } from 'react' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover' -import StatusCard from '@/components/graph/StatusCard' +import StatusCard from '@/components/status/StatusCard' import { useTranslation } from 'react-i18next' const StatusIndicator = () => { diff --git a/lightrag_webui/src/components/ui/AsyncSearch.tsx b/lightrag_webui/src/components/ui/AsyncSearch.tsx index b1c25fe9..7b71fd77 100644 --- a/lightrag_webui/src/components/ui/AsyncSearch.tsx +++ b/lightrag_webui/src/components/ui/AsyncSearch.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from 'react' +import React, { useState, useEffect, useCallback, useRef } from 'react' import { Loader2 } from 'lucide-react' import { useDebounce } from '@/hooks/useDebounce' @@ -81,100 +81,97 @@ export function AsyncSearch({ const [options, setOptions] = useState([]) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) - const [selectedValue, setSelectedValue] = useState(value) - const [focusedValue, setFocusedValue] = useState(null) const [searchTerm, setSearchTerm] = useState('') const debouncedSearchTerm = useDebounce(searchTerm, preload ? 0 : 150) - const [originalOptions, setOriginalOptions] = useState([]) + const containerRef = useRef(null) useEffect(() => { setMounted(true) - setSelectedValue(value) - }, [value]) + }, []) - // Effect for initial fetch + // Handle clicks outside of the component useEffect(() => { - const initializeOptions = async () => { - try { - setLoading(true) - setError(null) - // If we have a value, use it for the initial search - const data = value !== null ? await fetcher(value) : [] - setOriginalOptions(data) - setOptions(data) - } catch (err) { - setError(err instanceof Error ? err.message : 'Failed to fetch options') - } finally { - setLoading(false) + const handleClickOutside = (event: MouseEvent) => { + if ( + containerRef.current && + !containerRef.current.contains(event.target as Node) && + open + ) { + setOpen(false) } } - if (!mounted) { - initializeOptions() + document.addEventListener('mousedown', handleClickOutside) + return () => { + document.removeEventListener('mousedown', handleClickOutside) } - }, [mounted, fetcher, value]) + }, [open]) + const fetchOptions = useCallback(async (query: string) => { + try { + setLoading(true) + setError(null) + const data = await fetcher(query) + setOptions(data) + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to fetch options') + } finally { + setLoading(false) + } + }, [fetcher]) + + // Load options when search term changes useEffect(() => { - const fetchOptions = async () => { - try { - setLoading(true) - setError(null) - const data = await fetcher(debouncedSearchTerm) - setOriginalOptions(data) - setOptions(data) - } catch (err) { - setError(err instanceof Error ? err.message : 'Failed to fetch options') - } finally { - setLoading(false) - } - } + if (!mounted) return - if (!mounted) { - fetchOptions() - } else if (!preload) { - fetchOptions() - } else if (preload) { + if (preload) { if (debouncedSearchTerm) { - setOptions( - originalOptions.filter((option) => + setOptions((prev) => + prev.filter((option) => filterFn ? filterFn(option, debouncedSearchTerm) : true ) ) - } else { - setOptions(originalOptions) } + } else { + fetchOptions(debouncedSearchTerm) } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [fetcher, debouncedSearchTerm, mounted, preload, filterFn]) + }, [mounted, debouncedSearchTerm, preload, filterFn, fetchOptions]) - const handleSelect = useCallback( - (currentValue: string) => { - if (currentValue !== selectedValue) { - setSelectedValue(currentValue) - onChange(currentValue) - } + // Load initial value + useEffect(() => { + if (!mounted || !value) return + fetchOptions(value) + }, [mounted, value, fetchOptions]) + + const handleSelect = useCallback((currentValue: string) => { + onChange(currentValue) + requestAnimationFrame(() => { + // Blur the input to ensure focus event triggers on next click + const input = document.activeElement as HTMLElement + input?.blur() + // Close the dropdown setOpen(false) - }, - [selectedValue, setSelectedValue, setOpen, onChange] - ) + }) + }, [onChange]) - const handleFocus = useCallback( - (currentValue: string) => { - if (currentValue !== focusedValue) { - setFocusedValue(currentValue) - onFocus(currentValue) - } - }, - [focusedValue, setFocusedValue, onFocus] - ) + const handleFocus = useCallback(() => { + setOpen(true) + // Use current search term to fetch options + fetchOptions(searchTerm) + }, [searchTerm, fetchOptions]) + + const handleMouseDown = useCallback((e: React.MouseEvent) => { + const target = e.target as HTMLElement + if (target.closest('.cmd-item')) { + e.preventDefault() + } + }, []) return (
{ - setOpen(true) - }} - onBlur={() => setOpen(false)} + onMouseDown={handleMouseDown} >
@@ -182,12 +179,13 @@ export function AsyncSearch({ placeholder={placeholder} value={searchTerm} className="max-h-8" + onFocus={handleFocus} onValueChange={(value) => { setSearchTerm(value) - if (value && !open) setOpen(true) + if (!open) setOpen(true) }} /> - {loading && options.length > 0 && ( + {loading && (
@@ -209,8 +207,8 @@ export function AsyncSearch({ key={getOptionValue(option) + `${idx}`} value={getOptionValue(option)} onSelect={handleSelect} - onMouseEnter={() => handleFocus(getOptionValue(option))} - className="truncate" + onMouseMove={() => onFocus(getOptionValue(option))} + className="truncate cmd-item" > {renderOption(option)} diff --git a/lightrag_webui/src/features/SiteHeader.tsx b/lightrag_webui/src/features/SiteHeader.tsx index fb21df40..ccbfd25e 100644 --- a/lightrag_webui/src/features/SiteHeader.tsx +++ b/lightrag_webui/src/features/SiteHeader.tsx @@ -67,18 +67,20 @@ export default function SiteHeader() { return (
- - + -
+
{isGuestMode && (
@@ -87,7 +89,7 @@ export default function SiteHeader() { )}
-