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 # Authentication (Disabled)
HOST=0.0.0.0 # LIGHTRAG_API_KEY=jleu1212
PORT=3015 # AUTH_ACCOUNTS=jleu3482:jleu1212
WEBUI_TITLE='Search Anything Railway'
WEBUI_DESCRIPTION="Search Anything Railway!"
### Login Configuration (optional) # DeepSeek API Configuration
AUTH_ACCOUNTS='jleu3482:jleu1212' OPENAI_API_KEY=sk-55f6e57f1d834b0e93ceaf98cc2cb715
TOKEN_SECRET=lightrag-production-key-2024 OPENAI_BASE_URL=https://api.deepseek.com/v1
TOKEN_EXPIRE_HOURS=48 LLM_MODEL=deepseek-chat
### RAGAnything Configuration # Database Configuration
PARSE_METHOD=auto REDIS_URI=redis://localhost:6379
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
NEO4J_URI=bolt://localhost:7687 NEO4J_URI=bolt://localhost:7687
NEO4J_USERNAME=neo4j NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=jleu1212 NEO4J_PASSWORD=jleu1212
QDRANT_URI=http://localhost:6333/
POSTGRES_URI=postgresql://jleu3482:jleu1212@localhost:5432/rag_anything
### Qdrant Configuration # Embedding Configuration
QDRANT_URL=http://localhost:6333 OLLAMA_EMBEDDING_MODEL=snowflake-arctic-embed:latest
# QDRANT_API_KEY=your-api-key-if-needed OLLAMA_RERANKER_MODEL=jina-reranker:latest
EMBEDDING_BINDING_API_KEY=governor
### Redis Configuration OLLAMA_API_KEY=governor
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_BINDING_HOST=http://localhost:11434 EMBEDDING_BINDING_HOST=http://localhost:11434
EMBEDDING_BATCH_NUM=32 OLLAMA_HOST=http://localhost:11434
EMBEDDING_FUNC_MAX_ASYNC=16
### Reranker Configuration (jina-reranker-v2) # Performance Settings
RERANK_BINDING=jina PYTHONIOENCODING=utf-8
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

View File

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

View File

@@ -79,5 +79,12 @@ async def delete_workspace(
workspace_name: str, workspace_name: str,
workspace_manager: WorkspaceManager = Depends(get_workspace_manager), workspace_manager: WorkspaceManager = Depends(get_workspace_manager),
): ):
"""Delete a workspace (not implemented).""" """Delete a workspace."""
raise HTTPException(status_code=501, detail="Workspace deletion not yet implemented") 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 */ /* Font Awesome icon styling - consolidated */
.label-icon { .label-icon {
display: inline-block; 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 { .packetByte {
font-size: ${e.byteFontSize}; 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+`
`:p=`{ `:p=`{
`+A+` `+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}; `+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()+` `+_.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). 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()+` `+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()+` `+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). 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()+` `+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{ .pieCircle{
stroke: ${t.pieStrokeColor}; stroke: ${t.pieStrokeColor};
stroke-width : ${t.pieStrokeWidth}; 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()+` `+_.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). 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()+` `+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" /> <link rel="icon" type="image/png" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RailSeek</title> <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/react-vendor-DEwriMA6.js">
<link rel="modulepreload" crossorigin href="/webui/assets/ui-vendor-CeCm8EER.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/graph-vendor-B-X5JegA.js">
<link rel="modulepreload" crossorigin href="/webui/assets/utils-vendor-BysuhMZA.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-graph-Ce9OX-bo.js">
<link rel="modulepreload" crossorigin href="/webui/assets/feature-documents-Cz85jZmh.js"> <link rel="modulepreload" crossorigin href="/webui/assets/feature-documents-D0lvjDJ6.js">
<link rel="modulepreload" crossorigin href="/webui/assets/mermaid-vendor-C4V_MkUy.js"> <link rel="modulepreload" crossorigin href="/webui/assets/mermaid-vendor-GB05DkYd.js">
<link rel="modulepreload" crossorigin href="/webui/assets/markdown-vendor-DQBWdwkI.js"> <link rel="modulepreload" crossorigin href="/webui/assets/markdown-vendor-BiwnQtuo.js">
<link rel="modulepreload" crossorigin href="/webui/assets/feature-retrieval-24678VmD.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/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> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

@@ -5,6 +5,7 @@ Provides isolation between different workspaces by managing separate LightRAG in
import os import os
import logging import logging
import asyncio
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
from lightrag import LightRAG from lightrag import LightRAG
@@ -62,11 +63,54 @@ class WorkspaceManager:
logger.error(f"Failed to create workspace '{name}': {e}") logger.error(f"Failed to create workspace '{name}': {e}")
raise raise
def delete_workspace(self, name: str) -> bool: async def delete_workspace(self, name: str) -> bool:
"""Delete a workspace directory and all its data.""" """Delete a workspace directory and all its data."""
# TODO: implement deletion with caution (maybe require confirmation) import shutil
# For now, just raise NotImplementedError from pathlib import Path
raise NotImplementedError("Workspace deletion not yet implemented")
# 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: def get_rag(self, workspace: str = "") -> LightRAG:
"""Get or create a LightRAG instance for the given workspace.""" """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) sys.path.insert(0, workspace_dir)
from fast_image_classifier import get_image_classifier from fast_image_classifier import get_image_classifier
# Import optimized OCR processor
from .optimized_ocr_processor import OptimizedOCRProcessor
# Configure logging # Configure logging
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -377,9 +380,11 @@ class DocumentProcessor:
def __init__(self): def __init__(self):
self.config = get_config() self.config = get_config()
self.ocr_processor = OCRProcessor( self.ocr_processor = OptimizedOCRProcessor(
use_gpu=self.config.performance.USE_GPU, 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 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]: 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 Returns processed images metadata and additional content from OCR
""" """
processed_images = [] processed_images = []
additional_content = [] additional_content = []
temp_paths = []
temp_files = []
# Step 1: Save all images to temporary files
for i, image_data in enumerate(images): for i, image_data in enumerate(images):
temp_path = None temp_path = None
try: try:
@@ -461,24 +469,60 @@ class DocumentProcessor:
temp_file.write(image_bytes) temp_file.write(image_bytes)
temp_path = temp_file.name temp_path = temp_file.name
# Process image with OCR first, then classify only if no text found temp_paths.append(temp_path)
image_metadata = {"path": temp_path, "index": i} 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: if self.ocr_processor.ocr_available:
try: try:
logger.info(f"Running GPU OCR on image {i+1}") logger.info(f"Running batch OCR on {len(temp_paths)} images")
ocr_result = self.ocr_processor.extract_text_from_image(temp_path) batch_results = self.ocr_processor.extract_text_from_images_batch(temp_paths)
logger.info(f"OCR result for image {i+1}: {len(ocr_result['text'])} characters, confidence: {ocr_result['confidence']}") 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_text"] = ocr_result["text"]
image_metadata["ocr_confidence"] = ocr_result["confidence"] image_metadata["ocr_confidence"] = ocr_result["confidence"]
additional_content.append(f"[Image {i+1} OCR Text]: {ocr_result['text']}") additional_content.append(f"[Image {i+1} OCR Text]: {ocr_result['text']}")
logger.info(f"Image {i+1} has text content, skipping classification") logger.info(f"Image {i+1} has text content, skipping classification")
else: else:
logger.info(f"Image {i+1} has no text, proceeding to classification") 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: if self.image_classifier and self.image_classifier.available:
try: try:
classification_results = self.image_classifier.classify_image(temp_path, top_k=3) classification_results = self.image_classifier.classify_image(temp_path, top_k=3)
@@ -505,9 +549,6 @@ class DocumentProcessor:
except Exception as classify_error: except Exception as classify_error:
logger.error(f"Image classification failed for image {i+1}: {classify_error}") logger.error(f"Image classification failed for image {i+1}: {classify_error}")
image_metadata["classification_error"] = str(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) processed_images.append(image_metadata)
@@ -516,7 +557,7 @@ class DocumentProcessor:
processed_images.append({ processed_images.append({
"index": i, "index": i,
"error": str(e), "error": str(e),
"path": temp_path or "unknown" "path": temp_path
}) })
finally: finally:
# Clean up temporary file # Clean up temporary file

View File

@@ -2250,6 +2250,50 @@ class LightRAG:
except Exception as e: except Exception as e:
logger.error(f"Error while clearing cache: {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: def clear_cache(self) -> None:
"""Synchronous version of aclear_cache.""" """Synchronous version of aclear_cache."""
return always_get_an_event_loop().run_until_complete(self.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) host = kwargs.pop("host", None)
timeout = kwargs.pop("timeout", 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) ollama_client = ollama.AsyncClient(host=host, timeout=timeout, headers=headers)
try: try:
options = kwargs.pop("options", {}) options = kwargs.pop("options", {})

View File

@@ -4008,6 +4008,7 @@ async def _build_llm_context(
if not entities_context and not relations_context: if not entities_context and not relations_context:
if return_raw_data: if return_raw_data:
# Return empty raw data structure when no entities/relations # 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( empty_raw_data = _convert_to_user_format(
[], [],
[], [],
@@ -4122,11 +4123,33 @@ async def _build_query_context(
chunks_vdb, 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 not search_result["final_entities"] and not search_result["final_relations"]:
if query_param.mode != "mix": 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 return None
else: else:
if not search_result["chunk_tracking"]: 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 return None
# Stage 2: Apply token truncation for LLM efficiency # 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["entities_context"]
and not truncation_result["relations_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 return None
# Stage 4: Build final LLM context with dynamic token processing # 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) => { axiosInstance.interceptors.request.use((config) => {
const apiKey = useSettingsStore.getState().apiKey const apiKey = useSettingsStore.getState().apiKey
const token = localStorage.getItem('LIGHTRAG-API-TOKEN'); const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
const workspace = useSettingsStore.getState().workspace
// Always include token if it exists, regardless of path // Always include token if it exists, regardless of path
if (token) { if (token) {
@@ -275,6 +276,10 @@ axiosInstance.interceptors.request.use((config) => {
if (apiKey) { if (apiKey) {
config.headers['X-API-Key'] = apiKey config.headers['X-API-Key'] = apiKey
} }
// Add workspace header if workspace is selected
if (workspace) {
config.headers['X-Workspace'] = workspace
}
return config return config
}) })
@@ -360,6 +365,7 @@ export const queryTextStream = async (
) => { ) => {
const apiKey = useSettingsStore.getState().apiKey; const apiKey = useSettingsStore.getState().apiKey;
const token = localStorage.getItem('LIGHTRAG-API-TOKEN'); const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
const workspace = useSettingsStore.getState().workspace;
const headers: HeadersInit = { const headers: HeadersInit = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/x-ndjson', 'Accept': 'application/x-ndjson',
@@ -370,6 +376,9 @@ export const queryTextStream = async (
if (apiKey) { if (apiKey) {
headers['X-API-Key'] = apiKey; headers['X-API-Key'] = apiKey;
} }
if (workspace) {
headers['X-Workspace'] = workspace;
}
try { try {
const response = await fetch(`${backendBaseUrl}/query/stream`, { 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 }) const response = await axiosInstance.post('/workspaces/', { name })
return response.data 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 { useEffect, useState, ChangeEvent, KeyboardEvent } from 'react'
import { useSettingsStore } from '@/stores/settings' 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 Button from '@/components/ui/Button'
import Input from '@/components/ui/Input' import Input from '@/components/ui/Input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/Select' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/Select'
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter, DialogClose } from '@/components/ui/Dialog' 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' import { useTranslation } from 'react-i18next'
export function WorkspaceSelector() { export function WorkspaceSelector() {
@@ -18,6 +18,8 @@ export function WorkspaceSelector() {
const [search, setSearch] = useState('') const [search, setSearch] = useState('')
const [newWorkspaceName, setNewWorkspaceName] = useState('') const [newWorkspaceName, setNewWorkspaceName] = useState('')
const [creating, setCreating] = useState(false) const [creating, setCreating] = useState(false)
const [deleting, setDeleting] = useState(false)
const [showDeleteDialog, setShowDeleteDialog] = useState(false)
// Fetch workspaces on mount // Fetch workspaces on mount
useEffect(() => { 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 => const filteredWorkspaces = workspaceList.filter(name =>
name.toLowerCase().includes(search.toLowerCase()) name.toLowerCase().includes(search.toLowerCase())
) )
return ( return (
<div className="flex items-center gap-2"> <div className="flex flex-row items-center gap-2">
<Select <Select
value={workspace || ''} value={workspace || ''}
onValueChange={(value) => setWorkspace(value)} onValueChange={(value) => setWorkspace(value)}
@@ -95,6 +114,42 @@ export function WorkspaceSelector() {
</SelectContent> </SelectContent>
</Select> </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> <Dialog>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button size="icon" variant="outline"> <Button size="icon" variant="outline">
@@ -132,5 +187,6 @@ export function WorkspaceSelector() {
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</div> </div>
</div>
) )
} }

View File

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

View File

@@ -68,7 +68,9 @@ export default function SiteHeader() {
} }
return ( 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"> <div className="min-w-[200px] w-auto flex items-center">
<a href={webuiPrefix} className="flex items-center gap-2"> <a href={webuiPrefix} className="flex items-center gap-2">
<ZapIcon className="size-4 text-emerald-400" aria-hidden="true" /> <ZapIcon className="size-4 text-emerald-400" aria-hidden="true" />
@@ -93,8 +95,6 @@ export default function SiteHeader() {
</TooltipProvider> </TooltipProvider>
</div> </div>
)} )}
<span className="mx-2 text-xs text-gray-300 dark:text-gray-600">|</span>
<WorkspaceSelector />
</div> </div>
<div className="flex h-10 flex-1 items-center justify-center"> <div className="flex h-10 flex-1 items-center justify-center">
@@ -132,6 +132,12 @@ export default function SiteHeader() {
)} )}
</div> </div>
</nav> </nav>
</div>
{/* Second row: Workspace selector */}
<div className="flex items-center gap-2 py-1 border-t border-border/40">
<WorkspaceSelector />
</div>
</header> </header>
) )
} }

View File

@@ -27,7 +27,10 @@
"namePlaceholder": "Workspace name", "namePlaceholder": "Workspace name",
"createDescription": "Create a new isolated workspace for your documents and indexes.", "createDescription": "Create a new isolated workspace for your documents and indexes.",
"create": "Create", "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": { "login": {
"description": "Please enter your account and password to log in to the system", "description": "Please enter your account and password to log in to the system",
@@ -47,7 +50,9 @@
"cancel": "Cancel", "cancel": "Cancel",
"save": "Save", "save": "Save",
"saving": "Saving...", "saving": "Saving...",
"saveFailed": "Save failed" "saveFailed": "Save failed",
"delete": "Delete",
"deleting": "Deleting..."
}, },
"documentPanel": { "documentPanel": {
"clearDocuments": { "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['OLLAMA_RERANKER_MODEL'] = 'jina-reranker:latest'
os.environ['OPENAI_API_MODEL'] = 'deepseek-chat' os.environ['OPENAI_API_MODEL'] = 'deepseek-chat'
os.environ['OPENAI_API_BASE'] = 'https://api.deepseek.com/v1' os.environ['OPENAI_API_BASE'] = 'https://api.deepseek.com/v1'
os.environ['LLM_BINDING_HOST'] = 'https://api.deepseek.com/v1'
# Set database environment variables # Set database environment variables
os.environ['REDIS_URI'] = 'redis://localhost:6379' 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