OpenRAG 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openrag-0.2.2/src/openrag.egg-info → openrag-0.2.3}/PKG-INFO +1 -1
- {openrag-0.2.2 → openrag-0.2.3}/pyproject.toml +1 -1
- {openrag-0.2.2 → openrag-0.2.3}/src/api/settings.py +73 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/config/config_manager.py +43 -2
- {openrag-0.2.2 → openrag-0.2.3}/src/main.py +36 -18
- {openrag-0.2.2 → openrag-0.2.3/src/openrag.egg-info}/PKG-INFO +1 -1
- {openrag-0.2.2 → openrag-0.2.3}/LICENSE +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/MANIFEST.in +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/README.md +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/setup.cfg +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/agent.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/auth.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/chat.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/connector_router.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/connectors.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/docling.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/documents.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/flows.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/keys.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/knowledge_filter.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/langflow_files.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/models.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/nudges.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/oidc.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/provider_health.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/provider_validation.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/router.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/search.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/tasks.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/upload.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/v1/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/v1/chat.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/v1/documents.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/v1/knowledge_filters.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/v1/search.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api/v1/settings.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/api_key_middleware.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/auth_context.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/auth_middleware.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/config/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/config/settings.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/base.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/connection_manager.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/google_drive/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/google_drive/connector.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/google_drive/oauth.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/langflow_connector_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/onedrive/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/onedrive/connector.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/onedrive/oauth.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/sharepoint/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/sharepoint/connector.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/connectors/sharepoint/oauth.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/models/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/models/processors.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/models/tasks.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/openrag.egg-info/SOURCES.txt +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/openrag.egg-info/dependency_links.txt +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/openrag.egg-info/entry_points.txt +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/openrag.egg-info/requires.txt +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/openrag.egg-info/top_level.txt +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/api_key_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/auth_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/chat_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/conversation_persistence_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/document_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/flows_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/knowledge_filter_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/langflow_file_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/langflow_history_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/langflow_mcp_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/models_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/monitor_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/search_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/session_ownership_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/services/task_service.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/session_manager.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/docker-compose.gpu.yml +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/docker-compose.yml +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/components/ollama_embedding.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/components/ollama_llm.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/components/ollama_llm_text.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/components/watsonx_embedding.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/components/watsonx_llm.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/components/watsonx_llm_text.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/ingestion_flow.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/openrag_agent.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/openrag_nudges.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/flows/openrag_url_mcp.json +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/openrag-documents/docling.pdf +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/openrag-documents/ibm_anthropic.pdf +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/openrag-documents/openrag-documentation.pdf +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/_assets/openrag-documents/warmup_ocr.pdf +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/main.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/managers/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/managers/container_manager.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/managers/docling_manager.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/managers/env_manager.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/screens/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/screens/config.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/screens/diagnostics.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/screens/logs.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/screens/monitor.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/screens/welcome.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/utils/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/utils/clipboard.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/utils/platform.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/utils/validation.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/utils/version_check.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/command_modal.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/diagnostics_notification.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/error_notification.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/factory_reset_warning_modal.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/flow_backup_warning_modal.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/prune_options_modal.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/upgrade_instructions_modal.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/version_mismatch_warning_modal.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/tui/widgets/waves.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/container_utils.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/document_processing.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/embedding_fields.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/embeddings.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/file_utils.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/gpu_detection.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/hash_utils.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/langflow_headers.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/logging_config.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/opensearch_queries.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/paths.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/process_pool.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/telemetry/__init__.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/telemetry/category.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/telemetry/client.py +0 -0
- {openrag-0.2.2 → openrag-0.2.3}/src/utils/telemetry/message_id.py +0 -0
|
@@ -65,6 +65,16 @@ async def get_settings(request, session_manager):
|
|
|
65
65
|
"ingest_flow_id": LANGFLOW_INGEST_FLOW_ID,
|
|
66
66
|
"langflow_public_url": LANGFLOW_PUBLIC_URL,
|
|
67
67
|
"edited": openrag_config.edited,
|
|
68
|
+
# Onboarding state
|
|
69
|
+
"onboarding": {
|
|
70
|
+
"current_step": openrag_config.onboarding.current_step,
|
|
71
|
+
"assistant_message": openrag_config.onboarding.assistant_message,
|
|
72
|
+
"selected_nudge": openrag_config.onboarding.selected_nudge,
|
|
73
|
+
"card_steps": openrag_config.onboarding.card_steps,
|
|
74
|
+
"upload_steps": openrag_config.onboarding.upload_steps,
|
|
75
|
+
"openrag_docs_filter_id": openrag_config.onboarding.openrag_docs_filter_id,
|
|
76
|
+
"user_doc_filter_id": openrag_config.onboarding.user_doc_filter_id,
|
|
77
|
+
},
|
|
68
78
|
# OpenRAG configuration
|
|
69
79
|
"providers": {
|
|
70
80
|
"openai": {
|
|
@@ -1087,6 +1097,10 @@ async def onboarding(request, flows_service, session_manager=None):
|
|
|
1087
1097
|
"Created OpenRAG Docs knowledge filter",
|
|
1088
1098
|
filter_id=openrag_docs_filter_id,
|
|
1089
1099
|
)
|
|
1100
|
+
# Save the filter ID to the config
|
|
1101
|
+
current_config.onboarding.openrag_docs_filter_id = openrag_docs_filter_id
|
|
1102
|
+
if not config_manager.save_config_file(current_config):
|
|
1103
|
+
logger.error("Failed to save openrag_docs_filter_id to config")
|
|
1090
1104
|
except Exception as e:
|
|
1091
1105
|
logger.error(
|
|
1092
1106
|
"Failed to create OpenRAG Docs knowledge filter", error=str(e)
|
|
@@ -1353,6 +1367,65 @@ async def _update_langflow_chunk_settings(config, flows_service):
|
|
|
1353
1367
|
raise
|
|
1354
1368
|
|
|
1355
1369
|
|
|
1370
|
+
async def update_onboarding_state(request):
|
|
1371
|
+
"""Update onboarding state in configuration"""
|
|
1372
|
+
try:
|
|
1373
|
+
await TelemetryClient.send_event(Category.ONBOARDING, MessageId.ORB_ONBOARD_START)
|
|
1374
|
+
|
|
1375
|
+
# Parse request body
|
|
1376
|
+
body = await request.json()
|
|
1377
|
+
|
|
1378
|
+
# Validate allowed fields
|
|
1379
|
+
allowed_fields = {
|
|
1380
|
+
"current_step",
|
|
1381
|
+
"assistant_message",
|
|
1382
|
+
"selected_nudge",
|
|
1383
|
+
"card_steps",
|
|
1384
|
+
"upload_steps",
|
|
1385
|
+
"openrag_docs_filter_id",
|
|
1386
|
+
"user_doc_filter_id",
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
# Check for invalid fields
|
|
1390
|
+
invalid_fields = set(body.keys()) - allowed_fields
|
|
1391
|
+
if invalid_fields:
|
|
1392
|
+
return JSONResponse(
|
|
1393
|
+
{
|
|
1394
|
+
"error": f"Invalid fields: {', '.join(invalid_fields)}. Allowed fields: {', '.join(allowed_fields)}"
|
|
1395
|
+
},
|
|
1396
|
+
status_code=400,
|
|
1397
|
+
)
|
|
1398
|
+
|
|
1399
|
+
# Update onboarding state using config manager
|
|
1400
|
+
success = config_manager.update_onboarding_state(**body)
|
|
1401
|
+
|
|
1402
|
+
if not success:
|
|
1403
|
+
return JSONResponse(
|
|
1404
|
+
{"error": "Failed to update onboarding state"},
|
|
1405
|
+
status_code=500,
|
|
1406
|
+
)
|
|
1407
|
+
|
|
1408
|
+
logger.info(f"Onboarding state updated: {body}")
|
|
1409
|
+
|
|
1410
|
+
return JSONResponse(
|
|
1411
|
+
{
|
|
1412
|
+
"message": "Onboarding state updated successfully",
|
|
1413
|
+
"updated_fields": list(body.keys()),
|
|
1414
|
+
}
|
|
1415
|
+
)
|
|
1416
|
+
|
|
1417
|
+
except json.JSONDecodeError:
|
|
1418
|
+
return JSONResponse(
|
|
1419
|
+
{"error": "Invalid JSON in request body"}, status_code=400
|
|
1420
|
+
)
|
|
1421
|
+
except Exception as e:
|
|
1422
|
+
logger.error(f"Error updating onboarding state: {str(e)}")
|
|
1423
|
+
return JSONResponse(
|
|
1424
|
+
{"error": f"Failed to update onboarding state: {str(e)}"},
|
|
1425
|
+
status_code=500,
|
|
1426
|
+
)
|
|
1427
|
+
|
|
1428
|
+
|
|
1356
1429
|
async def reapply_all_settings(session_manager = None):
|
|
1357
1430
|
"""
|
|
1358
1431
|
Reapply all current configuration settings to Langflow flows and global variables.
|
|
@@ -4,7 +4,7 @@ import os
|
|
|
4
4
|
import yaml
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Dict, Any, Optional
|
|
7
|
-
from dataclasses import dataclass, asdict
|
|
7
|
+
from dataclasses import dataclass, asdict, field
|
|
8
8
|
from utils.logging_config import get_logger
|
|
9
9
|
|
|
10
10
|
logger = get_logger(__name__)
|
|
@@ -85,6 +85,19 @@ class AgentConfig:
|
|
|
85
85
|
system_prompt: str = "You are the OpenRAG Agent. You answer questions using retrieval, reasoning, and tool use.\nYou have access to several tools. Your job is to determine **which tool to use and when**.\n### Available Tools\n- OpenSearch Retrieval Tool:\n Use this to search the indexed knowledge base. Use when the user asks about product details, internal concepts, processes, architecture, documentation, roadmaps, or anything that may be stored in the index.\n- Conversation History:\n Use this to maintain continuity when the user is referring to previous turns. \n Do not treat history as a factual source.\n- Conversation File Context:\n Use this when the user asks about a document they uploaded or refers directly to its contents.\n- URL Ingestion Tool:\n Use this **only** when the user explicitly asks you to read, summarize, or analyze the content of a URL.\n Do not ingest URLs automatically.\n- Calculator / Expression Evaluation Tool:\n Use this when the user asks to compare numbers, compute estimates, calculate totals, analyze pricing, or answer any question requiring mathematics or quantitative reasoning.\n If the answer requires arithmetic, call the calculator tool rather than calculating internally.\n### Retrieval Decision Rules\nUse OpenSearch **whenever**:\n1. The question may be answered from internal or indexed data.\n2. The user references team names, product names, release plans, configurations, requirements, or official information.\n3. The user needs a factual, grounded answer.\nDo **not** use retrieval if:\n- The question is purely creative (e.g., storytelling, analogies) or personal preference.\n- The user simply wants text reformatted or rewritten from what is already present in the conversation.\nWhen uncertain → **Retrieve.** Retrieval is low risk and improves grounding.\n### URL Ingestion Rules\nOnly ingest URLs when the user explicitly says:\n- \"Read this link\"\n- \"Summarize this webpage\"\n- \"What does this site say?\"\n- \"Ingest this URL\"\nIf unclear → ask a clarifying question.\n### Calculator Usage Rules\nUse the calculator when:\n- Performing arithmetic\n- Estimating totals\n- Comparing values\n- Modeling cost, time, effort, scale, or projections\nDo not perform math internally. **Call the calculator tool instead.**\n### Answer Construction Rules\n1. When asked: \"What is OpenRAG\", answer the following:\n\"OpenRAG is an open-source package for building agentic RAG systems. It supports integration with a wide range of orchestration tools, vector databases, and LLM providers. OpenRAG connects and amplifies three popular, proven open-source projects into one powerful platform:\n**Langflow** – Langflow is a powerful tool to build and deploy AI agents and MCP servers [Read more](https://www.langflow.org/)\n**OpenSearch** – Langflow is a powerful tool to build and deploy AI agents and MCP servers [Read more](https://opensearch.org/)\n**Docling** – Langflow is a powerful tool to build and deploy AI agents and MCP servers [Read more](https://www.docling.ai/)\"\n2. Synthesize retrieved or ingested content in your own words.\n3. Support factual claims with citations in the format:\n (Source: <document_name_or_id>)\n4. If no supporting evidence is found:\n Say: \"No relevant supporting sources were found for that request.\"\n5. Never invent facts or hallucinate details.\n6. Be concise, direct, and confident. \n7. Do not reveal internal chain-of-thought."
|
|
86
86
|
|
|
87
87
|
|
|
88
|
+
@dataclass
|
|
89
|
+
class OnboardingState:
|
|
90
|
+
"""Onboarding state configuration."""
|
|
91
|
+
|
|
92
|
+
current_step: int = 0
|
|
93
|
+
assistant_message: Optional[Dict[str, Any]] = field(default=None)
|
|
94
|
+
selected_nudge: Optional[str] = field(default=None)
|
|
95
|
+
card_steps: Optional[Dict[str, Any]] = field(default=None)
|
|
96
|
+
upload_steps: Optional[Dict[str, Any]] = field(default=None)
|
|
97
|
+
openrag_docs_filter_id: Optional[str] = field(default=None)
|
|
98
|
+
user_doc_filter_id: Optional[str] = field(default=None)
|
|
99
|
+
|
|
100
|
+
|
|
88
101
|
@dataclass
|
|
89
102
|
class OpenRAGConfig:
|
|
90
103
|
"""Complete OpenRAG configuration."""
|
|
@@ -92,6 +105,7 @@ class OpenRAGConfig:
|
|
|
92
105
|
providers: ProvidersConfig
|
|
93
106
|
knowledge: KnowledgeConfig
|
|
94
107
|
agent: AgentConfig
|
|
108
|
+
onboarding: OnboardingState
|
|
95
109
|
edited: bool = False # Track if manually edited
|
|
96
110
|
|
|
97
111
|
@classmethod
|
|
@@ -107,6 +121,7 @@ class OpenRAGConfig:
|
|
|
107
121
|
),
|
|
108
122
|
knowledge=KnowledgeConfig(**data.get("knowledge", {})),
|
|
109
123
|
agent=AgentConfig(**data.get("agent", {})),
|
|
124
|
+
onboarding=OnboardingState(**data.get("onboarding", {})),
|
|
110
125
|
edited=data.get("edited", False),
|
|
111
126
|
)
|
|
112
127
|
|
|
@@ -156,6 +171,7 @@ class ConfigManager:
|
|
|
156
171
|
},
|
|
157
172
|
"knowledge": {},
|
|
158
173
|
"agent": {},
|
|
174
|
+
"onboarding": {},
|
|
159
175
|
}
|
|
160
176
|
|
|
161
177
|
# Load from config file if it exists
|
|
@@ -172,7 +188,7 @@ class ConfigManager:
|
|
|
172
188
|
file_config["providers"][provider]
|
|
173
189
|
)
|
|
174
190
|
|
|
175
|
-
for section in ["knowledge", "agent"]:
|
|
191
|
+
for section in ["knowledge", "agent", "onboarding"]:
|
|
176
192
|
if section in file_config:
|
|
177
193
|
config_data[section].update(file_config[section])
|
|
178
194
|
|
|
@@ -294,6 +310,31 @@ class ConfigManager:
|
|
|
294
310
|
logger.error(f"Failed to save configuration to {self.config_file}: {e}")
|
|
295
311
|
return False
|
|
296
312
|
|
|
313
|
+
def update_onboarding_state(self, **kwargs) -> bool:
|
|
314
|
+
"""Update onboarding state fields.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
**kwargs: Onboarding state fields to update (current_step, assistant_message, etc.)
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
True if updated successfully, False otherwise.
|
|
321
|
+
"""
|
|
322
|
+
try:
|
|
323
|
+
config = self.get_config()
|
|
324
|
+
|
|
325
|
+
# Update only the provided fields
|
|
326
|
+
for key, value in kwargs.items():
|
|
327
|
+
if hasattr(config.onboarding, key):
|
|
328
|
+
setattr(config.onboarding, key, value)
|
|
329
|
+
else:
|
|
330
|
+
logger.warning(f"Unknown onboarding field: {key}")
|
|
331
|
+
|
|
332
|
+
# Save the updated config
|
|
333
|
+
return self.save_config_file(config)
|
|
334
|
+
except Exception as e:
|
|
335
|
+
logger.error(f"Failed to update onboarding state: {e}")
|
|
336
|
+
return False
|
|
337
|
+
|
|
297
338
|
|
|
298
339
|
# Global config manager instance
|
|
299
340
|
config_manager = ConfigManager()
|
|
@@ -108,7 +108,7 @@ async def wait_for_opensearch():
|
|
|
108
108
|
|
|
109
109
|
for attempt in range(max_retries):
|
|
110
110
|
try:
|
|
111
|
-
await clients.opensearch.
|
|
111
|
+
await clients.opensearch.ping()
|
|
112
112
|
logger.info("OpenSearch is ready")
|
|
113
113
|
await TelemetryClient.send_event(Category.OPENSEARCH_SETUP, MessageId.ORB_OS_CONN_ESTABLISHED)
|
|
114
114
|
return
|
|
@@ -384,7 +384,7 @@ async def ingest_default_documents_when_ready(services):
|
|
|
384
384
|
await _ingest_default_documents_openrag(services, file_paths)
|
|
385
385
|
else:
|
|
386
386
|
await _ingest_default_documents_langflow(services, file_paths)
|
|
387
|
-
|
|
387
|
+
|
|
388
388
|
await TelemetryClient.send_event(Category.DOCUMENT_INGESTION, MessageId.ORB_DOC_DEFAULT_COMPLETE)
|
|
389
389
|
|
|
390
390
|
except Exception as e:
|
|
@@ -457,6 +457,11 @@ async def _ingest_default_documents_langflow(services, file_paths):
|
|
|
457
457
|
file_count=len(file_paths),
|
|
458
458
|
)
|
|
459
459
|
|
|
460
|
+
async def health_check(request):
|
|
461
|
+
"""Simple liveness probe: Indicates that the OpenRAG Backend service is online and running."""
|
|
462
|
+
return JSONResponse({"status": "ok"}, status_code=200)
|
|
463
|
+
|
|
464
|
+
|
|
460
465
|
async def opensearch_health_ready(request):
|
|
461
466
|
"""Readiness probe: verifies OpenSearch dependency is reachable."""
|
|
462
467
|
try:
|
|
@@ -507,48 +512,48 @@ async def _ingest_default_documents_openrag(services, file_paths):
|
|
|
507
512
|
|
|
508
513
|
async def _update_mcp_servers_with_provider_credentials(services):
|
|
509
514
|
"""Update MCP servers with provider credentials at startup.
|
|
510
|
-
|
|
515
|
+
|
|
511
516
|
This is especially important for no-auth mode where users don't go through
|
|
512
517
|
the OAuth login flow that would normally set these credentials.
|
|
513
518
|
"""
|
|
514
519
|
try:
|
|
515
520
|
auth_service = services.get("auth_service")
|
|
516
521
|
session_manager = services.get("session_manager")
|
|
517
|
-
|
|
522
|
+
|
|
518
523
|
if not auth_service or not auth_service.langflow_mcp_service:
|
|
519
524
|
logger.debug("MCP service not available, skipping credential update")
|
|
520
525
|
return
|
|
521
|
-
|
|
526
|
+
|
|
522
527
|
config = get_openrag_config()
|
|
523
|
-
|
|
528
|
+
|
|
524
529
|
# Build global vars with provider credentials using utility function
|
|
525
530
|
from utils.langflow_headers import build_mcp_global_vars_from_config
|
|
526
|
-
|
|
531
|
+
|
|
527
532
|
global_vars = build_mcp_global_vars_from_config(config)
|
|
528
|
-
|
|
533
|
+
|
|
529
534
|
# In no-auth mode, add the anonymous JWT token and user details
|
|
530
535
|
if is_no_auth_mode() and session_manager:
|
|
531
536
|
from session_manager import AnonymousUser
|
|
532
|
-
|
|
537
|
+
|
|
533
538
|
# Create/get anonymous JWT for no-auth mode
|
|
534
539
|
anonymous_jwt = session_manager.get_effective_jwt_token(None, None)
|
|
535
540
|
if anonymous_jwt:
|
|
536
541
|
global_vars["JWT"] = anonymous_jwt
|
|
537
|
-
|
|
542
|
+
|
|
538
543
|
# Add anonymous user details
|
|
539
544
|
anonymous_user = AnonymousUser()
|
|
540
545
|
global_vars["OWNER"] = anonymous_user.user_id # "anonymous"
|
|
541
546
|
global_vars["OWNER_NAME"] = f'"{anonymous_user.name}"' # "Anonymous User" (quoted for spaces)
|
|
542
547
|
global_vars["OWNER_EMAIL"] = anonymous_user.email # "anonymous@localhost"
|
|
543
|
-
|
|
548
|
+
|
|
544
549
|
logger.info("Added anonymous JWT and user details to MCP servers for no-auth mode")
|
|
545
|
-
|
|
550
|
+
|
|
546
551
|
if global_vars:
|
|
547
552
|
result = await auth_service.langflow_mcp_service.update_mcp_servers_with_global_vars(global_vars)
|
|
548
553
|
logger.info("Updated MCP servers with provider credentials at startup", **result)
|
|
549
554
|
else:
|
|
550
555
|
logger.debug("No provider credentials configured, skipping MCP server update")
|
|
551
|
-
|
|
556
|
+
|
|
552
557
|
except Exception as e:
|
|
553
558
|
logger.warning("Failed to update MCP servers with provider credentials at startup", error=str(e))
|
|
554
559
|
# Don't fail startup if MCP update fails
|
|
@@ -567,7 +572,7 @@ async def startup_tasks(services):
|
|
|
567
572
|
|
|
568
573
|
# Configure alerting security
|
|
569
574
|
await configure_alerting_security()
|
|
570
|
-
|
|
575
|
+
|
|
571
576
|
# Update MCP servers with provider credentials (especially important for no-auth mode)
|
|
572
577
|
await _update_mcp_servers_with_provider_credentials(services)
|
|
573
578
|
|
|
@@ -578,7 +583,7 @@ async def startup_tasks(services):
|
|
|
578
583
|
logger.info("Checking if Langflow flows were reset")
|
|
579
584
|
flows_service = services["flows_service"]
|
|
580
585
|
reset_flows = await flows_service.check_flows_reset()
|
|
581
|
-
|
|
586
|
+
|
|
582
587
|
if reset_flows:
|
|
583
588
|
logger.info(
|
|
584
589
|
f"Detected reset flows: {', '.join(reset_flows)}. Reapplying all settings."
|
|
@@ -676,7 +681,7 @@ async def initialize_services():
|
|
|
676
681
|
await TelemetryClient.send_event(Category.CONNECTOR_OPERATIONS, MessageId.ORB_CONN_LOAD_FAILED)
|
|
677
682
|
else:
|
|
678
683
|
logger.info("[CONNECTORS] Skipping connection loading in no-auth mode")
|
|
679
|
-
|
|
684
|
+
|
|
680
685
|
await TelemetryClient.send_event(Category.SERVICE_INITIALIZATION, MessageId.ORB_SVC_INIT_SUCCESS)
|
|
681
686
|
|
|
682
687
|
langflow_file_service = LangflowFileService()
|
|
@@ -1159,6 +1164,13 @@ async def create_app():
|
|
|
1159
1164
|
),
|
|
1160
1165
|
methods=["POST"],
|
|
1161
1166
|
),
|
|
1167
|
+
Route(
|
|
1168
|
+
"/onboarding/state",
|
|
1169
|
+
require_auth(services["session_manager"])(
|
|
1170
|
+
settings.update_onboarding_state
|
|
1171
|
+
),
|
|
1172
|
+
methods=["POST"],
|
|
1173
|
+
),
|
|
1162
1174
|
# Provider health check endpoint
|
|
1163
1175
|
Route(
|
|
1164
1176
|
"/provider/health",
|
|
@@ -1167,6 +1179,12 @@ async def create_app():
|
|
|
1167
1179
|
),
|
|
1168
1180
|
methods=["GET"],
|
|
1169
1181
|
),
|
|
1182
|
+
# Health check endpoints
|
|
1183
|
+
Route(
|
|
1184
|
+
"/health",
|
|
1185
|
+
health_check,
|
|
1186
|
+
methods=["GET"],
|
|
1187
|
+
),
|
|
1170
1188
|
Route(
|
|
1171
1189
|
"/search/health",
|
|
1172
1190
|
opensearch_health_ready,
|
|
@@ -1523,13 +1541,13 @@ async def create_app():
|
|
|
1523
1541
|
while True:
|
|
1524
1542
|
try:
|
|
1525
1543
|
await asyncio.sleep(5 * 60) # Wait 5 minutes
|
|
1526
|
-
|
|
1544
|
+
|
|
1527
1545
|
# Check if onboarding has been completed
|
|
1528
1546
|
config = get_openrag_config()
|
|
1529
1547
|
if not config.edited:
|
|
1530
1548
|
logger.debug("Onboarding not completed yet, skipping periodic backup")
|
|
1531
1549
|
continue
|
|
1532
|
-
|
|
1550
|
+
|
|
1533
1551
|
flows_service = services.get("flows_service")
|
|
1534
1552
|
if flows_service:
|
|
1535
1553
|
logger.info("Running periodic flow backup")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|