OpenRAG 0.2.0__tar.gz → 0.2.1__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.0/src/openrag.egg-info → openrag-0.2.1}/PKG-INFO +10 -58
- openrag-0.2.1/README.md +34 -0
- {openrag-0.2.0 → openrag-0.2.1}/pyproject.toml +1 -1
- {openrag-0.2.0 → openrag-0.2.1}/src/api/docling.py +10 -3
- {openrag-0.2.0 → openrag-0.2.1}/src/api/keys.py +13 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/knowledge_filter.py +57 -2
- {openrag-0.2.0 → openrag-0.2.1}/src/api/oidc.py +11 -1
- {openrag-0.2.0 → openrag-0.2.1}/src/main.py +24 -0
- {openrag-0.2.0 → openrag-0.2.1/src/openrag.egg-info}/PKG-INFO +10 -58
- {openrag-0.2.0 → openrag-0.2.1}/src/services/models_service.py +0 -6
- {openrag-0.2.0 → openrag-0.2.1}/src/session_manager.py +40 -6
- openrag-0.2.1/src/tui/_assets/docker-compose.gpu.yml +12 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/docker-compose.yml +2 -2
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/main.py +51 -1
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/managers/docling_manager.py +3 -3
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/flow_backup_warning_modal.py +5 -3
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/version_mismatch_warning_modal.py +2 -1
- openrag-0.2.0/README.md +0 -82
- openrag-0.2.0/src/tui/_assets/docker-compose.gpu.yml +0 -7
- {openrag-0.2.0 → openrag-0.2.1}/LICENSE +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/MANIFEST.in +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/setup.cfg +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/agent.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/auth.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/chat.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/connector_router.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/connectors.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/documents.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/flows.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/langflow_files.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/models.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/nudges.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/provider_health.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/provider_validation.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/router.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/search.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/settings.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/tasks.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/upload.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/v1/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/v1/chat.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/v1/documents.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/v1/knowledge_filters.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/v1/search.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api/v1/settings.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/api_key_middleware.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/auth_context.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/auth_middleware.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/config/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/config/config_manager.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/config/settings.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/base.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/connection_manager.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/google_drive/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/google_drive/connector.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/google_drive/oauth.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/langflow_connector_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/onedrive/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/onedrive/connector.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/onedrive/oauth.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/sharepoint/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/sharepoint/connector.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/connectors/sharepoint/oauth.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/models/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/models/processors.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/models/tasks.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/openrag.egg-info/SOURCES.txt +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/openrag.egg-info/dependency_links.txt +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/openrag.egg-info/entry_points.txt +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/openrag.egg-info/requires.txt +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/openrag.egg-info/top_level.txt +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/api_key_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/auth_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/chat_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/conversation_persistence_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/document_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/flows_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/knowledge_filter_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/langflow_file_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/langflow_history_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/langflow_mcp_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/monitor_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/search_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/session_ownership_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/services/task_service.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/components/ollama_embedding.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/components/ollama_llm.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/components/ollama_llm_text.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/components/watsonx_embedding.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/components/watsonx_llm.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/components/watsonx_llm_text.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/ingestion_flow.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/openrag_agent.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/openrag_nudges.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/flows/openrag_url_mcp.json +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/openrag-documents/docling.pdf +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/openrag-documents/ibm_anthropic.pdf +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/openrag-documents/openrag-documentation.pdf +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/_assets/openrag-documents/warmup_ocr.pdf +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/managers/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/managers/container_manager.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/managers/env_manager.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/screens/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/screens/config.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/screens/diagnostics.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/screens/logs.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/screens/monitor.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/screens/welcome.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/utils/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/utils/clipboard.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/utils/platform.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/utils/validation.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/utils/version_check.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/command_modal.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/diagnostics_notification.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/error_notification.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/factory_reset_warning_modal.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/prune_options_modal.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/upgrade_instructions_modal.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/tui/widgets/waves.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/container_utils.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/document_processing.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/embedding_fields.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/embeddings.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/file_utils.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/gpu_detection.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/hash_utils.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/langflow_headers.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/logging_config.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/opensearch_queries.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/paths.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/process_pool.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/telemetry/__init__.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/telemetry/category.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/telemetry/client.py +0 -0
- {openrag-0.2.0 → openrag-0.2.1}/src/utils/telemetry/message_id.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrag
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.13
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -51,68 +51,20 @@ OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables
|
|
|
51
51
|
|
|
52
52
|
<a href="https://deepwiki.com/langflow-ai/openrag"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
<div align="center">
|
|
56
|
-
<a href="#quickstart" style="color: #0366d6;">Quickstart</a> |
|
|
57
|
-
<a href="#install-python-package" style="color: #0366d6;">Python package</a> |
|
|
58
|
-
<a href="#docker-or-podman-installation" style="color: #0366d6;">Docker or Podman</a> |
|
|
59
|
-
<a href="#development" style="color: #0366d6;">Development</a> |
|
|
60
|
-
<a href="#troubleshooting" style="color: #0366d6;">Troubleshooting</a>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
## Quickstart
|
|
64
|
-
|
|
65
|
-
To run OpenRAG without creating or modifying any project files, use `uvx`:
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
uvx openrag
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
This command runs OpenRAG without installing it to your project or globally.
|
|
72
|
-
|
|
73
|
-
To run a specific version of OpenRAG, run `uvx --from openrag==VERSION openrag`.
|
|
74
|
-
|
|
75
|
-
## Install Python package
|
|
76
|
-
|
|
77
|
-
To add the OpenRAG Python package to a Python project, use `uv`:
|
|
78
|
-
|
|
79
|
-
1. Create a new project with a virtual environment using `uv init`:
|
|
54
|
+
## Install OpenRAG
|
|
80
55
|
|
|
81
|
-
|
|
82
|
-
uv init YOUR_PROJECT_NAME
|
|
83
|
-
cd YOUR_PROJECT_NAME
|
|
84
|
-
```
|
|
56
|
+
To get started with OpenRAG, see the installation guides in the OpenRAG documentation:
|
|
85
57
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
2. Add OpenRAG to your project:
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
uv add openrag
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
To add a specific version of OpenRAG, run `uv add openrag==VERSION`.
|
|
96
|
-
|
|
97
|
-
3. Start the OpenRAG terminal user interface (TUI):
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
uv run openrag
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
4. Continue with the [Quickstart](https://docs.openr.ag/quickstart).
|
|
104
|
-
|
|
105
|
-
For all installation options, see the [OpenRAG installation guide](https://docs.openr.ag/install).
|
|
106
|
-
|
|
107
|
-
## Docker or Podman installation
|
|
108
|
-
|
|
109
|
-
By default, OpenRAG automatically starts the required containers and helps you manage them.
|
|
110
|
-
To install OpenRAG with self-managed containers, see the [OpenRAG installation guide](https://docs.openr.ag/docker).
|
|
58
|
+
* [Quickstart](https://docs.openr.ag/quickstart)
|
|
59
|
+
* [Install the OpenRAG Python package](https://docs.openr.ag/install-options)
|
|
60
|
+
* [Deploy self-managed services with Docker or Podman](https://docs.openr.ag/docker)
|
|
111
61
|
|
|
112
62
|
## Development
|
|
113
63
|
|
|
114
|
-
For developers
|
|
64
|
+
For developers who want to [contribute to OpenRAG](https://docs.openr.ag/support/contribute) or set up a development environment, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
115
65
|
|
|
116
66
|
## Troubleshooting
|
|
117
67
|
|
|
118
|
-
For
|
|
68
|
+
For assistance with OpenRAG, see [Troubleshoot OpenRAG](https://docs.openr.ag/support/troubleshoot) and visit the [Discussions page](https://github.com/langflow-ai/openrag/discussions).
|
|
69
|
+
|
|
70
|
+
To report a bug or submit a feature request, visit the [Issues page](https://github.com/langflow-ai/openrag/issues).
|
openrag-0.2.1/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# OpenRAG
|
|
4
|
+
|
|
5
|
+
<div align="center">
|
|
6
|
+
<a href="https://github.com/langflow-ai/langflow"><img src="https://img.shields.io/badge/Langflow-1C1C1E?style=flat&logo=langflow" alt="Langflow"></a>
|
|
7
|
+
|
|
8
|
+
<a href="https://github.com/opensearch-project/OpenSearch"><img src="https://img.shields.io/badge/OpenSearch-005EB8?style=flat&logo=opensearch&logoColor=white" alt="OpenSearch"></a>
|
|
9
|
+
|
|
10
|
+
<a href="https://github.com/docling-project/docling"><img src="https://img.shields.io/badge/Docling-000000?style=flat" alt="Langflow"></a>
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations. Users can upload, process, and query documents through a chat interface backed by large language models and semantic search capabilities. The system utilizes Langflow for document ingestion, retrieval workflows, and intelligent nudges, providing a seamless RAG experience. Built with [Starlette](https://github.com/Kludex/starlette) and [Next.js](https://github.com/vercel/next.js). Powered by [OpenSearch](https://github.com/opensearch-project/OpenSearch), [Langflow](https://github.com/langflow-ai/langflow), and [Docling](https://github.com/docling-project/docling).
|
|
15
|
+
|
|
16
|
+
<a href="https://deepwiki.com/langflow-ai/openrag"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
17
|
+
|
|
18
|
+
## Install OpenRAG
|
|
19
|
+
|
|
20
|
+
To get started with OpenRAG, see the installation guides in the OpenRAG documentation:
|
|
21
|
+
|
|
22
|
+
* [Quickstart](https://docs.openr.ag/quickstart)
|
|
23
|
+
* [Install the OpenRAG Python package](https://docs.openr.ag/install-options)
|
|
24
|
+
* [Deploy self-managed services with Docker or Podman](https://docs.openr.ag/docker)
|
|
25
|
+
|
|
26
|
+
## Development
|
|
27
|
+
|
|
28
|
+
For developers who want to [contribute to OpenRAG](https://docs.openr.ag/support/contribute) or set up a development environment, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
29
|
+
|
|
30
|
+
## Troubleshooting
|
|
31
|
+
|
|
32
|
+
For assistance with OpenRAG, see [Troubleshoot OpenRAG](https://docs.openr.ag/support/troubleshoot) and visit the [Discussions page](https://github.com/langflow-ai/openrag/discussions).
|
|
33
|
+
|
|
34
|
+
To report a bug or submit a feature request, visit the [Issues page](https://github.com/langflow-ai/openrag/issues).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Docling service proxy endpoints."""
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
import socket
|
|
4
5
|
import struct
|
|
5
6
|
from pathlib import Path
|
|
@@ -73,9 +74,15 @@ def determine_docling_host() -> str:
|
|
|
73
74
|
return "localhost"
|
|
74
75
|
|
|
75
76
|
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
# Use explicit URL if provided, otherwise auto-detect host
|
|
78
|
+
_docling_url_override = os.getenv("DOCLING_SERVE_URL")
|
|
79
|
+
if _docling_url_override:
|
|
80
|
+
DOCLING_SERVICE_URL = _docling_url_override.rstrip("/")
|
|
81
|
+
HOST_IP = _docling_url_override # For display in health responses
|
|
82
|
+
logger.info("Using DOCLING_SERVE_URL override: %s", DOCLING_SERVICE_URL)
|
|
83
|
+
else:
|
|
84
|
+
HOST_IP = determine_docling_host()
|
|
85
|
+
DOCLING_SERVICE_URL = f"http://{HOST_IP}:5001"
|
|
79
86
|
|
|
80
87
|
|
|
81
88
|
async def health(request: Request) -> JSONResponse:
|
|
@@ -4,6 +4,8 @@ API Key management endpoints.
|
|
|
4
4
|
These endpoints use JWT cookie authentication (for the UI) and allow users
|
|
5
5
|
to create, list, and revoke their API keys for use with the public API.
|
|
6
6
|
"""
|
|
7
|
+
import json
|
|
8
|
+
|
|
7
9
|
from starlette.requests import Request
|
|
8
10
|
from starlette.responses import JSONResponse
|
|
9
11
|
from utils.logging_config import get_logger
|
|
@@ -64,6 +66,17 @@ async def create_key_endpoint(request: Request, api_key_service):
|
|
|
64
66
|
|
|
65
67
|
try:
|
|
66
68
|
data = await request.json()
|
|
69
|
+
except json.JSONDecodeError:
|
|
70
|
+
return JSONResponse(
|
|
71
|
+
{
|
|
72
|
+
"success": False,
|
|
73
|
+
"error": "Invalid or missing JSON body",
|
|
74
|
+
"example": {"name": "My API Key"},
|
|
75
|
+
},
|
|
76
|
+
status_code=400,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
try:
|
|
67
80
|
name = data.get("name", "").strip()
|
|
68
81
|
|
|
69
82
|
if not name:
|
|
@@ -8,6 +8,42 @@ from utils.logging_config import get_logger
|
|
|
8
8
|
logger = get_logger(__name__)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
def normalize_query_data(query_data: str | dict) -> str:
|
|
12
|
+
"""
|
|
13
|
+
Normalize query_data to ensure all required fields exist with defaults.
|
|
14
|
+
This prevents frontend crashes when API-created filters have incomplete data.
|
|
15
|
+
"""
|
|
16
|
+
# Parse if string
|
|
17
|
+
if isinstance(query_data, str):
|
|
18
|
+
try:
|
|
19
|
+
data = json.loads(query_data)
|
|
20
|
+
except json.JSONDecodeError:
|
|
21
|
+
data = {}
|
|
22
|
+
else:
|
|
23
|
+
data = query_data or {}
|
|
24
|
+
|
|
25
|
+
# Ensure filters object exists with all required fields
|
|
26
|
+
filters = data.get("filters") or {}
|
|
27
|
+
normalized_filters = {
|
|
28
|
+
"data_sources": filters.get("data_sources", ["*"]),
|
|
29
|
+
"document_types": filters.get("document_types", ["*"]),
|
|
30
|
+
"owners": filters.get("owners", ["*"]),
|
|
31
|
+
"connector_types": filters.get("connector_types", ["*"]),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Build normalized query_data with defaults
|
|
35
|
+
normalized = {
|
|
36
|
+
"query": data.get("query", ""),
|
|
37
|
+
"filters": normalized_filters,
|
|
38
|
+
"limit": data.get("limit", 10),
|
|
39
|
+
"scoreThreshold": data.get("scoreThreshold", 0),
|
|
40
|
+
"color": data.get("color", "zinc"),
|
|
41
|
+
"icon": data.get("icon", "filter"),
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return json.dumps(normalized)
|
|
45
|
+
|
|
46
|
+
|
|
11
47
|
async def create_knowledge_filter(
|
|
12
48
|
request: Request, knowledge_filter_service, session_manager
|
|
13
49
|
):
|
|
@@ -25,6 +61,15 @@ async def create_knowledge_filter(
|
|
|
25
61
|
if not query_data:
|
|
26
62
|
return JSONResponse({"error": "Query data is required"}, status_code=400)
|
|
27
63
|
|
|
64
|
+
# Normalize query_data to ensure all required fields exist
|
|
65
|
+
try:
|
|
66
|
+
normalized_query_data = normalize_query_data(query_data)
|
|
67
|
+
except Exception as e:
|
|
68
|
+
logger.error(f"Failed to normalize query_data: {e}")
|
|
69
|
+
return JSONResponse(
|
|
70
|
+
{"error": f"Invalid queryData format: {str(e)}"}, status_code=400
|
|
71
|
+
)
|
|
72
|
+
|
|
28
73
|
user = request.state.user
|
|
29
74
|
jwt_token = session_manager.get_effective_jwt_token(user.user_id, request.state.jwt_token)
|
|
30
75
|
|
|
@@ -34,7 +79,7 @@ async def create_knowledge_filter(
|
|
|
34
79
|
"id": filter_id,
|
|
35
80
|
"name": name,
|
|
36
81
|
"description": description,
|
|
37
|
-
"query_data":
|
|
82
|
+
"query_data": normalized_query_data, # Store normalized query JSON with defaults
|
|
38
83
|
"owner": user.user_id,
|
|
39
84
|
"allowed_users": payload.get("allowedUsers", []), # ACL field for future use
|
|
40
85
|
"allowed_groups": payload.get("allowedGroups", []), # ACL field for future use
|
|
@@ -158,12 +203,22 @@ async def update_knowledge_filter(
|
|
|
158
203
|
{"error": "Failed to delete existing knowledge filter"}, status_code=500
|
|
159
204
|
)
|
|
160
205
|
|
|
206
|
+
# Normalize query_data if provided, otherwise use existing
|
|
207
|
+
query_data = payload.get("queryData", existing_filter["query_data"])
|
|
208
|
+
try:
|
|
209
|
+
normalized_query_data = normalize_query_data(query_data)
|
|
210
|
+
except Exception as e:
|
|
211
|
+
logger.error(f"Failed to normalize query_data: {e}")
|
|
212
|
+
return JSONResponse(
|
|
213
|
+
{"error": f"Invalid queryData format: {str(e)}"}, status_code=400
|
|
214
|
+
)
|
|
215
|
+
|
|
161
216
|
# Create updated knowledge filter document with same ID
|
|
162
217
|
updated_filter = {
|
|
163
218
|
"id": filter_id,
|
|
164
219
|
"name": payload.get("name", existing_filter["name"]),
|
|
165
220
|
"description": payload.get("description", existing_filter["description"]),
|
|
166
|
-
"query_data":
|
|
221
|
+
"query_data": normalized_query_data,
|
|
167
222
|
"owner": existing_filter["owner"],
|
|
168
223
|
"allowed_users": payload.get(
|
|
169
224
|
"allowedUsers", existing_filter.get("allowed_users", [])
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
1
3
|
from starlette.requests import Request
|
|
2
4
|
from starlette.responses import JSONResponse
|
|
3
5
|
import json
|
|
@@ -8,7 +10,11 @@ from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
|
|
|
8
10
|
|
|
9
11
|
async def oidc_discovery(request: Request, session_manager):
|
|
10
12
|
"""OIDC discovery endpoint"""
|
|
11
|
-
|
|
13
|
+
openrag_fqdn = os.getenv("OPENRAG_FQDN")
|
|
14
|
+
if openrag_fqdn:
|
|
15
|
+
base_url = f"http://{openrag_fqdn}:8000"
|
|
16
|
+
else:
|
|
17
|
+
base_url = str(request.base_url).rstrip("/")
|
|
12
18
|
|
|
13
19
|
discovery_config = {
|
|
14
20
|
"issuer": base_url,
|
|
@@ -44,6 +50,10 @@ async def jwks_endpoint(request: Request, session_manager):
|
|
|
44
50
|
# Get the public key from session manager
|
|
45
51
|
public_key_pem = session_manager.public_key_pem
|
|
46
52
|
|
|
53
|
+
if public_key_pem is None:
|
|
54
|
+
# Symmetric key in use - no JWKS available
|
|
55
|
+
return JSONResponse({"keys": []})
|
|
56
|
+
|
|
47
57
|
# Parse the PEM to extract key components
|
|
48
58
|
public_key = serialization.load_pem_public_key(public_key_pem.encode())
|
|
49
59
|
|
|
@@ -21,6 +21,7 @@ from functools import partial
|
|
|
21
21
|
|
|
22
22
|
from starlette.applications import Starlette
|
|
23
23
|
from starlette.routing import Route
|
|
24
|
+
from starlette.responses import JSONResponse
|
|
24
25
|
|
|
25
26
|
# Set multiprocessing start method to 'spawn' for CUDA compatibility
|
|
26
27
|
multiprocessing.set_start_method("spawn", force=True)
|
|
@@ -456,6 +457,24 @@ async def _ingest_default_documents_langflow(services, file_paths):
|
|
|
456
457
|
file_count=len(file_paths),
|
|
457
458
|
)
|
|
458
459
|
|
|
460
|
+
async def opensearch_health_ready(request):
|
|
461
|
+
"""Readiness probe: verifies OpenSearch dependency is reachable."""
|
|
462
|
+
try:
|
|
463
|
+
# Fast check that the cluster is reachable/auth works
|
|
464
|
+
await asyncio.wait_for(clients.opensearch.info(), timeout=5.0)
|
|
465
|
+
return JSONResponse(
|
|
466
|
+
{"status": "ready", "dependencies": {"opensearch": "up"}},
|
|
467
|
+
status_code=200,
|
|
468
|
+
)
|
|
469
|
+
except Exception as e:
|
|
470
|
+
return JSONResponse(
|
|
471
|
+
{
|
|
472
|
+
"status": "not_ready",
|
|
473
|
+
"dependencies": {"opensearch": "down"},
|
|
474
|
+
"error": str(e),
|
|
475
|
+
},
|
|
476
|
+
status_code=503,
|
|
477
|
+
)
|
|
459
478
|
|
|
460
479
|
async def _ingest_default_documents_openrag(services, file_paths):
|
|
461
480
|
"""Ingest default documents using traditional OpenRAG processor."""
|
|
@@ -1148,6 +1167,11 @@ async def create_app():
|
|
|
1148
1167
|
),
|
|
1149
1168
|
methods=["GET"],
|
|
1150
1169
|
),
|
|
1170
|
+
Route(
|
|
1171
|
+
"/search/health",
|
|
1172
|
+
opensearch_health_ready,
|
|
1173
|
+
methods=["GET"],
|
|
1174
|
+
),
|
|
1151
1175
|
# Models endpoints
|
|
1152
1176
|
Route(
|
|
1153
1177
|
"/models/openai",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrag
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.13
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -51,68 +51,20 @@ OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables
|
|
|
51
51
|
|
|
52
52
|
<a href="https://deepwiki.com/langflow-ai/openrag"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
<div align="center">
|
|
56
|
-
<a href="#quickstart" style="color: #0366d6;">Quickstart</a> |
|
|
57
|
-
<a href="#install-python-package" style="color: #0366d6;">Python package</a> |
|
|
58
|
-
<a href="#docker-or-podman-installation" style="color: #0366d6;">Docker or Podman</a> |
|
|
59
|
-
<a href="#development" style="color: #0366d6;">Development</a> |
|
|
60
|
-
<a href="#troubleshooting" style="color: #0366d6;">Troubleshooting</a>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
## Quickstart
|
|
64
|
-
|
|
65
|
-
To run OpenRAG without creating or modifying any project files, use `uvx`:
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
uvx openrag
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
This command runs OpenRAG without installing it to your project or globally.
|
|
72
|
-
|
|
73
|
-
To run a specific version of OpenRAG, run `uvx --from openrag==VERSION openrag`.
|
|
74
|
-
|
|
75
|
-
## Install Python package
|
|
76
|
-
|
|
77
|
-
To add the OpenRAG Python package to a Python project, use `uv`:
|
|
78
|
-
|
|
79
|
-
1. Create a new project with a virtual environment using `uv init`:
|
|
54
|
+
## Install OpenRAG
|
|
80
55
|
|
|
81
|
-
|
|
82
|
-
uv init YOUR_PROJECT_NAME
|
|
83
|
-
cd YOUR_PROJECT_NAME
|
|
84
|
-
```
|
|
56
|
+
To get started with OpenRAG, see the installation guides in the OpenRAG documentation:
|
|
85
57
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
2. Add OpenRAG to your project:
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
uv add openrag
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
To add a specific version of OpenRAG, run `uv add openrag==VERSION`.
|
|
96
|
-
|
|
97
|
-
3. Start the OpenRAG terminal user interface (TUI):
|
|
98
|
-
|
|
99
|
-
```bash
|
|
100
|
-
uv run openrag
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
4. Continue with the [Quickstart](https://docs.openr.ag/quickstart).
|
|
104
|
-
|
|
105
|
-
For all installation options, see the [OpenRAG installation guide](https://docs.openr.ag/install).
|
|
106
|
-
|
|
107
|
-
## Docker or Podman installation
|
|
108
|
-
|
|
109
|
-
By default, OpenRAG automatically starts the required containers and helps you manage them.
|
|
110
|
-
To install OpenRAG with self-managed containers, see the [OpenRAG installation guide](https://docs.openr.ag/docker).
|
|
58
|
+
* [Quickstart](https://docs.openr.ag/quickstart)
|
|
59
|
+
* [Install the OpenRAG Python package](https://docs.openr.ag/install-options)
|
|
60
|
+
* [Deploy self-managed services with Docker or Podman](https://docs.openr.ag/docker)
|
|
111
61
|
|
|
112
62
|
## Development
|
|
113
63
|
|
|
114
|
-
For developers
|
|
64
|
+
For developers who want to [contribute to OpenRAG](https://docs.openr.ag/support/contribute) or set up a development environment, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
115
65
|
|
|
116
66
|
## Troubleshooting
|
|
117
67
|
|
|
118
|
-
For
|
|
68
|
+
For assistance with OpenRAG, see [Troubleshoot OpenRAG](https://docs.openr.ag/support/troubleshoot) and visit the [Discussions page](https://github.com/langflow-ai/openrag/discussions).
|
|
69
|
+
|
|
70
|
+
To report a bug or submit a feature request, visit the [Issues page](https://github.com/langflow-ai/openrag/issues).
|
|
@@ -35,13 +35,7 @@ class ModelsService:
|
|
|
35
35
|
"claude-opus-4-1-20250805",
|
|
36
36
|
"claude-opus-4-20250514",
|
|
37
37
|
"claude-sonnet-4-20250514",
|
|
38
|
-
"claude-3-7-sonnet-latest",
|
|
39
|
-
"claude-3-5-sonnet-latest",
|
|
40
38
|
"claude-3-5-haiku-latest",
|
|
41
|
-
"claude-3-opus-latest",
|
|
42
|
-
"claude-3-sonnet-20240229",
|
|
43
|
-
"claude-3-5-sonnet-20240620",
|
|
44
|
-
"claude-3-5-sonnet-20241022",
|
|
45
39
|
"claude-3-5-haiku-20241022",
|
|
46
40
|
"claude-3-haiku-20240307",
|
|
47
41
|
]
|
|
@@ -60,13 +60,44 @@ class SessionManager:
|
|
|
60
60
|
str, Any
|
|
61
61
|
] = {} # user_id -> OpenSearch client
|
|
62
62
|
|
|
63
|
-
# Load RSA keys
|
|
64
63
|
self.private_key_path = private_key_path
|
|
65
64
|
self.public_key_path = public_key_path
|
|
66
|
-
|
|
65
|
+
|
|
66
|
+
# Configure JWT signing (checks env var first, falls back to key files)
|
|
67
|
+
self._configure_jwt_signing()
|
|
68
|
+
|
|
69
|
+
def _configure_jwt_signing(self):
|
|
70
|
+
"""Configure JWT signing - supports env var or file-based keys"""
|
|
71
|
+
signing_key = os.getenv("JWT_SIGNING_KEY")
|
|
72
|
+
|
|
73
|
+
if signing_key:
|
|
74
|
+
if signing_key.startswith("-----BEGIN"):
|
|
75
|
+
# PEM format = asymmetric (RS256)
|
|
76
|
+
self.private_key = serialization.load_pem_private_key(
|
|
77
|
+
signing_key.encode(), password=None
|
|
78
|
+
)
|
|
79
|
+
# Extract public key from private key
|
|
80
|
+
self.public_key = self.private_key.public_key()
|
|
81
|
+
self.public_key_pem = self.public_key.public_bytes(
|
|
82
|
+
encoding=serialization.Encoding.PEM,
|
|
83
|
+
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
|
84
|
+
).decode()
|
|
85
|
+
self.algorithm = "RS256"
|
|
86
|
+
logger.info("JWT signing configured with RSA key from environment")
|
|
87
|
+
else:
|
|
88
|
+
# Plain string = symmetric (HS256)
|
|
89
|
+
self.private_key = signing_key
|
|
90
|
+
self.public_key = signing_key # Same key for verification
|
|
91
|
+
self.public_key_pem = None # No JWKS for symmetric
|
|
92
|
+
self.algorithm = "HS256"
|
|
93
|
+
logger.info("JWT signing configured with symmetric key from environment")
|
|
94
|
+
else:
|
|
95
|
+
# Fall back to file-based RSA keys
|
|
96
|
+
self._load_rsa_keys()
|
|
97
|
+
self.algorithm = "RS256"
|
|
67
98
|
|
|
68
99
|
def _load_rsa_keys(self):
|
|
69
|
-
"""Load RSA private and public keys"""
|
|
100
|
+
"""Load RSA private and public keys from files"""
|
|
70
101
|
try:
|
|
71
102
|
with open(self.private_key_path, "rb") as f:
|
|
72
103
|
self.private_key = serialization.load_pem_private_key(
|
|
@@ -76,7 +107,6 @@ class SessionManager:
|
|
|
76
107
|
with open(self.public_key_path, "rb") as f:
|
|
77
108
|
self.public_key = serialization.load_pem_public_key(f.read())
|
|
78
109
|
|
|
79
|
-
# Also get public key in PEM format for JWKS
|
|
80
110
|
self.public_key_pem = open(self.public_key_path, "r").read()
|
|
81
111
|
|
|
82
112
|
except FileNotFoundError as e:
|
|
@@ -140,6 +170,9 @@ class SessionManager:
|
|
|
140
170
|
"""Create JWT token for an existing user"""
|
|
141
171
|
# Use OpenSearch-compatible issuer for OIDC validation
|
|
142
172
|
oidc_issuer = "http://openrag-backend:8000"
|
|
173
|
+
openrag_fqdn = os.getenv("OPENRAG_FQDN")
|
|
174
|
+
if openrag_fqdn:
|
|
175
|
+
oidc_issuer = f"http://{openrag_fqdn}:8000"
|
|
143
176
|
|
|
144
177
|
# Create JWT token with OIDC-compliant claims
|
|
145
178
|
now = datetime.utcnow()
|
|
@@ -158,9 +191,10 @@ class SessionManager:
|
|
|
158
191
|
"preferred_username": user.email,
|
|
159
192
|
"email_verified": True,
|
|
160
193
|
"roles": ["openrag_user"], # Backend role for OpenSearch
|
|
194
|
+
"user_roles": ["openrag_user"], # compatible with OpenSearch's roles_key
|
|
161
195
|
}
|
|
162
196
|
|
|
163
|
-
token = jwt.encode(token_payload, self.private_key, algorithm=
|
|
197
|
+
token = jwt.encode(token_payload, self.private_key, algorithm=self.algorithm)
|
|
164
198
|
return token
|
|
165
199
|
|
|
166
200
|
def verify_token(self, token: str) -> Optional[Dict[str, Any]]:
|
|
@@ -169,7 +203,7 @@ class SessionManager:
|
|
|
169
203
|
payload = jwt.decode(
|
|
170
204
|
token,
|
|
171
205
|
self.public_key,
|
|
172
|
-
algorithms=[
|
|
206
|
+
algorithms=[self.algorithm],
|
|
173
207
|
audience=["opensearch", "openrag"],
|
|
174
208
|
)
|
|
175
209
|
return payload
|
|
@@ -29,7 +29,7 @@ services:
|
|
|
29
29
|
- "9200:9200"
|
|
30
30
|
- "9600:9600"
|
|
31
31
|
volumes:
|
|
32
|
-
- ${OPENSEARCH_DATA_PATH:-./opensearch-data}:/usr/share/opensearch/data:
|
|
32
|
+
- ${OPENSEARCH_DATA_PATH:-./opensearch-data}:/usr/share/opensearch/data:U,z
|
|
33
33
|
|
|
34
34
|
dashboards:
|
|
35
35
|
image: opensearchproject/opensearch-dashboards:3.0.0
|
|
@@ -81,7 +81,7 @@ services:
|
|
|
81
81
|
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
|
|
82
82
|
volumes:
|
|
83
83
|
- ${OPENRAG_DOCUMENTS_PATH:-./openrag-documents}:/app/openrag-documents:Z
|
|
84
|
-
- ${OPENRAG_KEYS_PATH:-./keys}:/app/keys:
|
|
84
|
+
- ${OPENRAG_KEYS_PATH:-./keys}:/app/keys:U,z
|
|
85
85
|
- ${OPENRAG_FLOWS_PATH:-./flows}:/app/flows:U,z
|
|
86
86
|
- ${OPENRAG_CONFIG_PATH:-./config}:/app/config:Z
|
|
87
87
|
- ${OPENRAG_DATA_PATH:-./data}:/app/data:Z
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Main TUI application for OpenRAG."""
|
|
2
2
|
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
3
5
|
import sys
|
|
4
6
|
from pathlib import Path
|
|
5
7
|
from typing import Iterable, Optional
|
|
@@ -683,6 +685,51 @@ def migrate_legacy_data_directories():
|
|
|
683
685
|
logger.info("Data migration completed successfully")
|
|
684
686
|
|
|
685
687
|
|
|
688
|
+
def generate_jwt_keys(keys_dir: Path):
|
|
689
|
+
"""Generate RSA keys for JWT signing if they don't exist.
|
|
690
|
+
|
|
691
|
+
This pre-generates keys on the host so containers can read them,
|
|
692
|
+
avoiding permission issues with Podman rootless mode.
|
|
693
|
+
"""
|
|
694
|
+
private_key_path = keys_dir / "private_key.pem"
|
|
695
|
+
public_key_path = keys_dir / "public_key.pem"
|
|
696
|
+
|
|
697
|
+
if private_key_path.exists() and public_key_path.exists():
|
|
698
|
+
logger.debug("JWT keys already exist")
|
|
699
|
+
return
|
|
700
|
+
|
|
701
|
+
try:
|
|
702
|
+
# Generate private key
|
|
703
|
+
subprocess.run(
|
|
704
|
+
["openssl", "genrsa", "-out", str(private_key_path), "2048"],
|
|
705
|
+
check=True,
|
|
706
|
+
capture_output=True,
|
|
707
|
+
)
|
|
708
|
+
# Set restrictive permissions on private key (readable by owner only)
|
|
709
|
+
os.chmod(private_key_path, 0o600)
|
|
710
|
+
|
|
711
|
+
# Generate public key from private key
|
|
712
|
+
subprocess.run(
|
|
713
|
+
[
|
|
714
|
+
"openssl",
|
|
715
|
+
"rsa",
|
|
716
|
+
"-in", str(private_key_path),
|
|
717
|
+
"-pubout",
|
|
718
|
+
"-out", str(public_key_path),
|
|
719
|
+
],
|
|
720
|
+
check=True,
|
|
721
|
+
capture_output=True,
|
|
722
|
+
)
|
|
723
|
+
# Set permissions on public key (readable by all)
|
|
724
|
+
os.chmod(public_key_path, 0o644)
|
|
725
|
+
|
|
726
|
+
logger.info("Generated RSA keys for JWT signing")
|
|
727
|
+
except FileNotFoundError:
|
|
728
|
+
logger.warning("openssl not found, skipping JWT key generation (will be generated in container)")
|
|
729
|
+
except subprocess.CalledProcessError as e:
|
|
730
|
+
logger.error(f"Failed to generate RSA keys: {e}")
|
|
731
|
+
|
|
732
|
+
|
|
686
733
|
def setup_host_directories():
|
|
687
734
|
"""Initialize OpenRAG directory structure on the host.
|
|
688
735
|
|
|
@@ -703,11 +750,14 @@ def setup_host_directories():
|
|
|
703
750
|
base_dir / "data",
|
|
704
751
|
base_dir / "data" / "opensearch-data",
|
|
705
752
|
]
|
|
706
|
-
|
|
753
|
+
|
|
707
754
|
for directory in directories:
|
|
708
755
|
directory.mkdir(parents=True, exist_ok=True)
|
|
709
756
|
logger.debug(f"Ensured directory exists: {directory}")
|
|
710
757
|
|
|
758
|
+
# Generate JWT keys on host to avoid container permission issues
|
|
759
|
+
generate_jwt_keys(base_dir / "keys")
|
|
760
|
+
|
|
711
761
|
|
|
712
762
|
def run_tui():
|
|
713
763
|
"""Run the OpenRAG TUI application."""
|
|
@@ -37,9 +37,9 @@ class DoclingManager:
|
|
|
37
37
|
self._starting = False
|
|
38
38
|
self._external_process = False
|
|
39
39
|
|
|
40
|
-
# PID file to track docling-serve across sessions (in
|
|
41
|
-
from
|
|
42
|
-
self._pid_file =
|
|
40
|
+
# PID file to track docling-serve across sessions (centralized in ~/.openrag/tui/)
|
|
41
|
+
from utils.paths import get_tui_dir
|
|
42
|
+
self._pid_file = get_tui_dir() / ".docling.pid"
|
|
43
43
|
|
|
44
44
|
# Log storage - simplified, no queue
|
|
45
45
|
self._log_buffer: List[str] = []
|