workspace working

This commit is contained in:
2026-01-12 22:31:11 +08:00
parent 2738a822d1
commit 370fe6368a
149 changed files with 4648 additions and 660 deletions

116
.env
View File

@@ -1,105 +1,27 @@
### Server Configuration
HOST=0.0.0.0
PORT=3015
WEBUI_TITLE='Search Anything Railway'
WEBUI_DESCRIPTION="Search Anything Railway!"
# Authentication (Disabled)
# LIGHTRAG_API_KEY=jleu1212
# AUTH_ACCOUNTS=jleu3482:jleu1212
### Login Configuration (optional)
AUTH_ACCOUNTS='jleu3482:jleu1212'
TOKEN_SECRET=lightrag-production-key-2024
TOKEN_EXPIRE_HOURS=48
# DeepSeek API Configuration
OPENAI_API_KEY=sk-55f6e57f1d834b0e93ceaf98cc2cb715
OPENAI_BASE_URL=https://api.deepseek.com/v1
LLM_MODEL=deepseek-chat
### RAGAnything Configuration
PARSE_METHOD=auto
PARSER=mineru
ENABLE_IMAGE_PROCESSING=true
ENABLE_TABLE_PROCESSING=true
ENABLE_EQUATION_PROCESSING=true
MAX_CONCURRENT_FILES=4
SUPPORTED_FILE_EXTENSIONS=.pdf,.jpg,.jpeg,.png,.bmp,.tiff,.tif,.gif,.webp,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.txt,.md
RECURSIVE_FOLDER_PROCESSING=true
### Context Extraction
CONTEXT_WINDOW=1
CONTEXT_MODE=page
MAX_CONTEXT_TOKENS=2000
INCLUDE_HEADERS=true
INCLUDE_CAPTIONS=true
### Storage Configuration
LIGHTRAG_KV_STORAGE=RedisKVStorage
LIGHTRAG_VECTOR_STORAGE=QdrantVectorDBStorage
LIGHTRAG_DOC_STATUS_STORAGE=PGDocStatusStorage
LIGHTRAG_GRAPH_STORAGE=Neo4JStorage
### PostgreSQL Configuration
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=jleu3482
POSTGRES_PASSWORD=jleu1212
POSTGRES_DATABASE=rag_anything
POSTGRES_MAX_CONNECTIONS=20
### Neo4j Configuration
# Database Configuration
REDIS_URI=redis://localhost:6379
NEO4J_URI=bolt://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=jleu1212
QDRANT_URI=http://localhost:6333/
POSTGRES_URI=postgresql://jleu3482:jleu1212@localhost:5432/rag_anything
### Qdrant Configuration
QDRANT_URL=http://localhost:6333
# QDRANT_API_KEY=your-api-key-if-needed
### Redis Configuration
REDIS_URI=redis://localhost:6379
### LLM Configuration (for deepseek-chat)
LLM_BINDING=openai
LLM_MODEL=deepseek-chat
LLM_BINDING_HOST=https://api.deepseek.com/v1
LLM_BINDING_API_KEY=sk-55f6e57f1d834b0e93ceaf98cc2cb715
OPENAI_API_KEY=sk-55f6e57f1d834b0e93ceaf98cc2cb715
OPENAI_API_BASE=https://api.deepseek.com/v1
ENABLE_LLM_CACHE=true
ENABLE_LLM_CACHE_FOR_EXTRACT=true
TIMEOUT=240
TEMPERATURE=0
MAX_ASYNC=8
MAX_TOKENS=32768
### Embedding Configuration (Snowflake Arctic Embed)
EMBEDDING_BINDING=ollama
EMBEDDING_MODEL=snowflake-arctic-embed2:latest
EMBEDDING_DIM=1024
# Embedding Configuration
OLLAMA_EMBEDDING_MODEL=snowflake-arctic-embed:latest
OLLAMA_RERANKER_MODEL=jina-reranker:latest
EMBEDDING_BINDING_API_KEY=governor
OLLAMA_API_KEY=governor
EMBEDDING_BINDING_HOST=http://localhost:11434
EMBEDDING_BATCH_NUM=32
EMBEDDING_FUNC_MAX_ASYNC=16
OLLAMA_HOST=http://localhost:11434
### Reranker Configuration (jina-reranker-v2)
RERANK_BINDING=jina
RERANK_MODEL=jina-reranker-v2:latest
### Performance Optimization
MAX_PARALLEL_INSERT=4
CHUNK_SIZE=1200
CHUNK_OVERLAP_SIZE=100
MAX_GRAPH_NODES=1000
### Logging
LOG_LEVEL=INFO
VERBOSE=False
### Summary Configuration
SUMMARY_LANGUAGE=English
FORCE_LLM_SUMMARY_ON_MERGE=6
MAX_TOKEN_SUMMARY=500
### Query Settings
HISTORY_TURNS=3
COSINE_THRESHOLD=0.2
TOP_K=60
MAX_TOKEN_TEXT_CHUNK=4000
MAX_TOKEN_RELATION_DESC=4000
MAX_TOKEN_ENTITY_DESC=4000
### Entity Extraction Optimization
OPTIMIZE_ENTITY_EXTRACTION=false
# Performance Settings
PYTHONIOENCODING=utf-8

View File

@@ -17,12 +17,13 @@ from fastapi import (
Depends,
File,
HTTPException,
Request,
UploadFile,
)
from pydantic import BaseModel, Field, field_validator
from lightrag import LightRAG
from lightrag.base import DeletionResult, DocProcessingStatus, DocStatus
from lightrag.base import DeletionResult, DocProcessingStatus, DocStatus, StoragesStatus
from lightrag.utils import generate_track_id
from lightrag.api.utils_api import get_combined_auth_dependency
from ..config import global_args
@@ -1612,17 +1613,40 @@ async def background_delete_documents(
def create_document_routes(
workspace_manager, api_key: Optional[str] = None
):
# Get default RAG instance and document manager from workspace manager
rag = workspace_manager.get_rag()
doc_manager = workspace_manager.get_document_manager()
# Create combined auth dependency for document routes
combined_auth = get_combined_auth_dependency(api_key)
# Dependency to get workspace-specific RAG and DocumentManager based on X-Workspace header
async def get_workspace_rag_and_manager(request: Request):
workspace = request.headers.get("X-Workspace", "").strip()
rag = workspace_manager.get_rag(workspace)
doc_manager = workspace_manager.get_document_manager(workspace)
# Ensure storages are initialized for this workspace
try:
# Always attempt to initialize storages if not already initialized
logger.info(f"Workspace '{workspace}': storages status = {rag._storages_status}")
if rag._storages_status != StoragesStatus.FINALIZED:
logger.info(f"Initializing storages for workspace '{workspace}'")
await rag.initialize_storages()
logger.info(f"Storages initialized, status now = {rag._storages_status}")
# Debug: check doc_status lock
if hasattr(rag, 'doc_status') and hasattr(rag.doc_status, '_storage_lock'):
lock = rag.doc_status._storage_lock
logger.info(f"doc_status._storage_lock = {lock}, type = {type(lock)}")
if lock is None:
logger.error("doc_status._storage_lock is None! This will cause errors.")
except Exception as e:
logger.error(f"Failed to initialize storages for workspace '{workspace}': {e}")
raise HTTPException(status_code=500, detail=f"Storage initialization failed: {e}")
return rag, doc_manager
@router.post(
"/scan", response_model=ScanResponse, dependencies=[Depends(combined_auth)]
)
async def scan_for_new_documents(background_tasks: BackgroundTasks):
async def scan_for_new_documents(
background_tasks: BackgroundTasks,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager)
):
"""
Trigger the scanning process for new documents.
@@ -1633,6 +1657,7 @@ def create_document_routes(
Returns:
ScanResponse: A response object containing the scanning status and track_id
"""
rag, doc_manager = workspace_rag_and_manager
# Generate track_id with "scan" prefix for scanning operation
track_id = generate_track_id("scan")
@@ -1648,7 +1673,9 @@ def create_document_routes(
"/upload", response_model=InsertResponse, dependencies=[Depends(combined_auth)]
)
async def upload_to_input_dir(
background_tasks: BackgroundTasks, file: UploadFile = File(...)
background_tasks: BackgroundTasks,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
file: UploadFile = File(...)
):
"""
Upload a file to the input directory and index it.
@@ -1659,6 +1686,7 @@ def create_document_routes(
Args:
background_tasks: FastAPI BackgroundTasks for async processing
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
file (UploadFile): The file to be uploaded. It must have an allowed extension.
Returns:
@@ -1668,6 +1696,7 @@ def create_document_routes(
Raises:
HTTPException: If the file type is not supported (400) or other errors occur (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
# Sanitize filename to prevent Path Traversal attacks
safe_filename = sanitize_filename(file.filename, doc_manager.input_dir)
@@ -1710,7 +1739,8 @@ def create_document_routes(
"/text", response_model=InsertResponse, dependencies=[Depends(combined_auth)]
)
async def insert_text(
request: InsertTextRequest, background_tasks: BackgroundTasks
request: InsertTextRequest, background_tasks: BackgroundTasks,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager)
):
"""
Insert text into the RAG system.
@@ -1721,6 +1751,7 @@ def create_document_routes(
Args:
request (InsertTextRequest): The request body containing the text to be inserted.
background_tasks: FastAPI BackgroundTasks for async processing
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
InsertResponse: A response object containing the status of the operation.
@@ -1728,6 +1759,7 @@ def create_document_routes(
Raises:
HTTPException: If an error occurs during text processing (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
# Generate track_id for text insertion
track_id = generate_track_id("insert")
@@ -1756,7 +1788,8 @@ def create_document_routes(
dependencies=[Depends(combined_auth)],
)
async def insert_texts(
request: InsertTextsRequest, background_tasks: BackgroundTasks
request: InsertTextsRequest, background_tasks: BackgroundTasks,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager)
):
"""
Insert multiple texts into the RAG system.
@@ -1767,6 +1800,7 @@ def create_document_routes(
Args:
request (InsertTextsRequest): The request body containing the list of texts.
background_tasks: FastAPI BackgroundTasks for async processing
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
InsertResponse: A response object containing the status of the operation.
@@ -1774,6 +1808,7 @@ def create_document_routes(
Raises:
HTTPException: If an error occurs during text processing (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
# Generate track_id for texts insertion
track_id = generate_track_id("insert")
@@ -1799,7 +1834,9 @@ def create_document_routes(
@router.delete(
"", response_model=ClearDocumentsResponse, dependencies=[Depends(combined_auth)]
)
async def clear_documents():
async def clear_documents(
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager)
):
"""
Clear all documents from the RAG system.
@@ -1807,6 +1844,9 @@ def create_document_routes(
It uses the storage drop methods to properly clean up all data and removes all files
from the input directory.
Args:
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
ClearDocumentsResponse: A response object containing the status and message.
- status="success": All documents and files were successfully cleared.
@@ -1825,6 +1865,8 @@ def create_document_routes(
get_pipeline_status_lock,
)
rag, doc_manager = workspace_rag_and_manager
# Get pipeline status and lock
pipeline_status = await get_namespace_data("pipeline_status")
pipeline_status_lock = get_pipeline_status_lock()
@@ -2080,13 +2122,18 @@ def create_document_routes(
@router.get(
"", response_model=DocsStatusesResponse, dependencies=[Depends(combined_auth)]
)
async def documents() -> DocsStatusesResponse:
async def documents(
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
) -> DocsStatusesResponse:
"""
Get the status of all documents in the system.
This endpoint retrieves the current status of all documents, grouped by their
processing status (PENDING, PROCESSING, PROCESSED, FAILED).
Args:
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
DocsStatusesResponse: A response object containing a dictionary where keys are
DocStatus values and values are lists of DocStatusResponse
@@ -2095,6 +2142,7 @@ def create_document_routes(
Raises:
HTTPException: If an error occurs while retrieving document statuses (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
statuses = (
DocStatus.PENDING,
@@ -2152,6 +2200,7 @@ def create_document_routes(
async def delete_document(
delete_request: DeleteDocRequest,
background_tasks: BackgroundTasks,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
) -> DeleteDocByIdResponse:
"""
Delete documents and all their associated data by their IDs using background processing.
@@ -2166,6 +2215,7 @@ def create_document_routes(
Args:
delete_request (DeleteDocRequest): The request containing the document IDs and delete_file options.
background_tasks: FastAPI BackgroundTasks for async processing
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
DeleteDocByIdResponse: The result of the deletion operation.
@@ -2177,6 +2227,7 @@ def create_document_routes(
HTTPException:
- 500: If an unexpected internal error occurs during initialization.
"""
rag, doc_manager = workspace_rag_and_manager
doc_ids = delete_request.doc_ids
# The rag object is initialized from the server startup args,
@@ -2227,7 +2278,10 @@ def create_document_routes(
response_model=ClearCacheResponse,
dependencies=[Depends(combined_auth)],
)
async def clear_cache(request: ClearCacheRequest):
async def clear_cache(
request: ClearCacheRequest,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
):
"""
Clear all cache data from the LLM response cache storage.
@@ -2236,6 +2290,7 @@ def create_document_routes(
Args:
request (ClearCacheRequest): The request body (ignored for compatibility).
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
ClearCacheResponse: A response object containing the status and message.
@@ -2243,6 +2298,7 @@ def create_document_routes(
Raises:
HTTPException: If an error occurs during cache clearing (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
# Call the aclear_cache method (no modes parameter)
await rag.aclear_cache()
@@ -2261,12 +2317,16 @@ def create_document_routes(
response_model=DeletionResult,
dependencies=[Depends(combined_auth)],
)
async def delete_entity(request: DeleteEntityRequest):
async def delete_entity(
request: DeleteEntityRequest,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
):
"""
Delete an entity and all its relationships from the knowledge graph.
Args:
request (DeleteEntityRequest): The request body containing the entity name.
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
DeletionResult: An object containing the outcome of the deletion process.
@@ -2274,6 +2334,7 @@ def create_document_routes(
Raises:
HTTPException: If the entity is not found (404) or an error occurs (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
result = await rag.adelete_by_entity(entity_name=request.entity_name)
if result.status == "not_found":
@@ -2296,12 +2357,16 @@ def create_document_routes(
response_model=DeletionResult,
dependencies=[Depends(combined_auth)],
)
async def delete_relation(request: DeleteRelationRequest):
async def delete_relation(
request: DeleteRelationRequest,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
):
"""
Delete a relationship between two entities from the knowledge graph.
Args:
request (DeleteRelationRequest): The request body containing the source and target entity names.
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
DeletionResult: An object containing the outcome of the deletion process.
@@ -2309,6 +2374,7 @@ def create_document_routes(
Raises:
HTTPException: If the relation is not found (404) or an error occurs (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
result = await rag.adelete_by_relation(
source_entity=request.source_entity,
@@ -2334,7 +2400,10 @@ def create_document_routes(
response_model=TrackStatusResponse,
dependencies=[Depends(combined_auth)],
)
async def get_track_status(track_id: str) -> TrackStatusResponse:
async def get_track_status(
track_id: str,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
) -> TrackStatusResponse:
"""
Get the processing status of documents by tracking ID.
@@ -2343,6 +2412,7 @@ def create_document_routes(
Args:
track_id (str): The tracking ID returned from upload, text, or texts endpoints
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
TrackStatusResponse: A response object containing:
@@ -2353,6 +2423,7 @@ def create_document_routes(
Raises:
HTTPException: If track_id is invalid (400) or an error occurs (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
# Validate track_id
if not track_id or not track_id.strip():
@@ -2410,6 +2481,7 @@ def create_document_routes(
)
async def get_documents_paginated(
request: DocumentsRequest,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
) -> PaginatedDocsResponse:
"""
Get documents with pagination support.
@@ -2420,6 +2492,7 @@ def create_document_routes(
Args:
request (DocumentsRequest): The request body containing pagination parameters
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
PaginatedDocsResponse: A response object containing:
@@ -2430,6 +2503,7 @@ def create_document_routes(
Raises:
HTTPException: If an error occurs while retrieving documents (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
# Get paginated documents and status counts in parallel
docs_task = rag.doc_status.get_docs_paginated(
@@ -2495,19 +2569,25 @@ def create_document_routes(
response_model=StatusCountsResponse,
dependencies=[Depends(combined_auth)],
)
async def get_document_status_counts() -> StatusCountsResponse:
async def get_document_status_counts(
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
) -> StatusCountsResponse:
"""
Get counts of documents by status.
This endpoint retrieves the count of documents in each processing status
(PENDING, PROCESSING, PROCESSED, FAILED) for all documents in the system.
Args:
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
StatusCountsResponse: A response object containing status counts
Raises:
HTTPException: If an error occurs while retrieving status counts (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
status_counts = await rag.doc_status.get_all_status_counts()
return StatusCountsResponse(status_counts=status_counts)
@@ -2521,7 +2601,10 @@ def create_document_routes(
"/download/{filename}",
dependencies=[Depends(combined_auth)],
)
async def download_document(filename: str):
async def download_document(
filename: str,
workspace_rag_and_manager: tuple = Depends(get_workspace_rag_and_manager),
):
"""
Download a document file by filename.
@@ -2530,6 +2613,7 @@ def create_document_routes(
Args:
filename (str): The name of the file to download
workspace_rag_and_manager: Tuple containing (rag, doc_manager) for the workspace
Returns:
FileResponse: The file content with appropriate headers for download
@@ -2537,6 +2621,7 @@ def create_document_routes(
Raises:
HTTPException: If file is not found (404) or an error occurs (500).
"""
rag, doc_manager = workspace_rag_and_manager
try:
# Sanitize filename to prevent path traversal
safe_filename = sanitize_filename(filename, doc_manager.input_dir)

View File

@@ -153,21 +153,41 @@ def create_query_routes(rag_or_manager, api_key: Optional[str] = None, top_k: in
# Accept either a LightRAG instance or a WorkspaceManager
from lightrag.api.workspace_manager import WorkspaceManager
from lightrag import LightRAG
if isinstance(rag_or_manager, WorkspaceManager):
# Get default RAG instance from workspace manager
rag = rag_or_manager.get_rag()
elif isinstance(rag_or_manager, LightRAG):
rag = rag_or_manager
else:
raise TypeError(f"Expected LightRAG or WorkspaceManager, got {type(rag_or_manager)}")
from fastapi import Request, Depends, HTTPException
from lightrag.base import StoragesStatus
from lightrag.utils import logger
combined_auth = get_combined_auth_dependency(api_key)
# Define dependency to get workspace-specific RAG instance
async def get_workspace_rag(request: Request):
if isinstance(rag_or_manager, WorkspaceManager):
workspace = request.headers.get("X-Workspace", "").strip()
rag = rag_or_manager.get_rag(workspace)
# Ensure storages are initialized for this workspace
try:
logger.info(f"Workspace '{workspace}': storages status = {rag._storages_status}")
if rag._storages_status != StoragesStatus.FINALIZED:
logger.info(f"Initializing storages for workspace '{workspace}'")
await rag.initialize_storages()
logger.info(f"Storages initialized, status now = {rag._storages_status}")
except Exception as e:
logger.error(f"Failed to initialize storages for workspace '{workspace}': {e}")
raise HTTPException(status_code=500, detail=f"Storage initialization failed: {e}")
return rag
elif isinstance(rag_or_manager, LightRAG):
# Single RAG instance mode - ignore workspace header
return rag_or_manager
else:
raise TypeError(f"Expected LightRAG or WorkspaceManager, got {type(rag_or_manager)}")
@router.post(
"/query", response_model=QueryResponse, dependencies=[Depends(combined_auth)]
)
async def query_text(request: QueryRequest):
async def query_text(
request: QueryRequest,
rag: LightRAG = Depends(get_workspace_rag)
):
"""
Handle a POST request at the /query endpoint to process user queries using RAG capabilities.
@@ -200,7 +220,10 @@ def create_query_routes(rag_or_manager, api_key: Optional[str] = None, top_k: in
raise HTTPException(status_code=500, detail=str(e))
@router.post("/query/stream", dependencies=[Depends(combined_auth)])
async def query_text_stream(request: QueryRequest):
async def query_text_stream(
request: QueryRequest,
rag: LightRAG = Depends(get_workspace_rag)
):
"""
This endpoint performs a retrieval-augmented generation (RAG) query and streams the response.
@@ -253,7 +276,10 @@ def create_query_routes(rag_or_manager, api_key: Optional[str] = None, top_k: in
response_model=QueryDataResponse,
dependencies=[Depends(combined_auth)],
)
async def query_data(request: QueryRequest):
async def query_data(
request: QueryRequest,
rag: LightRAG = Depends(get_workspace_rag)
):
"""
Retrieve structured data without LLM generation.

View File

@@ -72,21 +72,41 @@ def create_search_routes(rag_or_manager, api_key: Optional[str] = None, top_k: i
# Accept either a LightRAG instance or a WorkspaceManager
from lightrag.api.workspace_manager import WorkspaceManager
from lightrag import LightRAG
if isinstance(rag_or_manager, WorkspaceManager):
# Get default RAG instance from workspace manager
rag = rag_or_manager.get_rag()
elif isinstance(rag_or_manager, LightRAG):
rag = rag_or_manager
else:
raise TypeError(f"Expected LightRAG or WorkspaceManager, got {type(rag_or_manager)}")
from fastapi import Request, Depends
from lightrag.base import StoragesStatus
from lightrag.utils import logger
combined_auth = get_combined_auth_dependency(api_key)
# Define dependency to get workspace-specific RAG instance
async def get_workspace_rag(request: Request):
if isinstance(rag_or_manager, WorkspaceManager):
workspace = request.headers.get("X-Workspace", "").strip()
rag = rag_or_manager.get_rag(workspace)
# Ensure storages are initialized for this workspace
try:
logger.info(f"Workspace '{workspace}': storages status = {rag._storages_status}")
if rag._storages_status != StoragesStatus.FINALIZED:
logger.info(f"Initializing storages for workspace '{workspace}'")
await rag.initialize_storages()
logger.info(f"Storages initialized, status now = {rag._storages_status}")
except Exception as e:
logger.error(f"Failed to initialize storages for workspace '{workspace}': {e}")
raise HTTPException(status_code=500, detail=f"Storage initialization failed: {e}")
return rag
elif isinstance(rag_or_manager, LightRAG):
# Single RAG instance mode - ignore workspace header
return rag_or_manager
else:
raise TypeError(f"Expected LightRAG or WorkspaceManager, got {type(rag_or_manager)}")
@router.post(
"/search", response_model=SearchResponse, dependencies=[Depends(combined_auth)]
)
async def search_documents(request: SearchRequest):
async def search_documents(
request: SearchRequest,
rag: LightRAG = Depends(get_workspace_rag)
):
"""
Handle a POST request at the /search endpoint to search documents using RAG capabilities.
This is an alias for the /query endpoint with simplified response format.
@@ -173,7 +193,10 @@ def create_search_routes(rag_or_manager, api_key: Optional[str] = None, top_k: i
response_model=SearchDataResponse,
dependencies=[Depends(combined_auth)]
)
async def search_data(request: SearchRequest):
async def search_data(
request: SearchRequest,
rag: LightRAG = Depends(get_workspace_rag)
):
"""
API search endpoint that returns structured data without LLM generation.
This is an alias for the /query/data endpoint.

View File

@@ -79,5 +79,12 @@ async def delete_workspace(
workspace_name: str,
workspace_manager: WorkspaceManager = Depends(get_workspace_manager),
):
"""Delete a workspace (not implemented)."""
raise HTTPException(status_code=501, detail="Workspace deletion not yet implemented")
"""Delete a workspace."""
try:
await workspace_manager.delete_workspace(workspace_name)
return {"message": f"Workspace '{workspace_name}' deleted successfully"}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"Error deleting workspace: {e}")
raise HTTPException(status_code=500, detail=str(e))

View File

@@ -1 +1 @@
import{e as o,c as l,g as b,k as O,h as P,j as p,l as w,m as c,n as v,t as A,o as N}from"./_baseUniq-CZTq81C3.js";import{a_ as g,aw as _,a$ as $,b0 as E,b1 as F,b2 as x,b3 as M,b4 as y,b5 as B,b6 as T}from"./mermaid-vendor-C4V_MkUy.js";var S=/\s/;function G(n){for(var r=n.length;r--&&S.test(n.charAt(r)););return r}var H=/^\s+/;function L(n){return n&&n.slice(0,G(n)+1).replace(H,"")}var m=NaN,R=/^[-+]0x[0-9a-f]+$/i,q=/^0b[01]+$/i,z=/^0o[0-7]+$/i,C=parseInt;function K(n){if(typeof n=="number")return n;if(o(n))return m;if(g(n)){var r=typeof n.valueOf=="function"?n.valueOf():n;n=g(r)?r+"":r}if(typeof n!="string")return n===0?n:+n;n=L(n);var t=q.test(n);return t||z.test(n)?C(n.slice(2),t?2:8):R.test(n)?m:+n}var W=1/0,X=17976931348623157e292;function Y(n){if(!n)return n===0?n:0;if(n=K(n),n===W||n===-1/0){var r=n<0?-1:1;return r*X}return n===n?n:0}function D(n){var r=Y(n),t=r%1;return r===r?t?r-t:r:0}function fn(n){var r=n==null?0:n.length;return r?l(n):[]}var I=Object.prototype,J=I.hasOwnProperty,dn=_(function(n,r){n=Object(n);var t=-1,e=r.length,i=e>2?r[2]:void 0;for(i&&$(r[0],r[1],i)&&(e=1);++t<e;)for(var f=r[t],a=E(f),s=-1,d=a.length;++s<d;){var u=a[s],h=n[u];(h===void 0||F(h,I[u])&&!J.call(n,u))&&(n[u]=f[u])}return n});function un(n){var r=n==null?0:n.length;return r?n[r-1]:void 0}function Q(n){return function(r,t,e){var i=Object(r);if(!x(r)){var f=b(t);r=O(r),t=function(s){return f(i[s],s,i)}}var a=n(r,t,e);return a>-1?i[f?r[a]:a]:void 0}}var U=Math.max;function Z(n,r,t){var e=n==null?0:n.length;if(!e)return-1;var i=t==null?0:D(t);return i<0&&(i=U(e+i,0)),P(n,b(r),i)}var hn=Q(Z);function V(n,r){var t=-1,e=x(n)?Array(n.length):[];return p(n,function(i,f,a){e[++t]=r(i,f,a)}),e}function gn(n,r){var t=M(n)?w:V;return t(n,b(r))}var j=Object.prototype,k=j.hasOwnProperty;function nn(n,r){return n!=null&&k.call(n,r)}function bn(n,r){return n!=null&&c(n,r,nn)}function rn(n,r){return n<r}function tn(n,r,t){for(var e=-1,i=n.length;++e<i;){var f=n[e],a=r(f);if(a!=null&&(s===void 0?a===a&&!o(a):t(a,s)))var s=a,d=f}return d}function mn(n){return n&&n.length?tn(n,y,rn):void 0}function an(n,r,t,e){if(!g(n))return n;r=v(r,n);for(var i=-1,f=r.length,a=f-1,s=n;s!=null&&++i<f;){var d=A(r[i]),u=t;if(d==="__proto__"||d==="constructor"||d==="prototype")return n;if(i!=a){var h=s[d];u=void 0,u===void 0&&(u=g(h)?h:B(r[i+1])?[]:{})}T(s,d,u),s=s[d]}return n}function on(n,r,t){for(var e=-1,i=r.length,f={};++e<i;){var a=r[e],s=N(n,a);t(s,a)&&an(f,v(a,n),s)}return f}export{rn as a,tn as b,V as c,on as d,mn as e,fn as f,hn as g,bn as h,dn as i,D as j,un as l,gn as m,Y as t};
import{e as o,c as l,g as b,k as O,h as P,j as p,l as w,m as c,n as v,t as A,o as N}from"./_baseUniq-DUOGdItU.js";import{a_ as g,aw as _,a$ as $,b0 as E,b1 as F,b2 as x,b3 as M,b4 as y,b5 as B,b6 as T}from"./mermaid-vendor-GB05DkYd.js";var S=/\s/;function G(n){for(var r=n.length;r--&&S.test(n.charAt(r)););return r}var H=/^\s+/;function L(n){return n&&n.slice(0,G(n)+1).replace(H,"")}var m=NaN,R=/^[-+]0x[0-9a-f]+$/i,q=/^0b[01]+$/i,z=/^0o[0-7]+$/i,C=parseInt;function K(n){if(typeof n=="number")return n;if(o(n))return m;if(g(n)){var r=typeof n.valueOf=="function"?n.valueOf():n;n=g(r)?r+"":r}if(typeof n!="string")return n===0?n:+n;n=L(n);var t=q.test(n);return t||z.test(n)?C(n.slice(2),t?2:8):R.test(n)?m:+n}var W=1/0,X=17976931348623157e292;function Y(n){if(!n)return n===0?n:0;if(n=K(n),n===W||n===-1/0){var r=n<0?-1:1;return r*X}return n===n?n:0}function D(n){var r=Y(n),t=r%1;return r===r?t?r-t:r:0}function fn(n){var r=n==null?0:n.length;return r?l(n):[]}var I=Object.prototype,J=I.hasOwnProperty,dn=_(function(n,r){n=Object(n);var t=-1,e=r.length,i=e>2?r[2]:void 0;for(i&&$(r[0],r[1],i)&&(e=1);++t<e;)for(var f=r[t],a=E(f),s=-1,d=a.length;++s<d;){var u=a[s],h=n[u];(h===void 0||F(h,I[u])&&!J.call(n,u))&&(n[u]=f[u])}return n});function un(n){var r=n==null?0:n.length;return r?n[r-1]:void 0}function Q(n){return function(r,t,e){var i=Object(r);if(!x(r)){var f=b(t);r=O(r),t=function(s){return f(i[s],s,i)}}var a=n(r,t,e);return a>-1?i[f?r[a]:a]:void 0}}var U=Math.max;function Z(n,r,t){var e=n==null?0:n.length;if(!e)return-1;var i=t==null?0:D(t);return i<0&&(i=U(e+i,0)),P(n,b(r),i)}var hn=Q(Z);function V(n,r){var t=-1,e=x(n)?Array(n.length):[];return p(n,function(i,f,a){e[++t]=r(i,f,a)}),e}function gn(n,r){var t=M(n)?w:V;return t(n,b(r))}var j=Object.prototype,k=j.hasOwnProperty;function nn(n,r){return n!=null&&k.call(n,r)}function bn(n,r){return n!=null&&c(n,r,nn)}function rn(n,r){return n<r}function tn(n,r,t){for(var e=-1,i=n.length;++e<i;){var f=n[e],a=r(f);if(a!=null&&(s===void 0?a===a&&!o(a):t(a,s)))var s=a,d=f}return d}function mn(n){return n&&n.length?tn(n,y,rn):void 0}function an(n,r,t,e){if(!g(n))return n;r=v(r,n);for(var i=-1,f=r.length,a=f-1,s=n;s!=null&&++i<f;){var d=A(r[i]),u=t;if(d==="__proto__"||d==="constructor"||d==="prototype")return n;if(i!=a){var h=s[d];u=void 0,u===void 0&&(u=g(h)?h:B(r[i+1])?[]:{})}T(s,d,u),s=s[d]}return n}function on(n,r,t){for(var e=-1,i=r.length,f={};++e<i;){var a=r[e],s=N(n,a);t(s,a)&&an(f,v(a,n),s)}return f}export{rn as a,tn as b,V as c,on as d,mn as e,fn as f,hn as g,bn as h,dn as i,D as j,un as l,gn as m,Y as t};

View File

@@ -1 +1 @@
import{_ as l}from"./mermaid-vendor-C4V_MkUy.js";function m(e,c){var i,t,o;e.accDescr&&((i=c.setAccDescription)==null||i.call(c,e.accDescr)),e.accTitle&&((t=c.setAccTitle)==null||t.call(c,e.accTitle)),e.title&&((o=c.setDiagramTitle)==null||o.call(c,e.title))}l(m,"populateCommonDb");export{m as p};
import{_ as l}from"./mermaid-vendor-GB05DkYd.js";function m(e,c){var i,t,o;e.accDescr&&((i=c.setAccDescription)==null||i.call(c,e.accDescr)),e.accTitle&&((t=c.setAccTitle)==null||t.call(c,e.accTitle)),e.title&&((o=c.setDiagramTitle)==null||o.call(c,e.title))}l(m,"populateCommonDb");export{m as p};

View File

@@ -1 +1 @@
import{_ as n,a2 as x,j as l}from"./mermaid-vendor-C4V_MkUy.js";var c=n((a,t)=>{const e=a.append("rect");if(e.attr("x",t.x),e.attr("y",t.y),e.attr("fill",t.fill),e.attr("stroke",t.stroke),e.attr("width",t.width),e.attr("height",t.height),t.name&&e.attr("name",t.name),t.rx&&e.attr("rx",t.rx),t.ry&&e.attr("ry",t.ry),t.attrs!==void 0)for(const r in t.attrs)e.attr(r,t.attrs[r]);return t.class&&e.attr("class",t.class),e},"drawRect"),d=n((a,t)=>{const e={x:t.startx,y:t.starty,width:t.stopx-t.startx,height:t.stopy-t.starty,fill:t.fill,stroke:t.stroke,class:"rect"};c(a,e).lower()},"drawBackgroundRect"),g=n((a,t)=>{const e=t.text.replace(x," "),r=a.append("text");r.attr("x",t.x),r.attr("y",t.y),r.attr("class","legend"),r.style("text-anchor",t.anchor),t.class&&r.attr("class",t.class);const s=r.append("tspan");return s.attr("x",t.x+t.textMargin*2),s.text(e),r},"drawText"),h=n((a,t,e,r)=>{const s=a.append("image");s.attr("x",t),s.attr("y",e);const i=l.sanitizeUrl(r);s.attr("xlink:href",i)},"drawImage"),m=n((a,t,e,r)=>{const s=a.append("use");s.attr("x",t),s.attr("y",e);const i=l.sanitizeUrl(r);s.attr("xlink:href",`#${i}`)},"drawEmbeddedImage"),y=n(()=>({x:0,y:0,width:100,height:100,fill:"#EDF2AE",stroke:"#666",anchor:"start",rx:0,ry:0}),"getNoteRect"),p=n(()=>({x:0,y:0,width:100,height:100,"text-anchor":"start",style:"#666",textMargin:0,rx:0,ry:0,tspan:!0}),"getTextObj");export{d as a,p as b,m as c,c as d,h as e,g as f,y as g};
import{_ as n,a2 as x,j as l}from"./mermaid-vendor-GB05DkYd.js";var c=n((a,t)=>{const e=a.append("rect");if(e.attr("x",t.x),e.attr("y",t.y),e.attr("fill",t.fill),e.attr("stroke",t.stroke),e.attr("width",t.width),e.attr("height",t.height),t.name&&e.attr("name",t.name),t.rx&&e.attr("rx",t.rx),t.ry&&e.attr("ry",t.ry),t.attrs!==void 0)for(const r in t.attrs)e.attr(r,t.attrs[r]);return t.class&&e.attr("class",t.class),e},"drawRect"),d=n((a,t)=>{const e={x:t.startx,y:t.starty,width:t.stopx-t.startx,height:t.stopy-t.starty,fill:t.fill,stroke:t.stroke,class:"rect"};c(a,e).lower()},"drawBackgroundRect"),g=n((a,t)=>{const e=t.text.replace(x," "),r=a.append("text");r.attr("x",t.x),r.attr("y",t.y),r.attr("class","legend"),r.style("text-anchor",t.anchor),t.class&&r.attr("class",t.class);const s=r.append("tspan");return s.attr("x",t.x+t.textMargin*2),s.text(e),r},"drawText"),h=n((a,t,e,r)=>{const s=a.append("image");s.attr("x",t),s.attr("y",e);const i=l.sanitizeUrl(r);s.attr("xlink:href",i)},"drawImage"),m=n((a,t,e,r)=>{const s=a.append("use");s.attr("x",t),s.attr("y",e);const i=l.sanitizeUrl(r);s.attr("xlink:href",`#${i}`)},"drawEmbeddedImage"),y=n(()=>({x:0,y:0,width:100,height:100,fill:"#EDF2AE",stroke:"#666",anchor:"start",rx:0,ry:0}),"getNoteRect"),p=n(()=>({x:0,y:0,width:100,height:100,"text-anchor":"start",style:"#666",textMargin:0,rx:0,ry:0,tspan:!0}),"getTextObj");export{d as a,p as b,m as c,c as d,h as e,g as f,y as g};

View File

@@ -1 +1 @@
import{_ as s}from"./mermaid-vendor-C4V_MkUy.js";var t,e=(t=class{constructor(i){this.init=i,this.records=this.init()}reset(){this.records=this.init()}},s(t,"ImperativeState"),t);export{e as I};
import{_ as s}from"./mermaid-vendor-GB05DkYd.js";var t,e=(t=class{constructor(i){this.init=i,this.records=this.init()}reset(){this.records=this.init()}},s(t,"ImperativeState"),t);export{e as I};

View File

@@ -1 +1 @@
import{_ as a,d as o}from"./mermaid-vendor-C4V_MkUy.js";var d=a((t,e)=>{let n;return e==="sandbox"&&(n=o("#i"+t)),(e==="sandbox"?o(n.nodes()[0].contentDocument.body):o("body")).select(`[id="${t}"]`)},"getDiagramElement");export{d as g};
import{_ as a,d as o}from"./mermaid-vendor-GB05DkYd.js";var d=a((t,e)=>{let n;return e==="sandbox"&&(n=o("#i"+t)),(e==="sandbox"?o(n.nodes()[0].contentDocument.body):o("body")).select(`[id="${t}"]`)},"getDiagramElement");export{d as g};

View File

@@ -1,4 +1,4 @@
import{_ as e}from"./mermaid-vendor-C4V_MkUy.js";var l=e(()=>`
import{_ as e}from"./mermaid-vendor-GB05DkYd.js";var l=e(()=>`
/* Font Awesome icon styling - consolidated */
.label-icon {
display: inline-block;

View File

@@ -1 +1 @@
import{_ as a,e as w,l as x}from"./mermaid-vendor-C4V_MkUy.js";var d=a((e,t,i,o)=>{e.attr("class",i);const{width:r,height:h,x:n,y:c}=u(e,t);w(e,h,r,o);const s=l(n,c,r,h,t);e.attr("viewBox",s),x.debug(`viewBox configured: ${s} with padding: ${t}`)},"setupViewPortForSVG"),u=a((e,t)=>{var o;const i=((o=e.node())==null?void 0:o.getBBox())||{width:0,height:0,x:0,y:0};return{width:i.width+t*2,height:i.height+t*2,x:i.x,y:i.y}},"calculateDimensionsWithPadding"),l=a((e,t,i,o,r)=>`${e-r} ${t-r} ${i} ${o}`,"createViewBox");export{d as s};
import{_ as a,e as w,l as x}from"./mermaid-vendor-GB05DkYd.js";var d=a((e,t,i,o)=>{e.attr("class",i);const{width:r,height:h,x:n,y:c}=u(e,t);w(e,h,r,o);const s=l(n,c,r,h,t);e.attr("viewBox",s),x.debug(`viewBox configured: ${s} with padding: ${t}`)},"setupViewPortForSVG"),u=a((e,t)=>{var o;const i=((o=e.node())==null?void 0:o.getBBox())||{width:0,height:0,x:0,y:0};return{width:i.width+t*2,height:i.height+t*2,x:i.x,y:i.y}},"calculateDimensionsWithPadding"),l=a((e,t,i,o,r)=>`${e-r} ${t-r} ${i} ${o}`,"createViewBox");export{d as s};

View File

@@ -0,0 +1 @@
import{s as a,c as s,a as e,C as t}from"./chunk-SZ463SBG-HfqGkezl.js";import{_ as i}from"./mermaid-vendor-GB05DkYd.js";import"./chunk-E2GYISFI-Cixkpli4.js";import"./chunk-BFAMUDN2-ghvP-Rq6.js";import"./chunk-SKB7J2MH-gQmYvnvi.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var c={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{c as diagram};

View File

@@ -1 +0,0 @@
import{s as a,c as s,a as e,C as t}from"./chunk-SZ463SBG-B_R_Pg-v.js";import{_ as i}from"./mermaid-vendor-C4V_MkUy.js";import"./chunk-E2GYISFI-_KKYlGsz.js";import"./chunk-BFAMUDN2-lYQpQICr.js";import"./chunk-SKB7J2MH-JBIfIwyf.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var c={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{c as diagram};

View File

@@ -0,0 +1 @@
import{s as a,c as s,a as e,C as t}from"./chunk-SZ463SBG-HfqGkezl.js";import{_ as i}from"./mermaid-vendor-GB05DkYd.js";import"./chunk-E2GYISFI-Cixkpli4.js";import"./chunk-BFAMUDN2-ghvP-Rq6.js";import"./chunk-SKB7J2MH-gQmYvnvi.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var c={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{c as diagram};

View File

@@ -1 +0,0 @@
import{s as a,c as s,a as e,C as t}from"./chunk-SZ463SBG-B_R_Pg-v.js";import{_ as i}from"./mermaid-vendor-C4V_MkUy.js";import"./chunk-E2GYISFI-_KKYlGsz.js";import"./chunk-BFAMUDN2-lYQpQICr.js";import"./chunk-SKB7J2MH-JBIfIwyf.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var c={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{c as diagram};

View File

@@ -0,0 +1 @@
import{b as r}from"./_baseUniq-DUOGdItU.js";var e=4;function a(o){return r(o,e)}export{a as c};

View File

@@ -1 +0,0 @@
import{b as r}from"./_baseUniq-CZTq81C3.js";var e=4;function a(o){return r(o,e)}export{a as c};

View File

@@ -1,4 +1,4 @@
import{p as y}from"./chunk-353BL4L5-BgtJsm81.js";import{_ as l,s as B,g as S,t as z,q as F,a as P,b as E,F as v,K as W,e as T,z as D,G as _,H as A,l as w}from"./mermaid-vendor-C4V_MkUy.js";import{p as N}from"./treemap-75Q7IDZK-Bh7sugQT.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";import"./_baseUniq-CZTq81C3.js";import"./_basePickBy-Z1bijFVM.js";import"./clone-Dx_4EPXr.js";var x={packet:[]},m=structuredClone(x),L=A.packet,Y=l(()=>{const t=v({...L,..._().packet});return t.showBits&&(t.paddingY+=10),t},"getConfig"),G=l(()=>m.packet,"getPacket"),H=l(t=>{t.length>0&&m.packet.push(t)},"pushWord"),I=l(()=>{D(),m=structuredClone(x)},"clear"),u={pushWord:H,getPacket:G,getConfig:Y,clear:I,setAccTitle:E,getAccTitle:P,setDiagramTitle:F,getDiagramTitle:z,getAccDescription:S,setAccDescription:B},K=1e4,M=l(t=>{y(t,u);let e=-1,o=[],n=1;const{bitsPerRow:i}=u.getConfig();for(let{start:a,end:r,bits:c,label:f}of t.blocks){if(a!==void 0&&r!==void 0&&r<a)throw new Error(`Packet block ${a} - ${r} is invalid. End must be greater than start.`);if(a??(a=e+1),a!==e+1)throw new Error(`Packet block ${a} - ${r??a} is not contiguous. It should start from ${e+1}.`);if(c===0)throw new Error(`Packet block ${a} is invalid. Cannot have a zero bit field.`);for(r??(r=a+(c??1)-1),c??(c=r-a+1),e=r,w.debug(`Packet block ${a} - ${e} with label ${f}`);o.length<=i+1&&u.getPacket().length<K;){const[d,p]=O({start:a,end:r,bits:c,label:f},n,i);if(o.push(d),d.end+1===n*i&&(u.pushWord(o),o=[],n++),!p)break;({start:a,end:r,bits:c,label:f}=p)}}u.pushWord(o)},"populate"),O=l((t,e,o)=>{if(t.start===void 0)throw new Error("start should have been set during first phase");if(t.end===void 0)throw new Error("end should have been set during first phase");if(t.start>t.end)throw new Error(`Block start ${t.start} is greater than block end ${t.end}.`);if(t.end+1<=e*o)return[t,void 0];const n=e*o-1,i=e*o;return[{start:t.start,end:n,label:t.label,bits:n-t.start},{start:i,end:t.end,label:t.label,bits:t.end-i}]},"getNextFittingBlock"),q={parse:l(async t=>{const e=await N("packet",t);w.debug(e),M(e)},"parse")},R=l((t,e,o,n)=>{const i=n.db,a=i.getConfig(),{rowHeight:r,paddingY:c,bitWidth:f,bitsPerRow:d}=a,p=i.getPacket(),s=i.getDiagramTitle(),k=r+c,g=k*(p.length+1)-(s?0:r),b=f*d+2,h=W(e);h.attr("viewbox",`0 0 ${b} ${g}`),T(h,g,b,a.useMaxWidth);for(const[C,$]of p.entries())U(h,$,C,a);h.append("text").text(s).attr("x",b/2).attr("y",g-k/2).attr("dominant-baseline","middle").attr("text-anchor","middle").attr("class","packetTitle")},"draw"),U=l((t,e,o,{rowHeight:n,paddingX:i,paddingY:a,bitWidth:r,bitsPerRow:c,showBits:f})=>{const d=t.append("g"),p=o*(n+a)+a;for(const s of e){const k=s.start%c*r+1,g=(s.end-s.start+1)*r-i;if(d.append("rect").attr("x",k).attr("y",p).attr("width",g).attr("height",n).attr("class","packetBlock"),d.append("text").attr("x",k+g/2).attr("y",p+n/2).attr("class","packetLabel").attr("dominant-baseline","middle").attr("text-anchor","middle").text(s.label),!f)continue;const b=s.end===s.start,h=p-2;d.append("text").attr("x",k+(b?g/2:0)).attr("y",h).attr("class","packetByte start").attr("dominant-baseline","auto").attr("text-anchor",b?"middle":"start").text(s.start),b||d.append("text").attr("x",k+g).attr("y",h).attr("class","packetByte end").attr("dominant-baseline","auto").attr("text-anchor","end").text(s.end)}},"drawWord"),X={draw:R},j={byteFontSize:"10px",startByteColor:"black",endByteColor:"black",labelColor:"black",labelFontSize:"12px",titleColor:"black",titleFontSize:"14px",blockStrokeColor:"black",blockStrokeWidth:"1",blockFillColor:"#efefef"},J=l(({packet:t}={})=>{const e=v(j,t);return`
import{p as y}from"./chunk-353BL4L5-BdESKFSH.js";import{_ as l,s as B,g as S,t as z,q as F,a as P,b as E,F as v,K as W,e as T,z as D,G as _,H as A,l as w}from"./mermaid-vendor-GB05DkYd.js";import{p as N}from"./treemap-75Q7IDZK-C9xJN-2g.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";import"./_baseUniq-DUOGdItU.js";import"./_basePickBy-V-PVS_is.js";import"./clone-CyTo8HmA.js";var x={packet:[]},m=structuredClone(x),L=A.packet,Y=l(()=>{const t=v({...L,..._().packet});return t.showBits&&(t.paddingY+=10),t},"getConfig"),G=l(()=>m.packet,"getPacket"),H=l(t=>{t.length>0&&m.packet.push(t)},"pushWord"),I=l(()=>{D(),m=structuredClone(x)},"clear"),u={pushWord:H,getPacket:G,getConfig:Y,clear:I,setAccTitle:E,getAccTitle:P,setDiagramTitle:F,getDiagramTitle:z,getAccDescription:S,setAccDescription:B},K=1e4,M=l(t=>{y(t,u);let e=-1,o=[],n=1;const{bitsPerRow:i}=u.getConfig();for(let{start:a,end:r,bits:c,label:f}of t.blocks){if(a!==void 0&&r!==void 0&&r<a)throw new Error(`Packet block ${a} - ${r} is invalid. End must be greater than start.`);if(a??(a=e+1),a!==e+1)throw new Error(`Packet block ${a} - ${r??a} is not contiguous. It should start from ${e+1}.`);if(c===0)throw new Error(`Packet block ${a} is invalid. Cannot have a zero bit field.`);for(r??(r=a+(c??1)-1),c??(c=r-a+1),e=r,w.debug(`Packet block ${a} - ${e} with label ${f}`);o.length<=i+1&&u.getPacket().length<K;){const[d,p]=O({start:a,end:r,bits:c,label:f},n,i);if(o.push(d),d.end+1===n*i&&(u.pushWord(o),o=[],n++),!p)break;({start:a,end:r,bits:c,label:f}=p)}}u.pushWord(o)},"populate"),O=l((t,e,o)=>{if(t.start===void 0)throw new Error("start should have been set during first phase");if(t.end===void 0)throw new Error("end should have been set during first phase");if(t.start>t.end)throw new Error(`Block start ${t.start} is greater than block end ${t.end}.`);if(t.end+1<=e*o)return[t,void 0];const n=e*o-1,i=e*o;return[{start:t.start,end:n,label:t.label,bits:n-t.start},{start:i,end:t.end,label:t.label,bits:t.end-i}]},"getNextFittingBlock"),q={parse:l(async t=>{const e=await N("packet",t);w.debug(e),M(e)},"parse")},R=l((t,e,o,n)=>{const i=n.db,a=i.getConfig(),{rowHeight:r,paddingY:c,bitWidth:f,bitsPerRow:d}=a,p=i.getPacket(),s=i.getDiagramTitle(),k=r+c,g=k*(p.length+1)-(s?0:r),b=f*d+2,h=W(e);h.attr("viewbox",`0 0 ${b} ${g}`),T(h,g,b,a.useMaxWidth);for(const[C,$]of p.entries())U(h,$,C,a);h.append("text").text(s).attr("x",b/2).attr("y",g-k/2).attr("dominant-baseline","middle").attr("text-anchor","middle").attr("class","packetTitle")},"draw"),U=l((t,e,o,{rowHeight:n,paddingX:i,paddingY:a,bitWidth:r,bitsPerRow:c,showBits:f})=>{const d=t.append("g"),p=o*(n+a)+a;for(const s of e){const k=s.start%c*r+1,g=(s.end-s.start+1)*r-i;if(d.append("rect").attr("x",k).attr("y",p).attr("width",g).attr("height",n).attr("class","packetBlock"),d.append("text").attr("x",k+g/2).attr("y",p+n/2).attr("class","packetLabel").attr("dominant-baseline","middle").attr("text-anchor","middle").text(s.label),!f)continue;const b=s.end===s.start,h=p-2;d.append("text").attr("x",k+(b?g/2:0)).attr("y",h).attr("class","packetByte start").attr("dominant-baseline","auto").attr("text-anchor",b?"middle":"start").text(s.start),b||d.append("text").attr("x",k+g).attr("y",h).attr("class","packetByte end").attr("dominant-baseline","auto").attr("text-anchor","end").text(s.end)}},"drawWord"),X={draw:R},j={byteFontSize:"10px",startByteColor:"black",endByteColor:"black",labelColor:"black",labelFontSize:"12px",titleColor:"black",titleFontSize:"14px",blockStrokeColor:"black",blockStrokeWidth:"1",blockFillColor:"#efefef"},J=l(({packet:t}={})=>{const e=v(j,t);return`
.packetByte {
font-size: ${e.byteFontSize};
}

View File

@@ -1,4 +1,4 @@
import{g as q1}from"./chunk-E2GYISFI-_KKYlGsz.js";import{_ as m,o as O1,l as ee,c as be,d as Se,p as H1,r as X1,u as i1,b as Q1,s as J1,q as Z1,a as $1,g as et,t as tt,k as st,v as it,J as rt,x as nt,y as s1,z as at,A as ut,B as lt,C as ot}from"./mermaid-vendor-C4V_MkUy.js";import{g as ct}from"./chunk-BFAMUDN2-lYQpQICr.js";import{s as ht}from"./chunk-SKB7J2MH-JBIfIwyf.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var dt="flowchart-",Pe,pt=(Pe=class{constructor(){this.vertexCounter=0,this.config=be(),this.vertices=new Map,this.edges=[],this.classes=new Map,this.subGraphs=[],this.subGraphLookup=new Map,this.tooltips=new Map,this.subCount=0,this.firstGraphFlag=!0,this.secCount=-1,this.posCrossRef=[],this.funs=[],this.setAccTitle=Q1,this.setAccDescription=J1,this.setDiagramTitle=Z1,this.getAccTitle=$1,this.getAccDescription=et,this.getDiagramTitle=tt,this.funs.push(this.setupToolTips.bind(this)),this.addVertex=this.addVertex.bind(this),this.firstGraph=this.firstGraph.bind(this),this.setDirection=this.setDirection.bind(this),this.addSubGraph=this.addSubGraph.bind(this),this.addLink=this.addLink.bind(this),this.setLink=this.setLink.bind(this),this.updateLink=this.updateLink.bind(this),this.addClass=this.addClass.bind(this),this.setClass=this.setClass.bind(this),this.destructLink=this.destructLink.bind(this),this.setClickEvent=this.setClickEvent.bind(this),this.setTooltip=this.setTooltip.bind(this),this.updateLinkInterpolate=this.updateLinkInterpolate.bind(this),this.setClickFun=this.setClickFun.bind(this),this.bindFunctions=this.bindFunctions.bind(this),this.lex={firstGraph:this.firstGraph.bind(this)},this.clear(),this.setGen("gen-2")}sanitizeText(i){return st.sanitizeText(i,this.config)}lookUpDomId(i){for(const n of this.vertices.values())if(n.id===i)return n.domId;return i}addVertex(i,n,a,u,l,f,c={},A){var V,C;if(!i||i.trim().length===0)return;let r;if(A!==void 0){let p;A.includes(`
import{g as q1}from"./chunk-E2GYISFI-Cixkpli4.js";import{_ as m,o as O1,l as ee,c as be,d as Se,p as H1,r as X1,u as i1,b as Q1,s as J1,q as Z1,a as $1,g as et,t as tt,k as st,v as it,J as rt,x as nt,y as s1,z as at,A as ut,B as lt,C as ot}from"./mermaid-vendor-GB05DkYd.js";import{g as ct}from"./chunk-BFAMUDN2-ghvP-Rq6.js";import{s as ht}from"./chunk-SKB7J2MH-gQmYvnvi.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var dt="flowchart-",Pe,pt=(Pe=class{constructor(){this.vertexCounter=0,this.config=be(),this.vertices=new Map,this.edges=[],this.classes=new Map,this.subGraphs=[],this.subGraphLookup=new Map,this.tooltips=new Map,this.subCount=0,this.firstGraphFlag=!0,this.secCount=-1,this.posCrossRef=[],this.funs=[],this.setAccTitle=Q1,this.setAccDescription=J1,this.setDiagramTitle=Z1,this.getAccTitle=$1,this.getAccDescription=et,this.getDiagramTitle=tt,this.funs.push(this.setupToolTips.bind(this)),this.addVertex=this.addVertex.bind(this),this.firstGraph=this.firstGraph.bind(this),this.setDirection=this.setDirection.bind(this),this.addSubGraph=this.addSubGraph.bind(this),this.addLink=this.addLink.bind(this),this.setLink=this.setLink.bind(this),this.updateLink=this.updateLink.bind(this),this.addClass=this.addClass.bind(this),this.setClass=this.setClass.bind(this),this.destructLink=this.destructLink.bind(this),this.setClickEvent=this.setClickEvent.bind(this),this.setTooltip=this.setTooltip.bind(this),this.updateLinkInterpolate=this.updateLinkInterpolate.bind(this),this.setClickFun=this.setClickFun.bind(this),this.bindFunctions=this.bindFunctions.bind(this),this.lex={firstGraph:this.firstGraph.bind(this)},this.clear(),this.setGen("gen-2")}sanitizeText(i){return st.sanitizeText(i,this.config)}lookUpDomId(i){for(const n of this.vertices.values())if(n.id===i)return n.domId;return i}addVertex(i,n,a,u,l,f,c={},A){var V,C;if(!i||i.trim().length===0)return;let r;if(A!==void 0){let p;A.includes(`
`)?p=A+`
`:p=`{
`+A+`

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
import{_ as e,l as o,K as i,e as n,L as p}from"./mermaid-vendor-C4V_MkUy.js";import{p as m}from"./treemap-75Q7IDZK-Bh7sugQT.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";import"./_baseUniq-CZTq81C3.js";import"./_basePickBy-Z1bijFVM.js";import"./clone-Dx_4EPXr.js";var g={parse:e(async r=>{const a=await m("info",r);o.debug(a)},"parse")},v={version:p.version+""},d=e(()=>v.version,"getVersion"),c={getVersion:d},l=e((r,a,s)=>{o.debug(`rendering info diagram
import{_ as e,l as o,K as i,e as n,L as p}from"./mermaid-vendor-GB05DkYd.js";import{p as m}from"./treemap-75Q7IDZK-C9xJN-2g.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";import"./_baseUniq-DUOGdItU.js";import"./_basePickBy-V-PVS_is.js";import"./clone-CyTo8HmA.js";var g={parse:e(async r=>{const a=await m("info",r);o.debug(a)},"parse")},v={version:p.version+""},d=e(()=>v.version,"getVersion"),c={getVersion:d},l=e((r,a,s)=>{o.debug(`rendering info diagram
`+r);const t=i(a);n(t,100,400,!0),t.append("g").append("text").attr("x",100).attr("y",40).attr("class","version").attr("font-size",32).style("text-anchor","middle").text(`v${s}`)},"draw"),f={draw:l},L={parser:g,db:c,renderer:f};export{L as diagram};

View File

@@ -1,4 +1,4 @@
import{a as gt,g as lt,f as mt,d as xt}from"./chunk-67H74DCK-jM39k9TN.js";import{g as kt}from"./chunk-E2GYISFI-_KKYlGsz.js";import{_ as r,g as _t,s as bt,a as vt,b as wt,t as Tt,q as St,c as R,d as G,e as $t,z as Mt,N as et}from"./mermaid-vendor-C4V_MkUy.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var U=function(){var t=r(function(h,n,a,l){for(a=a||{},l=h.length;l--;a[h[l]]=n);return a},"o"),e=[6,8,10,11,12,14,16,17,18],s=[1,9],c=[1,10],i=[1,11],f=[1,12],u=[1,13],y=[1,14],g={trace:r(function(){},"trace"),yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,taskName:18,taskData:19,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",18:"taskName",19:"taskData"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,2]],performAction:r(function(n,a,l,d,p,o,v){var k=o.length-1;switch(p){case 1:return o[k-1];case 2:this.$=[];break;case 3:o[k-1].push(o[k]),this.$=o[k-1];break;case 4:case 5:this.$=o[k];break;case 6:case 7:this.$=[];break;case 8:d.setDiagramTitle(o[k].substr(6)),this.$=o[k].substr(6);break;case 9:this.$=o[k].trim(),d.setAccTitle(this.$);break;case 10:case 11:this.$=o[k].trim(),d.setAccDescription(this.$);break;case 12:d.addSection(o[k].substr(8)),this.$=o[k].substr(8);break;case 13:d.addTask(o[k-1],o[k]),this.$="task";break}},"anonymous"),table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:s,12:c,14:i,16:f,17:u,18:y},t(e,[2,7],{1:[2,1]}),t(e,[2,3]),{9:15,11:s,12:c,14:i,16:f,17:u,18:y},t(e,[2,5]),t(e,[2,6]),t(e,[2,8]),{13:[1,16]},{15:[1,17]},t(e,[2,11]),t(e,[2,12]),{19:[1,18]},t(e,[2,4]),t(e,[2,9]),t(e,[2,10]),t(e,[2,13])],defaultActions:{},parseError:r(function(n,a){if(a.recoverable)this.trace(n);else{var l=new Error(n);throw l.hash=a,l}},"parseError"),parse:r(function(n){var a=this,l=[0],d=[],p=[null],o=[],v=this.table,k="",C=0,K=0,dt=2,Q=1,yt=o.slice.call(arguments,1),_=Object.create(this.lexer),I={yy:{}};for(var O in this.yy)Object.prototype.hasOwnProperty.call(this.yy,O)&&(I.yy[O]=this.yy[O]);_.setInput(n,I.yy),I.yy.lexer=_,I.yy.parser=this,typeof _.yylloc>"u"&&(_.yylloc={});var Y=_.yylloc;o.push(Y);var ft=_.options&&_.options.ranges;typeof I.yy.parseError=="function"?this.parseError=I.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function pt(w){l.length=l.length-2*w,p.length=p.length-w,o.length=o.length-w}r(pt,"popStack");function D(){var w;return w=d.pop()||_.lex()||Q,typeof w!="number"&&(w instanceof Array&&(d=w,w=d.pop()),w=a.symbols_[w]||w),w}r(D,"lex");for(var b,A,T,q,F={},N,M,tt,z;;){if(A=l[l.length-1],this.defaultActions[A]?T=this.defaultActions[A]:((b===null||typeof b>"u")&&(b=D()),T=v[A]&&v[A][b]),typeof T>"u"||!T.length||!T[0]){var X="";z=[];for(N in v[A])this.terminals_[N]&&N>dt&&z.push("'"+this.terminals_[N]+"'");_.showPosition?X="Parse error on line "+(C+1)+`:
import{a as gt,g as lt,f as mt,d as xt}from"./chunk-67H74DCK-C_VoI5m8.js";import{g as kt}from"./chunk-E2GYISFI-Cixkpli4.js";import{_ as r,g as _t,s as bt,a as vt,b as wt,t as Tt,q as St,c as R,d as G,e as $t,z as Mt,N as et}from"./mermaid-vendor-GB05DkYd.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var U=function(){var t=r(function(h,n,a,l){for(a=a||{},l=h.length;l--;a[h[l]]=n);return a},"o"),e=[6,8,10,11,12,14,16,17,18],s=[1,9],c=[1,10],i=[1,11],f=[1,12],u=[1,13],y=[1,14],g={trace:r(function(){},"trace"),yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,taskName:18,taskData:19,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",18:"taskName",19:"taskData"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,2]],performAction:r(function(n,a,l,d,p,o,v){var k=o.length-1;switch(p){case 1:return o[k-1];case 2:this.$=[];break;case 3:o[k-1].push(o[k]),this.$=o[k-1];break;case 4:case 5:this.$=o[k];break;case 6:case 7:this.$=[];break;case 8:d.setDiagramTitle(o[k].substr(6)),this.$=o[k].substr(6);break;case 9:this.$=o[k].trim(),d.setAccTitle(this.$);break;case 10:case 11:this.$=o[k].trim(),d.setAccDescription(this.$);break;case 12:d.addSection(o[k].substr(8)),this.$=o[k].substr(8);break;case 13:d.addTask(o[k-1],o[k]),this.$="task";break}},"anonymous"),table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:s,12:c,14:i,16:f,17:u,18:y},t(e,[2,7],{1:[2,1]}),t(e,[2,3]),{9:15,11:s,12:c,14:i,16:f,17:u,18:y},t(e,[2,5]),t(e,[2,6]),t(e,[2,8]),{13:[1,16]},{15:[1,17]},t(e,[2,11]),t(e,[2,12]),{19:[1,18]},t(e,[2,4]),t(e,[2,9]),t(e,[2,10]),t(e,[2,13])],defaultActions:{},parseError:r(function(n,a){if(a.recoverable)this.trace(n);else{var l=new Error(n);throw l.hash=a,l}},"parseError"),parse:r(function(n){var a=this,l=[0],d=[],p=[null],o=[],v=this.table,k="",C=0,K=0,dt=2,Q=1,yt=o.slice.call(arguments,1),_=Object.create(this.lexer),I={yy:{}};for(var O in this.yy)Object.prototype.hasOwnProperty.call(this.yy,O)&&(I.yy[O]=this.yy[O]);_.setInput(n,I.yy),I.yy.lexer=_,I.yy.parser=this,typeof _.yylloc>"u"&&(_.yylloc={});var Y=_.yylloc;o.push(Y);var ft=_.options&&_.options.ranges;typeof I.yy.parseError=="function"?this.parseError=I.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function pt(w){l.length=l.length-2*w,p.length=p.length-w,o.length=o.length-w}r(pt,"popStack");function D(){var w;return w=d.pop()||_.lex()||Q,typeof w!="number"&&(w instanceof Array&&(d=w,w=d.pop()),w=a.symbols_[w]||w),w}r(D,"lex");for(var b,A,T,q,F={},N,M,tt,z;;){if(A=l[l.length-1],this.defaultActions[A]?T=this.defaultActions[A]:((b===null||typeof b>"u")&&(b=D()),T=v[A]&&v[A][b]),typeof T>"u"||!T.length||!T[0]){var X="";z=[];for(N in v[A])this.terminals_[N]&&N>dt&&z.push("'"+this.terminals_[N]+"'");_.showPosition?X="Parse error on line "+(C+1)+`:
`+_.showPosition()+`
Expecting `+z.join(", ")+", got '"+(this.terminals_[b]||b)+"'":X="Parse error on line "+(C+1)+": Unexpected "+(b==Q?"end of input":"'"+(this.terminals_[b]||b)+"'"),this.parseError(X,{text:_.match,token:this.terminals_[b]||b,line:_.yylineno,loc:Y,expected:z})}if(T[0]instanceof Array&&T.length>1)throw new Error("Parse Error: multiple actions possible at state: "+A+", token: "+b);switch(T[0]){case 1:l.push(b),p.push(_.yytext),o.push(_.yylloc),l.push(T[1]),b=null,K=_.yyleng,k=_.yytext,C=_.yylineno,Y=_.yylloc;break;case 2:if(M=this.productions_[T[1]][1],F.$=p[p.length-M],F._$={first_line:o[o.length-(M||1)].first_line,last_line:o[o.length-1].last_line,first_column:o[o.length-(M||1)].first_column,last_column:o[o.length-1].last_column},ft&&(F._$.range=[o[o.length-(M||1)].range[0],o[o.length-1].range[1]]),q=this.performAction.apply(F,[k,K,C,I.yy,T[1],p,o].concat(yt)),typeof q<"u")return q;M&&(l=l.slice(0,-1*M*2),p=p.slice(0,-1*M),o=o.slice(0,-1*M)),l.push(this.productions_[T[1]][0]),p.push(F.$),o.push(F._$),tt=v[l[l.length-2]][l[l.length-1]],l.push(tt);break;case 3:return!0}}return!0},"parse")},m=function(){var h={EOF:1,parseError:r(function(a,l){if(this.yy.parser)this.yy.parser.parseError(a,l);else throw new Error(a)},"parseError"),setInput:r(function(n,a){return this.yy=a||this.yy||{},this._input=n,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:r(function(){var n=this._input[0];this.yytext+=n,this.yyleng++,this.offset++,this.match+=n,this.matched+=n;var a=n.match(/(?:\r\n?|\n).*/g);return a?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),n},"input"),unput:r(function(n){var a=n.length,l=n.split(/(?:\r\n?|\n)/g);this._input=n+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-a),this.offset-=a;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),l.length-1&&(this.yylineno-=l.length-1);var p=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:l?(l.length===d.length?this.yylloc.first_column:0)+d[d.length-l.length].length-l[0].length:this.yylloc.first_column-a},this.options.ranges&&(this.yylloc.range=[p[0],p[0]+this.yyleng-a]),this.yyleng=this.yytext.length,this},"unput"),more:r(function(){return this._more=!0,this},"more"),reject:r(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:r(function(n){this.unput(this.match.slice(n))},"less"),pastInput:r(function(){var n=this.matched.substr(0,this.matched.length-this.match.length);return(n.length>20?"...":"")+n.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:r(function(){var n=this.match;return n.length<20&&(n+=this._input.substr(0,20-n.length)),(n.substr(0,20)+(n.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:r(function(){var n=this.pastInput(),a=new Array(n.length+1).join("-");return n+this.upcomingInput()+`

View File

@@ -1,4 +1,4 @@
import{g as fe}from"./chunk-E2GYISFI-_KKYlGsz.js";import{_ as c,l as te,c as W,K as ye,a8 as be,a9 as me,aa as _e,a3 as Ee,H as Y,i as G,v as ke,J as Se,a4 as Ne,a5 as le,a6 as ce}from"./mermaid-vendor-C4V_MkUy.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var $=function(){var t=c(function(_,s,n,a){for(n=n||{},a=_.length;a--;n[_[a]]=s);return n},"o"),g=[1,4],d=[1,13],r=[1,12],p=[1,15],E=[1,16],f=[1,20],h=[1,19],L=[6,7,8],C=[1,26],w=[1,24],N=[1,25],i=[6,7,11],H=[1,31],x=[6,7,11,24],P=[1,6,13,16,17,20,23],M=[1,35],U=[1,36],A=[1,6,7,11,13,16,17,20,23],j=[1,38],V={trace:c(function(){},"trace"),yy:{},symbols_:{error:2,start:3,mindMap:4,spaceLines:5,SPACELINE:6,NL:7,KANBAN:8,document:9,stop:10,EOF:11,statement:12,SPACELIST:13,node:14,shapeData:15,ICON:16,CLASS:17,nodeWithId:18,nodeWithoutId:19,NODE_DSTART:20,NODE_DESCR:21,NODE_DEND:22,NODE_ID:23,SHAPE_DATA:24,$accept:0,$end:1},terminals_:{2:"error",6:"SPACELINE",7:"NL",8:"KANBAN",11:"EOF",13:"SPACELIST",16:"ICON",17:"CLASS",20:"NODE_DSTART",21:"NODE_DESCR",22:"NODE_DEND",23:"NODE_ID",24:"SHAPE_DATA"},productions_:[0,[3,1],[3,2],[5,1],[5,2],[5,2],[4,2],[4,3],[10,1],[10,1],[10,1],[10,2],[10,2],[9,3],[9,2],[12,3],[12,2],[12,2],[12,2],[12,1],[12,2],[12,1],[12,1],[12,1],[12,1],[14,1],[14,1],[19,3],[18,1],[18,4],[15,2],[15,1]],performAction:c(function(s,n,a,o,u,e,B){var l=e.length-1;switch(u){case 6:case 7:return o;case 8:o.getLogger().trace("Stop NL ");break;case 9:o.getLogger().trace("Stop EOF ");break;case 11:o.getLogger().trace("Stop NL2 ");break;case 12:o.getLogger().trace("Stop EOF2 ");break;case 15:o.getLogger().info("Node: ",e[l-1].id),o.addNode(e[l-2].length,e[l-1].id,e[l-1].descr,e[l-1].type,e[l]);break;case 16:o.getLogger().info("Node: ",e[l].id),o.addNode(e[l-1].length,e[l].id,e[l].descr,e[l].type);break;case 17:o.getLogger().trace("Icon: ",e[l]),o.decorateNode({icon:e[l]});break;case 18:case 23:o.decorateNode({class:e[l]});break;case 19:o.getLogger().trace("SPACELIST");break;case 20:o.getLogger().trace("Node: ",e[l-1].id),o.addNode(0,e[l-1].id,e[l-1].descr,e[l-1].type,e[l]);break;case 21:o.getLogger().trace("Node: ",e[l].id),o.addNode(0,e[l].id,e[l].descr,e[l].type);break;case 22:o.decorateNode({icon:e[l]});break;case 27:o.getLogger().trace("node found ..",e[l-2]),this.$={id:e[l-1],descr:e[l-1],type:o.getType(e[l-2],e[l])};break;case 28:this.$={id:e[l],descr:e[l],type:0};break;case 29:o.getLogger().trace("node found ..",e[l-3]),this.$={id:e[l-3],descr:e[l-1],type:o.getType(e[l-2],e[l])};break;case 30:this.$=e[l-1]+e[l];break;case 31:this.$=e[l];break}},"anonymous"),table:[{3:1,4:2,5:3,6:[1,5],8:g},{1:[3]},{1:[2,1]},{4:6,6:[1,7],7:[1,8],8:g},{6:d,7:[1,10],9:9,12:11,13:r,14:14,16:p,17:E,18:17,19:18,20:f,23:h},t(L,[2,3]),{1:[2,2]},t(L,[2,4]),t(L,[2,5]),{1:[2,6],6:d,12:21,13:r,14:14,16:p,17:E,18:17,19:18,20:f,23:h},{6:d,9:22,12:11,13:r,14:14,16:p,17:E,18:17,19:18,20:f,23:h},{6:C,7:w,10:23,11:N},t(i,[2,24],{18:17,19:18,14:27,16:[1,28],17:[1,29],20:f,23:h}),t(i,[2,19]),t(i,[2,21],{15:30,24:H}),t(i,[2,22]),t(i,[2,23]),t(x,[2,25]),t(x,[2,26]),t(x,[2,28],{20:[1,32]}),{21:[1,33]},{6:C,7:w,10:34,11:N},{1:[2,7],6:d,12:21,13:r,14:14,16:p,17:E,18:17,19:18,20:f,23:h},t(P,[2,14],{7:M,11:U}),t(A,[2,8]),t(A,[2,9]),t(A,[2,10]),t(i,[2,16],{15:37,24:H}),t(i,[2,17]),t(i,[2,18]),t(i,[2,20],{24:j}),t(x,[2,31]),{21:[1,39]},{22:[1,40]},t(P,[2,13],{7:M,11:U}),t(A,[2,11]),t(A,[2,12]),t(i,[2,15],{24:j}),t(x,[2,30]),{22:[1,41]},t(x,[2,27]),t(x,[2,29])],defaultActions:{2:[2,1],6:[2,2]},parseError:c(function(s,n){if(n.recoverable)this.trace(s);else{var a=new Error(s);throw a.hash=n,a}},"parseError"),parse:c(function(s){var n=this,a=[0],o=[],u=[null],e=[],B=this.table,l="",z=0,ie=0,ue=2,re=1,ge=e.slice.call(arguments,1),b=Object.create(this.lexer),T={yy:{}};for(var J in this.yy)Object.prototype.hasOwnProperty.call(this.yy,J)&&(T.yy[J]=this.yy[J]);b.setInput(s,T.yy),T.yy.lexer=b,T.yy.parser=this,typeof b.yylloc>"u"&&(b.yylloc={});var q=b.yylloc;e.push(q);var de=b.options&&b.options.ranges;typeof T.yy.parseError=="function"?this.parseError=T.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function pe(S){a.length=a.length-2*S,u.length=u.length-S,e.length=e.length-S}c(pe,"popStack");function ae(){var S;return S=o.pop()||b.lex()||re,typeof S!="number"&&(S instanceof Array&&(o=S,S=o.pop()),S=n.symbols_[S]||S),S}c(ae,"lex");for(var k,R,v,Q,F={},K,I,oe,X;;){if(R=a[a.length-1],this.defaultActions[R]?v=this.defaultActions[R]:((k===null||typeof k>"u")&&(k=ae()),v=B[R]&&B[R][k]),typeof v>"u"||!v.length||!v[0]){var Z="";X=[];for(K in B[R])this.terminals_[K]&&K>ue&&X.push("'"+this.terminals_[K]+"'");b.showPosition?Z="Parse error on line "+(z+1)+`:
import{g as fe}from"./chunk-E2GYISFI-Cixkpli4.js";import{_ as c,l as te,c as W,K as ye,a8 as be,a9 as me,aa as _e,a3 as Ee,H as Y,i as G,v as ke,J as Se,a4 as Ne,a5 as le,a6 as ce}from"./mermaid-vendor-GB05DkYd.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var $=function(){var t=c(function(_,s,n,a){for(n=n||{},a=_.length;a--;n[_[a]]=s);return n},"o"),g=[1,4],d=[1,13],r=[1,12],p=[1,15],E=[1,16],f=[1,20],h=[1,19],L=[6,7,8],C=[1,26],w=[1,24],N=[1,25],i=[6,7,11],H=[1,31],x=[6,7,11,24],P=[1,6,13,16,17,20,23],M=[1,35],U=[1,36],A=[1,6,7,11,13,16,17,20,23],j=[1,38],V={trace:c(function(){},"trace"),yy:{},symbols_:{error:2,start:3,mindMap:4,spaceLines:5,SPACELINE:6,NL:7,KANBAN:8,document:9,stop:10,EOF:11,statement:12,SPACELIST:13,node:14,shapeData:15,ICON:16,CLASS:17,nodeWithId:18,nodeWithoutId:19,NODE_DSTART:20,NODE_DESCR:21,NODE_DEND:22,NODE_ID:23,SHAPE_DATA:24,$accept:0,$end:1},terminals_:{2:"error",6:"SPACELINE",7:"NL",8:"KANBAN",11:"EOF",13:"SPACELIST",16:"ICON",17:"CLASS",20:"NODE_DSTART",21:"NODE_DESCR",22:"NODE_DEND",23:"NODE_ID",24:"SHAPE_DATA"},productions_:[0,[3,1],[3,2],[5,1],[5,2],[5,2],[4,2],[4,3],[10,1],[10,1],[10,1],[10,2],[10,2],[9,3],[9,2],[12,3],[12,2],[12,2],[12,2],[12,1],[12,2],[12,1],[12,1],[12,1],[12,1],[14,1],[14,1],[19,3],[18,1],[18,4],[15,2],[15,1]],performAction:c(function(s,n,a,o,u,e,B){var l=e.length-1;switch(u){case 6:case 7:return o;case 8:o.getLogger().trace("Stop NL ");break;case 9:o.getLogger().trace("Stop EOF ");break;case 11:o.getLogger().trace("Stop NL2 ");break;case 12:o.getLogger().trace("Stop EOF2 ");break;case 15:o.getLogger().info("Node: ",e[l-1].id),o.addNode(e[l-2].length,e[l-1].id,e[l-1].descr,e[l-1].type,e[l]);break;case 16:o.getLogger().info("Node: ",e[l].id),o.addNode(e[l-1].length,e[l].id,e[l].descr,e[l].type);break;case 17:o.getLogger().trace("Icon: ",e[l]),o.decorateNode({icon:e[l]});break;case 18:case 23:o.decorateNode({class:e[l]});break;case 19:o.getLogger().trace("SPACELIST");break;case 20:o.getLogger().trace("Node: ",e[l-1].id),o.addNode(0,e[l-1].id,e[l-1].descr,e[l-1].type,e[l]);break;case 21:o.getLogger().trace("Node: ",e[l].id),o.addNode(0,e[l].id,e[l].descr,e[l].type);break;case 22:o.decorateNode({icon:e[l]});break;case 27:o.getLogger().trace("node found ..",e[l-2]),this.$={id:e[l-1],descr:e[l-1],type:o.getType(e[l-2],e[l])};break;case 28:this.$={id:e[l],descr:e[l],type:0};break;case 29:o.getLogger().trace("node found ..",e[l-3]),this.$={id:e[l-3],descr:e[l-1],type:o.getType(e[l-2],e[l])};break;case 30:this.$=e[l-1]+e[l];break;case 31:this.$=e[l];break}},"anonymous"),table:[{3:1,4:2,5:3,6:[1,5],8:g},{1:[3]},{1:[2,1]},{4:6,6:[1,7],7:[1,8],8:g},{6:d,7:[1,10],9:9,12:11,13:r,14:14,16:p,17:E,18:17,19:18,20:f,23:h},t(L,[2,3]),{1:[2,2]},t(L,[2,4]),t(L,[2,5]),{1:[2,6],6:d,12:21,13:r,14:14,16:p,17:E,18:17,19:18,20:f,23:h},{6:d,9:22,12:11,13:r,14:14,16:p,17:E,18:17,19:18,20:f,23:h},{6:C,7:w,10:23,11:N},t(i,[2,24],{18:17,19:18,14:27,16:[1,28],17:[1,29],20:f,23:h}),t(i,[2,19]),t(i,[2,21],{15:30,24:H}),t(i,[2,22]),t(i,[2,23]),t(x,[2,25]),t(x,[2,26]),t(x,[2,28],{20:[1,32]}),{21:[1,33]},{6:C,7:w,10:34,11:N},{1:[2,7],6:d,12:21,13:r,14:14,16:p,17:E,18:17,19:18,20:f,23:h},t(P,[2,14],{7:M,11:U}),t(A,[2,8]),t(A,[2,9]),t(A,[2,10]),t(i,[2,16],{15:37,24:H}),t(i,[2,17]),t(i,[2,18]),t(i,[2,20],{24:j}),t(x,[2,31]),{21:[1,39]},{22:[1,40]},t(P,[2,13],{7:M,11:U}),t(A,[2,11]),t(A,[2,12]),t(i,[2,15],{24:j}),t(x,[2,30]),{22:[1,41]},t(x,[2,27]),t(x,[2,29])],defaultActions:{2:[2,1],6:[2,2]},parseError:c(function(s,n){if(n.recoverable)this.trace(s);else{var a=new Error(s);throw a.hash=n,a}},"parseError"),parse:c(function(s){var n=this,a=[0],o=[],u=[null],e=[],B=this.table,l="",z=0,ie=0,ue=2,re=1,ge=e.slice.call(arguments,1),b=Object.create(this.lexer),T={yy:{}};for(var J in this.yy)Object.prototype.hasOwnProperty.call(this.yy,J)&&(T.yy[J]=this.yy[J]);b.setInput(s,T.yy),T.yy.lexer=b,T.yy.parser=this,typeof b.yylloc>"u"&&(b.yylloc={});var q=b.yylloc;e.push(q);var de=b.options&&b.options.ranges;typeof T.yy.parseError=="function"?this.parseError=T.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function pe(S){a.length=a.length-2*S,u.length=u.length-S,e.length=e.length-S}c(pe,"popStack");function ae(){var S;return S=o.pop()||b.lex()||re,typeof S!="number"&&(S instanceof Array&&(o=S,S=o.pop()),S=n.symbols_[S]||S),S}c(ae,"lex");for(var k,R,v,Q,F={},K,I,oe,X;;){if(R=a[a.length-1],this.defaultActions[R]?v=this.defaultActions[R]:((k===null||typeof k>"u")&&(k=ae()),v=B[R]&&B[R][k]),typeof v>"u"||!v.length||!v[0]){var Z="";X=[];for(K in B[R])this.terminals_[K]&&K>ue&&X.push("'"+this.terminals_[K]+"'");b.showPosition?Z="Parse error on line "+(z+1)+`:
`+b.showPosition()+`
Expecting `+X.join(", ")+", got '"+(this.terminals_[k]||k)+"'":Z="Parse error on line "+(z+1)+": Unexpected "+(k==re?"end of input":"'"+(this.terminals_[k]||k)+"'"),this.parseError(Z,{text:b.match,token:this.terminals_[k]||k,line:b.yylineno,loc:q,expected:X})}if(v[0]instanceof Array&&v.length>1)throw new Error("Parse Error: multiple actions possible at state: "+R+", token: "+k);switch(v[0]){case 1:a.push(k),u.push(b.yytext),e.push(b.yylloc),a.push(v[1]),k=null,ie=b.yyleng,l=b.yytext,z=b.yylineno,q=b.yylloc;break;case 2:if(I=this.productions_[v[1]][1],F.$=u[u.length-I],F._$={first_line:e[e.length-(I||1)].first_line,last_line:e[e.length-1].last_line,first_column:e[e.length-(I||1)].first_column,last_column:e[e.length-1].last_column},de&&(F._$.range=[e[e.length-(I||1)].range[0],e[e.length-1].range[1]]),Q=this.performAction.apply(F,[l,ie,z,T.yy,v[1],u,e].concat(ge)),typeof Q<"u")return Q;I&&(a=a.slice(0,-1*I*2),u=u.slice(0,-1*I),e=e.slice(0,-1*I)),a.push(this.productions_[v[1]][0]),u.push(F.$),e.push(F._$),oe=B[a[a.length-2]][a[a.length-1]],a.push(oe);break;case 3:return!0}}return!0},"parse")},m=function(){var _={EOF:1,parseError:c(function(n,a){if(this.yy.parser)this.yy.parser.parseError(n,a);else throw new Error(n)},"parseError"),setInput:c(function(s,n){return this.yy=n||this.yy||{},this._input=s,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:c(function(){var s=this._input[0];this.yytext+=s,this.yyleng++,this.offset++,this.match+=s,this.matched+=s;var n=s.match(/(?:\r\n?|\n).*/g);return n?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),s},"input"),unput:c(function(s){var n=s.length,a=s.split(/(?:\r\n?|\n)/g);this._input=s+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-n),this.offset-=n;var o=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),a.length-1&&(this.yylineno-=a.length-1);var u=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:a?(a.length===o.length?this.yylloc.first_column:0)+o[o.length-a.length].length-a[0].length:this.yylloc.first_column-n},this.options.ranges&&(this.yylloc.range=[u[0],u[0]+this.yyleng-n]),this.yyleng=this.yytext.length,this},"unput"),more:c(function(){return this._more=!0,this},"more"),reject:c(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:c(function(s){this.unput(this.match.slice(s))},"less"),pastInput:c(function(){var s=this.matched.substr(0,this.matched.length-this.match.length);return(s.length>20?"...":"")+s.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:c(function(){var s=this.match;return s.length<20&&(s+=this._input.substr(0,20-s.length)),(s.substr(0,20)+(s.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:c(function(){var s=this.pastInput(),n=new Array(s.length+1).join("-");return s+this.upcomingInput()+`

View File

@@ -1,4 +1,4 @@
import{p as N}from"./chunk-353BL4L5-BgtJsm81.js";import{_ as i,g as B,s as U,a as q,b as H,t as K,q as V,l as C,c as Z,F as j,K as J,M as Q,N as z,O as X,e as Y,z as tt,P as et,H as at}from"./mermaid-vendor-C4V_MkUy.js";import{p as rt}from"./treemap-75Q7IDZK-Bh7sugQT.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";import"./_baseUniq-CZTq81C3.js";import"./_basePickBy-Z1bijFVM.js";import"./clone-Dx_4EPXr.js";var it=at.pie,D={sections:new Map,showData:!1},f=D.sections,w=D.showData,st=structuredClone(it),ot=i(()=>structuredClone(st),"getConfig"),nt=i(()=>{f=new Map,w=D.showData,tt()},"clear"),lt=i(({label:t,value:a})=>{f.has(t)||(f.set(t,a),C.debug(`added new section: ${t}, with value: ${a}`))},"addSection"),ct=i(()=>f,"getSections"),pt=i(t=>{w=t},"setShowData"),dt=i(()=>w,"getShowData"),F={getConfig:ot,clear:nt,setDiagramTitle:V,getDiagramTitle:K,setAccTitle:H,getAccTitle:q,setAccDescription:U,getAccDescription:B,addSection:lt,getSections:ct,setShowData:pt,getShowData:dt},gt=i((t,a)=>{N(t,a),a.setShowData(t.showData),t.sections.map(a.addSection)},"populateDb"),ut={parse:i(async t=>{const a=await rt("pie",t);C.debug(a),gt(a,F)},"parse")},mt=i(t=>`
import{p as N}from"./chunk-353BL4L5-BdESKFSH.js";import{_ as i,g as B,s as U,a as q,b as H,t as K,q as V,l as C,c as Z,F as j,K as J,M as Q,N as z,O as X,e as Y,z as tt,P as et,H as at}from"./mermaid-vendor-GB05DkYd.js";import{p as rt}from"./treemap-75Q7IDZK-C9xJN-2g.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";import"./_baseUniq-DUOGdItU.js";import"./_basePickBy-V-PVS_is.js";import"./clone-CyTo8HmA.js";var it=at.pie,D={sections:new Map,showData:!1},f=D.sections,w=D.showData,st=structuredClone(it),ot=i(()=>structuredClone(st),"getConfig"),nt=i(()=>{f=new Map,w=D.showData,tt()},"clear"),lt=i(({label:t,value:a})=>{f.has(t)||(f.set(t,a),C.debug(`added new section: ${t}, with value: ${a}`))},"addSection"),ct=i(()=>f,"getSections"),pt=i(t=>{w=t},"setShowData"),dt=i(()=>w,"getShowData"),F={getConfig:ot,clear:nt,setDiagramTitle:V,getDiagramTitle:K,setAccTitle:H,getAccTitle:q,setAccDescription:U,getAccDescription:B,addSection:lt,getSections:ct,setShowData:pt,getShowData:dt},gt=i((t,a)=>{N(t,a),a.setShowData(t.showData),t.sections.map(a.addSection)},"populateDb"),ut={parse:i(async t=>{const a=await rt("pie",t);C.debug(a),gt(a,F)},"parse")},mt=i(t=>`
.pieCircle{
stroke: ${t.pieStrokeColor};
stroke-width : ${t.pieStrokeWidth};

View File

@@ -1 +1 @@
import{s as r,b as e,a,S as i}from"./chunk-OW32GOEJ-CXy-rraF.js";import{_ as s}from"./mermaid-vendor-C4V_MkUy.js";import"./chunk-BFAMUDN2-lYQpQICr.js";import"./chunk-SKB7J2MH-JBIfIwyf.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var f={parser:a,get db(){return new i(2)},renderer:e,styles:r,init:s(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{f as diagram};
import{s as r,b as e,a,S as i}from"./chunk-OW32GOEJ-CHuxbc0x.js";import{_ as s}from"./mermaid-vendor-GB05DkYd.js";import"./chunk-BFAMUDN2-ghvP-Rq6.js";import"./chunk-SKB7J2MH-gQmYvnvi.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var f={parser:a,get db(){return new i(2)},renderer:e,styles:r,init:s(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{f as diagram};

View File

@@ -1,4 +1,4 @@
import{_ as s,c as xt,l as E,d as q,a3 as kt,a4 as _t,a5 as bt,a6 as vt,N as nt,D as wt,a7 as St,z as Et}from"./mermaid-vendor-C4V_MkUy.js";import"./feature-graph-C2lnkH6U.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var X=function(){var n=s(function(f,r,a,h){for(a=a||{},h=f.length;h--;a[f[h]]=r);return a},"o"),t=[6,8,10,11,12,14,16,17,20,21],e=[1,9],l=[1,10],i=[1,11],d=[1,12],c=[1,13],g=[1,16],m=[1,17],p={trace:s(function(){},"trace"),yy:{},symbols_:{error:2,start:3,timeline:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,period_statement:18,event_statement:19,period:20,event:21,$accept:0,$end:1},terminals_:{2:"error",4:"timeline",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",20:"period",21:"event"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,1],[18,1],[19,1]],performAction:s(function(r,a,h,u,y,o,S){var k=o.length-1;switch(y){case 1:return o[k-1];case 2:this.$=[];break;case 3:o[k-1].push(o[k]),this.$=o[k-1];break;case 4:case 5:this.$=o[k];break;case 6:case 7:this.$=[];break;case 8:u.getCommonDb().setDiagramTitle(o[k].substr(6)),this.$=o[k].substr(6);break;case 9:this.$=o[k].trim(),u.getCommonDb().setAccTitle(this.$);break;case 10:case 11:this.$=o[k].trim(),u.getCommonDb().setAccDescription(this.$);break;case 12:u.addSection(o[k].substr(8)),this.$=o[k].substr(8);break;case 15:u.addTask(o[k],0,""),this.$=o[k];break;case 16:u.addEvent(o[k].substr(2)),this.$=o[k];break}},"anonymous"),table:[{3:1,4:[1,2]},{1:[3]},n(t,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:e,12:l,14:i,16:d,17:c,18:14,19:15,20:g,21:m},n(t,[2,7],{1:[2,1]}),n(t,[2,3]),{9:18,11:e,12:l,14:i,16:d,17:c,18:14,19:15,20:g,21:m},n(t,[2,5]),n(t,[2,6]),n(t,[2,8]),{13:[1,19]},{15:[1,20]},n(t,[2,11]),n(t,[2,12]),n(t,[2,13]),n(t,[2,14]),n(t,[2,15]),n(t,[2,16]),n(t,[2,4]),n(t,[2,9]),n(t,[2,10])],defaultActions:{},parseError:s(function(r,a){if(a.recoverable)this.trace(r);else{var h=new Error(r);throw h.hash=a,h}},"parseError"),parse:s(function(r){var a=this,h=[0],u=[],y=[null],o=[],S=this.table,k="",M=0,C=0,B=2,J=1,O=o.slice.call(arguments,1),_=Object.create(this.lexer),N={yy:{}};for(var L in this.yy)Object.prototype.hasOwnProperty.call(this.yy,L)&&(N.yy[L]=this.yy[L]);_.setInput(r,N.yy),N.yy.lexer=_,N.yy.parser=this,typeof _.yylloc>"u"&&(_.yylloc={});var v=_.yylloc;o.push(v);var $=_.options&&_.options.ranges;typeof N.yy.parseError=="function"?this.parseError=N.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function R(T){h.length=h.length-2*T,y.length=y.length-T,o.length=o.length-T}s(R,"popStack");function A(){var T;return T=u.pop()||_.lex()||J,typeof T!="number"&&(T instanceof Array&&(u=T,T=u.pop()),T=a.symbols_[T]||T),T}s(A,"lex");for(var w,H,I,K,F={},j,P,et,G;;){if(H=h[h.length-1],this.defaultActions[H]?I=this.defaultActions[H]:((w===null||typeof w>"u")&&(w=A()),I=S[H]&&S[H][w]),typeof I>"u"||!I.length||!I[0]){var Q="";G=[];for(j in S[H])this.terminals_[j]&&j>B&&G.push("'"+this.terminals_[j]+"'");_.showPosition?Q="Parse error on line "+(M+1)+`:
import{_ as s,c as xt,l as E,d as q,a3 as kt,a4 as _t,a5 as bt,a6 as vt,N as nt,D as wt,a7 as St,z as Et}from"./mermaid-vendor-GB05DkYd.js";import"./feature-graph-Ce9OX-bo.js";import"./react-vendor-DEwriMA6.js";import"./graph-vendor-B-X5JegA.js";import"./ui-vendor-CeCm8EER.js";import"./utils-vendor-BysuhMZA.js";var X=function(){var n=s(function(f,r,a,h){for(a=a||{},h=f.length;h--;a[f[h]]=r);return a},"o"),t=[6,8,10,11,12,14,16,17,20,21],e=[1,9],l=[1,10],i=[1,11],d=[1,12],c=[1,13],g=[1,16],m=[1,17],p={trace:s(function(){},"trace"),yy:{},symbols_:{error:2,start:3,timeline:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,period_statement:18,event_statement:19,period:20,event:21,$accept:0,$end:1},terminals_:{2:"error",4:"timeline",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",20:"period",21:"event"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,1],[18,1],[19,1]],performAction:s(function(r,a,h,u,y,o,S){var k=o.length-1;switch(y){case 1:return o[k-1];case 2:this.$=[];break;case 3:o[k-1].push(o[k]),this.$=o[k-1];break;case 4:case 5:this.$=o[k];break;case 6:case 7:this.$=[];break;case 8:u.getCommonDb().setDiagramTitle(o[k].substr(6)),this.$=o[k].substr(6);break;case 9:this.$=o[k].trim(),u.getCommonDb().setAccTitle(this.$);break;case 10:case 11:this.$=o[k].trim(),u.getCommonDb().setAccDescription(this.$);break;case 12:u.addSection(o[k].substr(8)),this.$=o[k].substr(8);break;case 15:u.addTask(o[k],0,""),this.$=o[k];break;case 16:u.addEvent(o[k].substr(2)),this.$=o[k];break}},"anonymous"),table:[{3:1,4:[1,2]},{1:[3]},n(t,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:e,12:l,14:i,16:d,17:c,18:14,19:15,20:g,21:m},n(t,[2,7],{1:[2,1]}),n(t,[2,3]),{9:18,11:e,12:l,14:i,16:d,17:c,18:14,19:15,20:g,21:m},n(t,[2,5]),n(t,[2,6]),n(t,[2,8]),{13:[1,19]},{15:[1,20]},n(t,[2,11]),n(t,[2,12]),n(t,[2,13]),n(t,[2,14]),n(t,[2,15]),n(t,[2,16]),n(t,[2,4]),n(t,[2,9]),n(t,[2,10])],defaultActions:{},parseError:s(function(r,a){if(a.recoverable)this.trace(r);else{var h=new Error(r);throw h.hash=a,h}},"parseError"),parse:s(function(r){var a=this,h=[0],u=[],y=[null],o=[],S=this.table,k="",M=0,C=0,B=2,J=1,O=o.slice.call(arguments,1),_=Object.create(this.lexer),N={yy:{}};for(var L in this.yy)Object.prototype.hasOwnProperty.call(this.yy,L)&&(N.yy[L]=this.yy[L]);_.setInput(r,N.yy),N.yy.lexer=_,N.yy.parser=this,typeof _.yylloc>"u"&&(_.yylloc={});var v=_.yylloc;o.push(v);var $=_.options&&_.options.ranges;typeof N.yy.parseError=="function"?this.parseError=N.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function R(T){h.length=h.length-2*T,y.length=y.length-T,o.length=o.length-T}s(R,"popStack");function A(){var T;return T=u.pop()||_.lex()||J,typeof T!="number"&&(T instanceof Array&&(u=T,T=u.pop()),T=a.symbols_[T]||T),T}s(A,"lex");for(var w,H,I,K,F={},j,P,et,G;;){if(H=h[h.length-1],this.defaultActions[H]?I=this.defaultActions[H]:((w===null||typeof w>"u")&&(w=A()),I=S[H]&&S[H][w]),typeof I>"u"||!I.length||!I[0]){var Q="";G=[];for(j in S[H])this.terminals_[j]&&j>B&&G.push("'"+this.terminals_[j]+"'");_.showPosition?Q="Parse error on line "+(M+1)+`:
`+_.showPosition()+`
Expecting `+G.join(", ")+", got '"+(this.terminals_[w]||w)+"'":Q="Parse error on line "+(M+1)+": Unexpected "+(w==J?"end of input":"'"+(this.terminals_[w]||w)+"'"),this.parseError(Q,{text:_.match,token:this.terminals_[w]||w,line:_.yylineno,loc:v,expected:G})}if(I[0]instanceof Array&&I.length>1)throw new Error("Parse Error: multiple actions possible at state: "+H+", token: "+w);switch(I[0]){case 1:h.push(w),y.push(_.yytext),o.push(_.yylloc),h.push(I[1]),w=null,C=_.yyleng,k=_.yytext,M=_.yylineno,v=_.yylloc;break;case 2:if(P=this.productions_[I[1]][1],F.$=y[y.length-P],F._$={first_line:o[o.length-(P||1)].first_line,last_line:o[o.length-1].last_line,first_column:o[o.length-(P||1)].first_column,last_column:o[o.length-1].last_column},$&&(F._$.range=[o[o.length-(P||1)].range[0],o[o.length-1].range[1]]),K=this.performAction.apply(F,[k,C,M,N.yy,I[1],y,o].concat(O)),typeof K<"u")return K;P&&(h=h.slice(0,-1*P*2),y=y.slice(0,-1*P),o=o.slice(0,-1*P)),h.push(this.productions_[I[1]][0]),y.push(F.$),o.push(F._$),et=S[h[h.length-2]][h[h.length-1]],h.push(et);break;case 3:return!0}}return!0},"parse")},x=function(){var f={EOF:1,parseError:s(function(a,h){if(this.yy.parser)this.yy.parser.parseError(a,h);else throw new Error(a)},"parseError"),setInput:s(function(r,a){return this.yy=a||this.yy||{},this._input=r,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:s(function(){var r=this._input[0];this.yytext+=r,this.yyleng++,this.offset++,this.match+=r,this.matched+=r;var a=r.match(/(?:\r\n?|\n).*/g);return a?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),r},"input"),unput:s(function(r){var a=r.length,h=r.split(/(?:\r\n?|\n)/g);this._input=r+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-a),this.offset-=a;var u=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),h.length-1&&(this.yylineno-=h.length-1);var y=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:h?(h.length===u.length?this.yylloc.first_column:0)+u[u.length-h.length].length-h[0].length:this.yylloc.first_column-a},this.options.ranges&&(this.yylloc.range=[y[0],y[0]+this.yyleng-a]),this.yyleng=this.yytext.length,this},"unput"),more:s(function(){return this._more=!0,this},"more"),reject:s(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:s(function(r){this.unput(this.match.slice(r))},"less"),pastInput:s(function(){var r=this.matched.substr(0,this.matched.length-this.match.length);return(r.length>20?"...":"")+r.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:s(function(){var r=this.match;return r.length<20&&(r+=this._input.substr(0,20-r.length)),(r.substr(0,20)+(r.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:s(function(){var r=this.pastInput(),a=new Array(r.length+1).join("-");return r+this.upcomingInput()+`

View File

@@ -8,18 +8,18 @@
<link rel="icon" type="image/png" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RailSeek</title>
<script type="module" crossorigin src="/webui/assets/index-CSBE424h.js"></script>
<script type="module" crossorigin src="/webui/assets/index-4EuN1Ajv.js"></script>
<link rel="modulepreload" crossorigin href="/webui/assets/react-vendor-DEwriMA6.js">
<link rel="modulepreload" crossorigin href="/webui/assets/ui-vendor-CeCm8EER.js">
<link rel="modulepreload" crossorigin href="/webui/assets/graph-vendor-B-X5JegA.js">
<link rel="modulepreload" crossorigin href="/webui/assets/utils-vendor-BysuhMZA.js">
<link rel="modulepreload" crossorigin href="/webui/assets/feature-graph-C2lnkH6U.js">
<link rel="modulepreload" crossorigin href="/webui/assets/feature-documents-Cz85jZmh.js">
<link rel="modulepreload" crossorigin href="/webui/assets/mermaid-vendor-C4V_MkUy.js">
<link rel="modulepreload" crossorigin href="/webui/assets/markdown-vendor-DQBWdwkI.js">
<link rel="modulepreload" crossorigin href="/webui/assets/feature-retrieval-24678VmD.js">
<link rel="modulepreload" crossorigin href="/webui/assets/feature-graph-Ce9OX-bo.js">
<link rel="modulepreload" crossorigin href="/webui/assets/feature-documents-D0lvjDJ6.js">
<link rel="modulepreload" crossorigin href="/webui/assets/mermaid-vendor-GB05DkYd.js">
<link rel="modulepreload" crossorigin href="/webui/assets/markdown-vendor-BiwnQtuo.js">
<link rel="modulepreload" crossorigin href="/webui/assets/feature-retrieval-d11Pfb66.js">
<link rel="stylesheet" crossorigin href="/webui/assets/feature-graph-BipNuM18.css">
<link rel="stylesheet" crossorigin href="/webui/assets/index-Dgjqs9Yg.css">
<link rel="stylesheet" crossorigin href="/webui/assets/index-BTI4OT92.css">
</head>
<body>
<div id="root"></div>

View File

@@ -5,6 +5,7 @@ Provides isolation between different workspaces by managing separate LightRAG in
import os
import logging
import asyncio
from pathlib import Path
from typing import Dict, List, Optional, Tuple
from lightrag import LightRAG
@@ -62,11 +63,54 @@ class WorkspaceManager:
logger.error(f"Failed to create workspace '{name}': {e}")
raise
def delete_workspace(self, name: str) -> bool:
async def delete_workspace(self, name: str) -> bool:
"""Delete a workspace directory and all its data."""
# TODO: implement deletion with caution (maybe require confirmation)
# For now, just raise NotImplementedError
raise NotImplementedError("Workspace deletion not yet implemented")
import shutil
from pathlib import Path
# Validate name
if not name or not name.strip():
raise ValueError("Workspace name cannot be empty")
name = name.strip()
# Check if workspace exists
workspace_dir = self.base_working_dir / name
input_subdir = self.base_input_dir / name
if not workspace_dir.exists() and not input_subdir.exists():
raise ValueError(f"Workspace '{name}' does not exist")
# Remove cached instances
if name in self._rag_instances:
del self._rag_instances[name]
if name in self._doc_managers:
del self._doc_managers[name]
# Delete workspace data from storage (vector DB, KV, graph, etc.)
try:
if self.lightrag_factory:
# Create a temporary LightRAG instance for this workspace to delete its data
rag = self.lightrag_factory(str(self.base_working_dir), name)
# Call async delete_workspace_data
await rag.adelete_workspace_data()
logger.info(f"Deleted workspace data for '{name}' from storage")
else:
logger.warning("No lightrag_factory provided; workspace data may remain in storage")
except Exception as e:
logger.warning(f"Failed to delete workspace data for '{name}': {e}. Proceeding with directory deletion.")
# Delete directories recursively
try:
if workspace_dir.exists():
shutil.rmtree(workspace_dir)
logger.info(f"Deleted workspace directory: {workspace_dir}")
if input_subdir.exists():
shutil.rmtree(input_subdir)
logger.info(f"Deleted workspace input directory: {input_subdir}")
except Exception as e:
logger.error(f"Failed to delete workspace '{name}': {e}")
raise
return True
def get_rag(self, workspace: str = "") -> LightRAG:
"""Get or create a LightRAG instance for the given workspace."""

View File

@@ -30,6 +30,9 @@ if workspace_dir not in sys.path:
sys.path.insert(0, workspace_dir)
from fast_image_classifier import get_image_classifier
# Import optimized OCR processor
from .optimized_ocr_processor import OptimizedOCRProcessor
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@@ -377,9 +380,11 @@ class DocumentProcessor:
def __init__(self):
self.config = get_config()
self.ocr_processor = OCRProcessor(
self.ocr_processor = OptimizedOCRProcessor(
use_gpu=self.config.performance.USE_GPU,
languages=self.config.document_processing.OCR_LANGUAGES
languages=self.config.document_processing.OCR_LANGUAGES,
batch_size=4, # Process 4 images at a time for better performance
max_workers=2 # Use 2 parallel workers for async operations
)
self.supported_extensions = self.config.document_processing.SUPPORTED_EXTENSIONS
@@ -438,12 +443,15 @@ class DocumentProcessor:
def _extract_and_process_images(self, images: List[Any], file_type: str) -> Tuple[List[Dict[str, Any]], str]:
"""
Extract and process images from documents
Extract and process images from documents with batch OCR processing
Returns processed images metadata and additional content from OCR
"""
processed_images = []
additional_content = []
temp_paths = []
temp_files = []
# Step 1: Save all images to temporary files
for i, image_data in enumerate(images):
temp_path = None
try:
@@ -461,24 +469,60 @@ class DocumentProcessor:
temp_file.write(image_bytes)
temp_path = temp_file.name
# Process image with OCR first, then classify only if no text found
image_metadata = {"path": temp_path, "index": i}
temp_paths.append(temp_path)
temp_files.append((i, temp_path, image_data))
# Step 1: Always run GPU OCR first
except Exception as e:
logger.error(f"Error saving image {i} to temporary file: {e}")
processed_images.append({
"index": i,
"error": str(e),
"path": temp_path or "unknown"
})
if not temp_paths:
return processed_images, ""
# Step 2: Batch OCR processing
batch_results = []
if self.ocr_processor.ocr_available:
try:
logger.info(f"Running GPU OCR on image {i+1}")
ocr_result = self.ocr_processor.extract_text_from_image(temp_path)
logger.info(f"OCR result for image {i+1}: {len(ocr_result['text'])} characters, confidence: {ocr_result['confidence']}")
logger.info(f"Running batch OCR on {len(temp_paths)} images")
batch_results = self.ocr_processor.extract_text_from_images_batch(temp_paths)
logger.info(f"Batch OCR completed for {len(batch_results)} images")
except Exception as e:
logger.error(f"Batch OCR processing failed: {e}")
# Fall back to individual processing
batch_results = []
if ocr_result["text"].strip():
# Step 3: Process results
for idx, (i, temp_path, image_data) in enumerate(temp_files):
image_metadata = {"path": temp_path, "index": i}
try:
# Get OCR result for this image
ocr_result = None
if batch_results and idx < len(batch_results):
batch_result = batch_results[idx]
ocr_result = {
"text": batch_result.text,
"confidence": batch_result.confidence,
"bboxes": batch_result.bboxes,
"line_count": batch_result.line_count
}
else:
# Fallback to individual OCR
if self.ocr_processor.ocr_available:
ocr_result = self.ocr_processor.extract_text_from_image(temp_path)
if ocr_result and ocr_result["text"].strip():
image_metadata["ocr_text"] = ocr_result["text"]
image_metadata["ocr_confidence"] = ocr_result["confidence"]
additional_content.append(f"[Image {i+1} OCR Text]: {ocr_result['text']}")
logger.info(f"Image {i+1} has text content, skipping classification")
else:
logger.info(f"Image {i+1} has no text, proceeding to classification")
# Step 2: Only classify if OCR found no text
# Step 4: Only classify if OCR found no text
if self.image_classifier and self.image_classifier.available:
try:
classification_results = self.image_classifier.classify_image(temp_path, top_k=3)
@@ -505,9 +549,6 @@ class DocumentProcessor:
except Exception as classify_error:
logger.error(f"Image classification failed for image {i+1}: {classify_error}")
image_metadata["classification_error"] = str(classify_error)
except Exception as ocr_error:
logger.error(f"OCR processing failed for image {i+1}: {ocr_error}")
image_metadata["ocr_error"] = str(ocr_error)
processed_images.append(image_metadata)
@@ -516,7 +557,7 @@ class DocumentProcessor:
processed_images.append({
"index": i,
"error": str(e),
"path": temp_path or "unknown"
"path": temp_path
})
finally:
# Clean up temporary file

View File

@@ -2250,6 +2250,50 @@ class LightRAG:
except Exception as e:
logger.error(f"Error while clearing cache: {e}")
async def adelete_workspace_data(self) -> None:
"""Delete all data for the current workspace from all storage instances.
This method drops all collections/namespaces for the workspace, effectively
clearing all documents, chunks, entities, relationships, and cache.
Should be called before deleting workspace directories.
Example:
# Delete all workspace data
await rag.adelete_workspace_data()
"""
logger.info(f"Deleting all workspace data for workspace: {self.workspace}")
# Ensure storages are initialized before dropping
if self._storages_status != StoragesStatus.INITIALIZED:
await self.initialize_storages()
storages = [
("full_docs", self.full_docs),
("text_chunks", self.text_chunks),
("full_entities", self.full_entities),
("full_relations", self.full_relations),
("entities_vdb", self.entities_vdb),
("relationships_vdb", self.relationships_vdb),
("chunks_vdb", self.chunks_vdb),
("chunk_entity_relation_graph", self.chunk_entity_relation_graph),
("llm_response_cache", self.llm_response_cache),
("doc_status", self.doc_status),
]
for name, storage in storages:
if storage is None:
continue
try:
success = await storage.drop()
if success:
logger.debug(f"Successfully dropped {name} for workspace {self.workspace}")
else:
logger.warning(f"Failed to drop {name} for workspace {self.workspace}")
except Exception as e:
logger.error(f"Error dropping {name}: {e}")
logger.info(f"Workspace data deletion completed for workspace: {self.workspace}")
def delete_workspace_data(self) -> None:
"""Synchronous version of adelete_workspace_data."""
return always_get_an_event_loop().run_until_complete(self.adelete_workspace_data())
def clear_cache(self) -> None:
"""Synchronous version of aclear_cache."""
return always_get_an_event_loop().run_until_complete(self.aclear_cache())

View File

@@ -159,6 +159,8 @@ async def ollama_embed(texts: list[str], embed_model, **kwargs) -> np.ndarray:
host = kwargs.pop("host", None)
timeout = kwargs.pop("timeout", None)
logger.info(f"ollama_embed: host={host}, api_key={'***' if api_key else None}, headers={headers}")
ollama_client = ollama.AsyncClient(host=host, timeout=timeout, headers=headers)
try:
options = kwargs.pop("options", {})

View File

@@ -4008,6 +4008,7 @@ async def _build_llm_context(
if not entities_context and not relations_context:
if return_raw_data:
# Return empty raw data structure when no entities/relations
logger.debug(f"[_build_query_context] Early return (mode != mix) with empty raw data")
empty_raw_data = _convert_to_user_format(
[],
[],
@@ -4122,11 +4123,33 @@ async def _build_query_context(
chunks_vdb,
)
logger.debug(f"[_build_query_context] Early return check: entities={len(search_result['final_entities'])}, relations={len(search_result['final_relations'])}, chunk_tracking={search_result.get('chunk_tracking')}, mode={query_param.mode}, return_raw_data={return_raw_data}")
if not search_result["final_entities"] and not search_result["final_relations"]:
if query_param.mode != "mix":
if return_raw_data:
# Return empty raw data structure when no entities/relations
empty_raw_data = _convert_to_user_format(
[],
[],
[],
query_param.mode,
)
return None, empty_raw_data
else:
return None
else:
if not search_result["chunk_tracking"]:
if return_raw_data:
# Return empty raw data structure when no entities/relations/chunks
logger.debug(f"[_build_query_context] Early return (mode=mix, no chunk_tracking) with empty raw data")
empty_raw_data = _convert_to_user_format(
[],
[],
[],
query_param.mode,
)
return None, empty_raw_data
else:
return None
# Stage 2: Apply token truncation for LLM efficiency
@@ -4155,6 +4178,16 @@ async def _build_query_context(
and not truncation_result["entities_context"]
and not truncation_result["relations_context"]
):
if return_raw_data:
# Return empty raw data structure when no entities/relations/chunks
empty_raw_data = _convert_to_user_format(
[],
[],
[],
query_param.mode,
)
return None, empty_raw_data
else:
return None
# Stage 4: Build final LLM context with dynamic token processing

View File

@@ -267,6 +267,7 @@ const axiosInstance = axios.create({
axiosInstance.interceptors.request.use((config) => {
const apiKey = useSettingsStore.getState().apiKey
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
const workspace = useSettingsStore.getState().workspace
// Always include token if it exists, regardless of path
if (token) {
@@ -275,6 +276,10 @@ axiosInstance.interceptors.request.use((config) => {
if (apiKey) {
config.headers['X-API-Key'] = apiKey
}
// Add workspace header if workspace is selected
if (workspace) {
config.headers['X-Workspace'] = workspace
}
return config
})
@@ -360,6 +365,7 @@ export const queryTextStream = async (
) => {
const apiKey = useSettingsStore.getState().apiKey;
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
const workspace = useSettingsStore.getState().workspace;
const headers: HeadersInit = {
'Content-Type': 'application/json',
'Accept': 'application/x-ndjson',
@@ -370,6 +376,9 @@ export const queryTextStream = async (
if (apiKey) {
headers['X-API-Key'] = apiKey;
}
if (workspace) {
headers['X-Workspace'] = workspace;
}
try {
const response = await fetch(`${backendBaseUrl}/query/stream`, {
@@ -779,3 +788,8 @@ export const createWorkspace = async (name: string): Promise<WorkspaceResponse>
const response = await axiosInstance.post('/workspaces/', { name })
return response.data
}
export const deleteWorkspace = async (name: string): Promise<{ message: string }> => {
const response = await axiosInstance.delete(`/workspaces/${encodeURIComponent(name)}`)
return response.data
}

View File

@@ -1,11 +1,11 @@
import { useEffect, useState, ChangeEvent, KeyboardEvent } from 'react'
import { useSettingsStore } from '@/stores/settings'
import { listWorkspaces, createWorkspace } from '@/api/lightrag'
import { listWorkspaces, createWorkspace, deleteWorkspace } from '@/api/lightrag'
import Button from '@/components/ui/Button'
import Input from '@/components/ui/Input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/Select'
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter, DialogClose } from '@/components/ui/Dialog'
import { PlusIcon, SearchIcon } from 'lucide-react'
import { PlusIcon, SearchIcon, TrashIcon } from 'lucide-react'
import { useTranslation } from 'react-i18next'
export function WorkspaceSelector() {
@@ -18,6 +18,8 @@ export function WorkspaceSelector() {
const [search, setSearch] = useState('')
const [newWorkspaceName, setNewWorkspaceName] = useState('')
const [creating, setCreating] = useState(false)
const [deleting, setDeleting] = useState(false)
const [showDeleteDialog, setShowDeleteDialog] = useState(false)
// Fetch workspaces on mount
useEffect(() => {
@@ -56,12 +58,29 @@ export function WorkspaceSelector() {
}
}
const handleDeleteWorkspace = async () => {
if (!workspace) return
setDeleting(true)
try {
await deleteWorkspace(workspace)
await fetchWorkspaces()
// Clear selected workspace if it was deleted
setWorkspace('')
setShowDeleteDialog(false)
} catch (error) {
console.error('Failed to delete workspace:', error)
alert(`Failed to delete workspace: ${error}`)
} finally {
setDeleting(false)
}
}
const filteredWorkspaces = workspaceList.filter(name =>
name.toLowerCase().includes(search.toLowerCase())
)
return (
<div className="flex items-center gap-2">
<div className="flex flex-row items-center gap-2">
<Select
value={workspace || ''}
onValueChange={(value) => setWorkspace(value)}
@@ -95,6 +114,42 @@ export function WorkspaceSelector() {
</SelectContent>
</Select>
<div className="flex items-center gap-2">
{workspace && (
<Dialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
<DialogTrigger asChild>
<Button size="icon" variant="outline" className="text-destructive">
<TrashIcon className="size-4" />
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>{t('workspace.deleteTitle')}</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<p className="text-sm">
{t('workspace.deleteConfirm', { workspace })}
</p>
<p className="text-sm text-muted-foreground">
{t('workspace.deleteWarning')}
</p>
</div>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">{t('common.cancel')}</Button>
</DialogClose>
<Button
onClick={handleDeleteWorkspace}
disabled={deleting}
variant="destructive"
>
{deleting ? t('common.deleting') : t('common.delete')}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)}
<Dialog>
<DialogTrigger asChild>
<Button size="icon" variant="outline">
@@ -132,5 +187,6 @@ export function WorkspaceSelector() {
</DialogContent>
</Dialog>
</div>
</div>
)
}

View File

@@ -202,6 +202,7 @@ export default function DocumentManager() {
const setShowFileName = useSettingsStore.use.setShowFileName()
const documentsPageSize = useSettingsStore.use.documentsPageSize()
const setDocumentsPageSize = useSettingsStore.use.setDocumentsPageSize()
const workspace = useSettingsStore.use.workspace()
// New pagination state
const [currentPageDocs, setCurrentPageDocs] = useState<DocStatusResponse[]>([])
@@ -901,6 +902,7 @@ export default function DocumentManager() {
statusFilter,
sortField,
sortDirection,
workspace,
fetchPaginatedDocuments
]);

View File

@@ -68,7 +68,9 @@ export default function SiteHeader() {
}
return (
<header className="border-border/40 bg-background/95 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-50 flex h-10 w-full border-b px-4 backdrop-blur">
<header className="border-border/40 bg-background/95 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-50 flex flex-col w-full border-b px-4 backdrop-blur">
{/* First row: Title and other header items */}
<div className="flex h-10 items-center justify-between">
<div className="min-w-[200px] w-auto flex items-center">
<a href={webuiPrefix} className="flex items-center gap-2">
<ZapIcon className="size-4 text-emerald-400" aria-hidden="true" />
@@ -93,8 +95,6 @@ export default function SiteHeader() {
</TooltipProvider>
</div>
)}
<span className="mx-2 text-xs text-gray-300 dark:text-gray-600">|</span>
<WorkspaceSelector />
</div>
<div className="flex h-10 flex-1 items-center justify-center">
@@ -132,6 +132,12 @@ export default function SiteHeader() {
)}
</div>
</nav>
</div>
{/* Second row: Workspace selector */}
<div className="flex items-center gap-2 py-1 border-t border-border/40">
<WorkspaceSelector />
</div>
</header>
)
}

View File

@@ -27,7 +27,10 @@
"namePlaceholder": "Workspace name",
"createDescription": "Create a new isolated workspace for your documents and indexes.",
"create": "Create",
"creating": "Creating..."
"creating": "Creating...",
"deleteTitle": "Delete Workspace",
"deleteConfirm": "Are you sure you want to delete workspace '{{workspace}}'?",
"deleteWarning": "This will permanently delete all data in this workspace and cannot be undone."
},
"login": {
"description": "Please enter your account and password to log in to the system",
@@ -47,7 +50,9 @@
"cancel": "Cancel",
"save": "Save",
"saving": "Saving...",
"saveFailed": "Save failed"
"saveFailed": "Save failed",
"delete": "Delete",
"deleting": "Deleting..."
},
"documentPanel": {
"clearDocuments": {

View File

@@ -9,6 +9,7 @@ os.environ['OLLAMA_EMBEDDING_MODEL'] = 'snowflake-arctic-embed:latest'
os.environ['OLLAMA_RERANKER_MODEL'] = 'jina-reranker:latest'
os.environ['OPENAI_API_MODEL'] = 'deepseek-chat'
os.environ['OPENAI_API_BASE'] = 'https://api.deepseek.com/v1'
os.environ['LLM_BINDING_HOST'] = 'https://api.deepseek.com/v1'
# Set database environment variables
os.environ['REDIS_URI'] = 'redis://localhost:6379'

69
auto_commit.bat Normal file
View File

@@ -0,0 +1,69 @@
@echo off
REM Auto-commit batch script for LightRAG project
REM Usage: auto_commit.bat "Commit message"
setlocal
REM Get commit message from command line or generate one
if "%1"=="" (
for /f "tokens=1-3 delims=/: " %%a in ('time /t') do set TIME=%%a%%b
for /f "tokens=1-3 delims=/- " %%a in ('date /t') do set DATE=%%a-%%b-%%c
set MESSAGE=Auto-commit: %DATE% %TIME%
) else (
set MESSAGE=%1
)
echo Auto-commit starting with message: %MESSAGE%
echo ============================================================
REM Step 1: Check git status
echo 1. Checking git status...
git status --porcelain
if %errorlevel% neq 0 (
echo Error checking git status
exit /b 1
)
REM Step 2: Add all changes
echo.
echo 2. Adding all changes...
git add -A
if %errorlevel% neq 0 (
echo Error adding changes
exit /b 1
)
echo Changes added.
REM Step 3: Commit
echo.
echo 3. Committing with message: '%MESSAGE%'
git commit -m "%MESSAGE%"
if %errorlevel% neq 0 (
echo Error committing
exit /b 1
)
echo Commit successful.
REM Step 4: Push to remote
echo.
echo 4. Pushing to remote repository...
git push origin master
if %errorlevel% neq 0 (
echo Error pushing, trying with credentials...
git push http://jleu3482:jleu1212@localhost:8467/jleu3482/railseek6.git master
if %errorlevel% neq 0 (
echo Push failed
exit /b 1
)
)
echo Push successful!
REM Step 5: Show git log
echo.
echo 5. Latest commit:
git log --oneline -3
echo.
echo ============================================================
echo Auto-commit completed successfully!
endlocal

6
check_auth.py Normal file
View File

@@ -0,0 +1,6 @@
import requests
import json
resp = requests.get("http://localhost:3015/auth-status")
print(resp.status_code)
print(resp.json())

16
check_doc_status.py Normal file
View File

@@ -0,0 +1,16 @@
import requests
import sys
workspace = "test2"
url = f"http://localhost:3015/documents?workspace={workspace}"
try:
resp = requests.get(url, timeout=10)
if resp.status_code == 200:
data = resp.json()
print(f"Documents in workspace '{workspace}':")
for doc in data:
print(f" - {doc.get('name')}: status={doc.get('status')}, processed={doc.get('processed')}, error={doc.get('error')}")
else:
print(f"Error: {resp.status_code} {resp.text}")
except Exception as e:
print(f"Request failed: {e}")

29
check_docs_after_clear.py Normal file
View File

@@ -0,0 +1,29 @@
import asyncio
import aiohttp
import json
async def get_documents(workspace):
url = "http://localhost:3015/documents"
headers = {
"X-API-Key": "jleu1212",
"X-Workspace": workspace,
"accept": "application/json",
}
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers) as resp:
print(f"Documents status: {resp.status}")
if resp.status == 200:
result = await resp.json()
print(json.dumps(result, indent=2))
else:
text = await resp.text()
print(f"Error: {text}")
return resp.status
async def main():
workspace = "test1"
print("Checking documents after clear...")
await get_documents(workspace)
if __name__ == "__main__":
asyncio.run(main())

7
check_lines.py Normal file
View File

@@ -0,0 +1,7 @@
import sys
with open('LightRAG-main/lightrag/operate.py', 'r', encoding='utf-8') as f:
lines = f.readlines()
for i in range(4100, 4200):
line = lines[i].rstrip()
if 'return_raw_data' in line or 'return None' in line or 'empty_raw_data' in line:
print(f'{i}: {line[:120]}')

47
create_workspace_ui.py Normal file
View File

@@ -0,0 +1,47 @@
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(5)
wait = WebDriverWait(driver, 10)
try:
driver.get('http://localhost:3015')
time.sleep(3)
# Find the plus button (create workspace)
plus_button = driver.find_element(By.CSS_SELECTOR, 'button[aria-haspopup="dialog"][aria-controls*="radix-"]')
plus_button.click()
time.sleep(1)
# Find dialog input
dialog_input = driver.find_element(By.CSS_SELECTOR, 'input[placeholder="Workspace name"]')
dialog_input.send_keys('test_workspace_ui')
# Find confirm button
confirm_button = driver.find_element(By.XPATH, '//button[text()="Create"]')
confirm_button.click()
time.sleep(2)
# Now workspace selector should have new workspace
combobox = driver.find_element(By.CSS_SELECTOR, '[role="combobox"]')
print('Current workspace:', combobox.text)
# Click combobox to open dropdown
combobox.click()
time.sleep(1)
# Wait for dropdown items
items = driver.find_elements(By.CSS_SELECTOR, '[role="option"]')
print(f'Number of options: {len(items)}')
for i, item in enumerate(items):
print(f'Option {i}:', item.text)
# Take screenshot
driver.save_screenshot('after_create.png')
except Exception as e:
print('Error:', e)
import traceback
traceback.print_exc()
finally:
driver.quit()

27
debug_retrieval.py Normal file
View File

@@ -0,0 +1,27 @@
import asyncio
import aiohttp
import json
async def test():
url = "http://localhost:3015/search"
headers = {
"Content-Type": "application/json",
"X-Workspace": ""
}
data = {
"query": "what is the minimum safe working distance",
"mode": "mix",
"return_raw_data": True
}
async with aiohttp.ClientSession() as session:
async with session.post(url, headers=headers, json=data) as resp:
print(f"Status: {resp.status}")
if resp.status == 200:
result = await resp.json()
print(json.dumps(result, indent=2))
else:
text = await resp.text()
print(f"Error: {text}")
if __name__ == "__main__":
asyncio.run(test())

28
debug_retrieval2.py Normal file
View File

@@ -0,0 +1,28 @@
import asyncio
import aiohttp
import json
async def test():
url = "http://localhost:3015/search"
headers = {
"Content-Type": "application/json",
"X-Workspace": "",
"X-API-Key": "test-key"
}
data = {
"query": "what is the minimum safe working distance",
"mode": "mix",
"return_raw_data": True
}
async with aiohttp.ClientSession() as session:
async with session.post(url, headers=headers, json=data) as resp:
print(f"Status: {resp.status}")
if resp.status == 200:
result = await resp.json()
print(json.dumps(result, indent=2))
else:
text = await resp.text()
print(f"Error: {text}")
if __name__ == "__main__":
asyncio.run(test())

60
debug_storage_lock.py Normal file
View File

@@ -0,0 +1,60 @@
import asyncio
import sys
sys.path.insert(0, 'LightRAG-main')
from lightrag.api.workspace_manager import WorkspaceManager
from lightrag.lightrag import LightRAG
from lightrag.kg.shared_storage import get_storage_lock, initialize_share_data
async def main():
# Ensure shared data is initialized (should be done by default workspace)
initialize_share_data()
print("Shared data initialized")
# Get workspace manager (singleton)
from lightrag.api.lightrag_server import workspace_manager
if workspace_manager is None:
print("Workspace manager not initialized, creating...")
from lightrag.api.workspace_manager import WorkspaceManager
workspace_manager = WorkspaceManager()
# Get RAG instance for workspace 'test'
rag = workspace_manager.get_rag('test')
print(f"RAG instance: {rag}")
print(f"RAG workspace: {rag.workspace}")
print(f"RAG storages status: {rag._storages_status}")
# Check doc_status storage
doc_status = rag.doc_status
print(f"doc_status type: {type(doc_status)}")
print(f"doc_status._storage_lock: {doc_status._storage_lock}")
# Check global storage lock
lock = get_storage_lock()
print(f"Global storage lock: {lock}")
print(f"Global storage lock._lock: {lock._lock if hasattr(lock, '_lock') else 'N/A'}")
# Initialize storages
if rag._storages_status != rag._storages_status.FINALIZED:
print("Initializing storages...")
await rag.initialize_storages()
print(f"After initialization, storages status: {rag._storages_status}")
print(f"doc_status._storage_lock after init: {doc_status._storage_lock}")
if doc_status._storage_lock is None:
print("ERROR: _storage_lock still None!")
else:
print("Lock seems okay")
else:
print("Storages already initialized")
# Try to call get_docs_paginated (should not raise error)
try:
result = await doc_status.get_docs_paginated(page=1, page_size=10)
print(f"get_docs_paginated succeeded: {len(result[0])} docs")
except Exception as e:
print(f"get_docs_paginated failed: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
asyncio.run(main())

BIN
dropdown_open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
dropdown_options.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

9
extract_early_return.py Normal file
View File

@@ -0,0 +1,9 @@
import sys
with open('LightRAG-main/lightrag/operate.py', 'r', encoding='utf-8') as f:
lines = f.readlines()
for i, line in enumerate(lines):
if 'if not search_result' in line and 'final_entities' in line:
print(f'Found at line {i+1}: {line.strip()}')
for j in range(max(0, i-2), min(len(lines), i+15)):
print(f'{j+1}: {lines[j].rstrip()}')
break

5
extract_section.py Normal file
View File

@@ -0,0 +1,5 @@
import sys
with open('LightRAG-main/lightrag/operate.py', 'r', encoding='utf-8') as f:
lines = f.readlines()
for i, line in enumerate(lines[4140:4223], start=4140):
print(f'{i}: {line}', end='')

9
find_func.py Normal file
View File

@@ -0,0 +1,9 @@
import sys
with open('LightRAG-main/lightrag/utils.py', 'r', encoding='utf-8') as f:
lines = f.readlines()
for i, line in enumerate(lines):
if '_convert_to_user_format' in line and 'def' in line:
print(i, line.strip())
# print next few lines
for j in range(i, min(i+10, len(lines))):
print(j, lines[j].rstrip())

9
find_line.py Normal file
View File

@@ -0,0 +1,9 @@
import sys
with open('LightRAG-main/lightrag/operate.py', 'r', encoding='utf-8') as f:
lines = f.readlines()
for i, line in enumerate(lines):
if 'not merged_chunks' in line and 'and not truncation_result' in line:
print(f'Found at line {i+1}: {line.strip()}')
# print surrounding lines
for j in range(max(0, i-5), min(len(lines), i+10)):
print(f'{j+1}: {lines[j].rstrip()}')

10
find_line2.py Normal file
View File

@@ -0,0 +1,10 @@
import sys
with open('LightRAG-main/lightrag/operate.py', 'r', encoding='utf-8') as f:
lines = f.readlines()
for i, line in enumerate(lines):
if 'not merged_chunks' in line:
print(f'Found at line {i+1}: {line.strip()}')
# print surrounding lines
for j in range(max(0, i-5), min(len(lines), i+10)):
print(f'{j+1}: {lines[j].rstrip()}')
break

36
find_selector.py Normal file
View File

@@ -0,0 +1,36 @@
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(5)
wait = WebDriverWait(driver, 10)
try:
driver.get('http://localhost:3015')
time.sleep(3) # let page load
# Find all elements with class containing 'Select'
elements = driver.find_elements(By.CSS_SELECTOR, '[class*="Select"]')
for elem in elements:
print(elem.tag_name, elem.get_attribute('class'), elem.get_attribute('id'), elem.text[:50])
# Find button with role combobox
combos = driver.find_elements(By.CSS_SELECTOR, '[role="combobox"]')
for c in combos:
print('Combobox:', c.tag_name, c.get_attribute('class'), c.text[:50])
# Find any element with text 'workspace' (case insensitive)
workspaces = driver.find_elements(By.XPATH, "//*[contains(translate(text(), 'WORKSPACE', 'workspace'), 'workspace')]")
for w in workspaces:
print('Workspace text:', w.tag_name, w.get_attribute('class'), w.text[:50])
# Take screenshot
driver.save_screenshot('page.png')
print('Screenshot saved')
except Exception as e:
print('Error:', e)
finally:
driver.quit()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,38 @@
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(5)
try:
driver.get('http://localhost:3015')
time.sleep(3)
# Find combobox button
combobox = driver.find_element(By.CSS_SELECTOR, '[role="combobox"].w-48')
print('Combobox found')
# Click to open dropdown
combobox.click()
time.sleep(1)
# Find the dropdown container (maybe with role="listbox")
dropdowns = driver.find_elements(By.CSS_SELECTOR, '[role="listbox"]')
print(f'Number of listboxes: {len(dropdowns)}')
for d in dropdowns:
print('Listbox outer HTML:', d.get_attribute('outerHTML'))
# Also look for any div with class containing 'SelectContent' or 'PopoverContent'
popovers = driver.find_elements(By.CSS_SELECTOR, '[data-state="open"]')
print(f'Open popovers: {len(popovers)}')
for p in popovers:
print('Popover outer HTML:', p.get_attribute('outerHTML'))
# Take screenshot
driver.save_screenshot('dropdown_open.png')
except Exception as e:
print('Error:', e)
import traceback
traceback.print_exc()
finally:
driver.quit()

16
inspect_ui.py Normal file
View File

@@ -0,0 +1,16 @@
import requests
from bs4 import BeautifulSoup
url = 'http://localhost:3015'
resp = requests.get(url)
print(resp.status_code)
if resp.status_code == 200:
soup = BeautifulSoup(resp.text, 'html.parser')
# Find all elements with class containing 'Select'
for tag in soup.find_all(class_=lambda c: c and 'Select' in c):
print(tag.name, tag.get('class'), tag.get('id'))
# Also find workspace selector
print('--- Workspace selector ---')
for tag in soup.find_all(['div', 'button', 'span']):
if 'workspace' in str(tag).lower():
print(tag.name, tag.get('class'), tag.get('id'), tag.text[:50])

Some files were not shown because too many files have changed in this diff Show More