openrag 0.4.1.dev22__tar.gz → 0.5.0.dev2__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.4.1.dev22/src/openrag.egg-info → openrag-0.5.0.dev2}/PKG-INFO +11 -3
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/pyproject.toml +13 -4
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/agent.py +3 -15
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/auth.py +69 -9
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/chat.py +9 -3
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/connector_router.py +13 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/connectors.py +9 -10
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/documents.py +9 -3
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/keys.py +1 -1
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/knowledge_filter.py +2 -5
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/provider_validation.py +3 -3
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/search.py +0 -1
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/settings.py +256 -74
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/upload.py +16 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/v1/chat.py +6 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/v1/settings.py +3 -2
- openrag-0.5.0.dev2/src/auth/ibm_auth.py +90 -0
- openrag-0.5.0.dev2/src/bootstrap.py +23 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/config/config_manager.py +50 -14
- openrag-0.5.0.dev2/src/config/paths.py +93 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/config/settings.py +72 -30
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/connection_manager.py +87 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/google_drive/connector.py +58 -53
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/google_drive/oauth.py +90 -41
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/ibm_cos/connector.py +0 -5
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/langflow_connector_service.py +18 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/onedrive/connector.py +8 -11
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/onedrive/oauth.py +60 -65
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/service.py +6 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/sharepoint/connector.py +8 -11
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/sharepoint/oauth.py +61 -68
- openrag-0.5.0.dev2/src/dependencies.py +419 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/main.py +513 -199
- openrag-0.5.0.dev2/src/mcp_http/server.py +229 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/models/processors.py +52 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2/src/openrag.egg-info}/PKG-INFO +11 -3
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/openrag.egg-info/SOURCES.txt +8 -1
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/openrag.egg-info/requires.txt +10 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/openrag.egg-info/top_level.txt +3 -0
- openrag-0.5.0.dev2/src/services/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/api_key_service.py +16 -15
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/auth_service.py +116 -84
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/chat_service.py +42 -13
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/conversation_persistence_service.py +3 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/flows_service.py +252 -187
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/langflow_file_service.py +52 -43
- openrag-0.5.0.dev2/src/services/langflow_mcp_service.py +281 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/models_service.py +54 -11
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/search_service.py +117 -69
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/session_ownership_service.py +2 -1
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/session_manager.py +24 -10
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/docker-compose.yml +13 -6
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/ingestion_flow.json +2136 -1737
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/openrag_agent.json +1193 -998
- openrag-0.5.0.dev2/src/tui/_assets/flows/openrag_nudges.json +4674 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/openrag_url_mcp.json +3588 -2753
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/config_fields.py +21 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/main.py +81 -1
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/managers/docling_manager.py +42 -63
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/managers/env_manager.py +32 -11
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/screens/config.py +11 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/utils/startup_checks.py +19 -86
- openrag-0.5.0.dev2/src/utils/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/acl_utils.py +5 -2
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/document_processing.py +39 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/embedding_fields.py +39 -12
- openrag-0.5.0.dev2/src/utils/encryption.py +209 -0
- openrag-0.5.0.dev2/src/utils/langflow_headers.py +76 -0
- openrag-0.5.0.dev2/src/utils/logging_config.py +321 -0
- openrag-0.5.0.dev2/src/utils/opensearch_utils.py +387 -0
- openrag-0.5.0.dev2/src/utils/run_mode_utils.py +36 -0
- openrag-0.4.1.dev22/src/dependencies.py +0 -222
- openrag-0.4.1.dev22/src/services/langflow_mcp_service.py +0 -275
- openrag-0.4.1.dev22/src/tui/_assets/flows/openrag_nudges.json +0 -4851
- openrag-0.4.1.dev22/src/tui/_assets/openrag-documents/openrag-documentation.pdf +0 -0
- openrag-0.4.1.dev22/src/utils/langflow_headers.py +0 -79
- openrag-0.4.1.dev22/src/utils/logging_config.py +0 -151
- openrag-0.4.1.dev22/src/utils/opensearch_utils.py +0 -160
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/LICENSE +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/MANIFEST.in +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/README.md +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/setup.cfg +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/docling.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/flows.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/langflow_files.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/models.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/nudges.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/oidc.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/provider_health.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/router.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/tasks.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/v1/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/v1/documents.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/v1/knowledge_filters.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/v1/models.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/api/v1/search.py +0 -0
- {openrag-0.4.1.dev22/src/config → openrag-0.5.0.dev2/src/auth}/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/auth_context.py +0 -0
- {openrag-0.4.1.dev22/src/models → openrag-0.5.0.dev2/src/config}/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/config/embedding_constants.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/config/model_constants.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/aws_s3/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/aws_s3/api.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/aws_s3/auth.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/aws_s3/connector.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/aws_s3/models.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/aws_s3/support.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/base.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/google_drive/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/ibm_cos/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/ibm_cos/api.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/ibm_cos/auth.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/ibm_cos/models.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/ibm_cos/support.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/onedrive/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/sharepoint/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/connectors/sharepoint/utils.py +0 -0
- {openrag-0.4.1.dev22/src/services → openrag-0.5.0.dev2/src/mcp_http}/__init__.py +0 -0
- {openrag-0.4.1.dev22/src/utils → openrag-0.5.0.dev2/src/models}/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/models/tasks.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/models/url.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/openrag.egg-info/dependency_links.txt +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/openrag.egg-info/entry_points.txt +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/document_service.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/knowledge_filter_service.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/langflow_history_service.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/monitor_service.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/services/task_service.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/docker-compose.gpu.yml +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/components/ollama_embedding.json +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/components/ollama_llm.json +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/components/ollama_llm_text.json +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/components/watsonx_embedding.json +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/components/watsonx_llm.json +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/flows/components/watsonx_llm_text.json +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/openrag-documents/docling.pdf +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/openrag-documents/ibm_anthropic.pdf +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/_assets/openrag-documents/warmup_ocr.pdf +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/cli.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/managers/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/managers/container_manager.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/screens/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/screens/diagnostics.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/screens/logs.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/screens/monitor.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/screens/welcome.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/utils/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/utils/clipboard.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/utils/platform.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/utils/validation.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/utils/version_check.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/command_modal.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/diagnostics_notification.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/error_notification.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/factory_reset_warning_modal.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/flow_backup_warning_modal.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/prune_options_modal.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/upgrade_instructions_modal.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/version_mismatch_warning_modal.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/tui/widgets/waves.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/container_utils.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/docling_client.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/embeddings.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/env_utils.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/file_utils.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/gpu_detection.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/hash_utils.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/langflow_utils.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/opensearch_queries.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/paths.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/telemetry/__init__.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/telemetry/category.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/telemetry/client.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/telemetry/message_id.py +0 -0
- {openrag-0.4.1.dev22 → openrag-0.5.0.dev2}/src/utils/version_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrag
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0.dev2
|
|
4
4
|
Summary: OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations.
|
|
5
5
|
Classifier: Development Status :: 4 - Beta
|
|
6
6
|
Classifier: Environment :: Console
|
|
@@ -17,14 +17,15 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: agentd>=0.8.1
|
|
19
19
|
Requires-Dist: aiofiles>=24.1.0
|
|
20
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: aiohttp>=3.13.4
|
|
21
|
+
Requires-Dist: cryptography>=46.0.6
|
|
21
22
|
Requires-Dist: google-api-python-client>=2.143.0
|
|
22
23
|
Requires-Dist: google-auth-httplib2>=0.2.0
|
|
23
24
|
Requires-Dist: google-auth-oauthlib>=1.2.0
|
|
24
25
|
Requires-Dist: msal>=1.29.0
|
|
25
26
|
Requires-Dist: httpx>=0.27.0
|
|
26
27
|
Requires-Dist: opensearch-py[async]>=3.0.0
|
|
27
|
-
Requires-Dist: pyjwt>=2.
|
|
28
|
+
Requires-Dist: pyjwt>=2.12.0
|
|
28
29
|
Requires-Dist: python-multipart>=0.0.20
|
|
29
30
|
Requires-Dist: fastapi>=0.115.0
|
|
30
31
|
Requires-Dist: uvicorn>=0.35.0
|
|
@@ -37,10 +38,17 @@ Requires-Dist: python-dotenv>=1.0.0
|
|
|
37
38
|
Requires-Dist: textual-fspicker>=0.6.0
|
|
38
39
|
Requires-Dist: structlog>=25.4.0
|
|
39
40
|
Requires-Dist: zxcvbn>=4.5.0
|
|
41
|
+
Requires-Dist: prometheus-fastapi-instrumentator>=7.1.0
|
|
40
42
|
Requires-Dist: litellm==1.83.3
|
|
41
43
|
Requires-Dist: pyyaml>=6.0
|
|
42
44
|
Requires-Dist: tiktoken>=0.7.0
|
|
45
|
+
Requires-Dist: prometheus-fastapi-instrumentator>=7.1.0
|
|
46
|
+
Requires-Dist: fastmcp>=3.2.3
|
|
43
47
|
Requires-Dist: openai>=2.30.0
|
|
48
|
+
Requires-Dist: tenacity>=9.1.4
|
|
49
|
+
Requires-Dist: pygments>=2.20.0
|
|
50
|
+
Requires-Dist: pyasn1>=0.6.3
|
|
51
|
+
Requires-Dist: requests>=2.33.0
|
|
44
52
|
Dynamic: license-file
|
|
45
53
|
|
|
46
54
|
<div align="center">
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openrag"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.0.dev2"
|
|
8
8
|
description = "OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13"
|
|
@@ -23,14 +23,15 @@ classifiers = [
|
|
|
23
23
|
dependencies = [
|
|
24
24
|
"agentd>=0.8.1",
|
|
25
25
|
"aiofiles>=24.1.0",
|
|
26
|
-
"
|
|
26
|
+
"aiohttp>=3.13.4",
|
|
27
|
+
"cryptography>=46.0.6",
|
|
27
28
|
"google-api-python-client>=2.143.0",
|
|
28
29
|
"google-auth-httplib2>=0.2.0",
|
|
29
30
|
"google-auth-oauthlib>=1.2.0",
|
|
30
31
|
"msal>=1.29.0",
|
|
31
32
|
"httpx>=0.27.0",
|
|
32
33
|
"opensearch-py[async]>=3.0.0",
|
|
33
|
-
"pyjwt>=2.
|
|
34
|
+
"pyjwt>=2.12.0",
|
|
34
35
|
"python-multipart>=0.0.20",
|
|
35
36
|
"fastapi>=0.115.0",
|
|
36
37
|
"uvicorn>=0.35.0",
|
|
@@ -43,19 +44,27 @@ dependencies = [
|
|
|
43
44
|
"textual-fspicker>=0.6.0",
|
|
44
45
|
"structlog>=25.4.0",
|
|
45
46
|
"zxcvbn>=4.5.0",
|
|
47
|
+
"prometheus-fastapi-instrumentator>=7.1.0",
|
|
46
48
|
"litellm==1.83.3",
|
|
47
49
|
"pyyaml>=6.0",
|
|
48
50
|
"tiktoken>=0.7.0",
|
|
51
|
+
"prometheus-fastapi-instrumentator>=7.1.0",
|
|
52
|
+
"fastmcp>=3.2.3",
|
|
49
53
|
"openai>=2.30.0",
|
|
54
|
+
"tenacity>=9.1.4",
|
|
55
|
+
"pygments>=2.20.0",
|
|
56
|
+
"pyasn1>=0.6.3",
|
|
57
|
+
"requests>=2.33.0",
|
|
50
58
|
]
|
|
51
59
|
|
|
52
60
|
[dependency-groups]
|
|
53
|
-
dev = ["pytest>=
|
|
61
|
+
dev = ["pytest>=9.0.3", "pytest-asyncio>=0.21.0", "pytest-mock>=3.12.0", "pytest-cov>=4.0.0"]
|
|
54
62
|
|
|
55
63
|
[project.scripts]
|
|
56
64
|
openrag = "tui.main:run_tui"
|
|
57
65
|
|
|
58
66
|
[tool.uv]
|
|
59
67
|
package = true
|
|
68
|
+
override-dependencies = ["python-dotenv>=1.1.0"]
|
|
60
69
|
|
|
61
70
|
|
|
@@ -138,9 +138,6 @@ async def async_response_stream(
|
|
|
138
138
|
detected_tool_call = False
|
|
139
139
|
async for chunk in response:
|
|
140
140
|
chunk_count += 1
|
|
141
|
-
logger.debug(
|
|
142
|
-
"Stream chunk received", chunk_count=chunk_count, chunk=str(chunk)
|
|
143
|
-
)
|
|
144
141
|
|
|
145
142
|
import json
|
|
146
143
|
|
|
@@ -258,10 +255,7 @@ async def async_response_stream(
|
|
|
258
255
|
logger.info("Response generated", log_prefix=log_prefix, response=full_response)
|
|
259
256
|
|
|
260
257
|
except Exception as e:
|
|
261
|
-
logger.
|
|
262
|
-
import traceback
|
|
263
|
-
|
|
264
|
-
traceback.print_exc()
|
|
258
|
+
logger.exception("[AGENT] Streaming failed")
|
|
265
259
|
raise
|
|
266
260
|
|
|
267
261
|
|
|
@@ -316,10 +310,7 @@ async def async_response(
|
|
|
316
310
|
msg = error_msg
|
|
317
311
|
raise ValueError(msg)
|
|
318
312
|
except Exception as e:
|
|
319
|
-
logger.
|
|
320
|
-
import traceback
|
|
321
|
-
|
|
322
|
-
traceback.print_exc()
|
|
313
|
+
logger.exception("[AGENT] Non-streaming response failed")
|
|
323
314
|
raise
|
|
324
315
|
|
|
325
316
|
|
|
@@ -387,10 +378,7 @@ async def async_langflow_stream(
|
|
|
387
378
|
yield chunk
|
|
388
379
|
logger.debug("Langflow stream completed")
|
|
389
380
|
except Exception as e:
|
|
390
|
-
logger.
|
|
391
|
-
import traceback
|
|
392
|
-
|
|
393
|
-
traceback.print_exc()
|
|
381
|
+
logger.exception("[AGENT] Langflow stream failed")
|
|
394
382
|
raise
|
|
395
383
|
|
|
396
384
|
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
|
-
from fastapi import Depends, Request
|
|
3
|
+
from fastapi import Depends, HTTPException, Request
|
|
4
4
|
from fastapi.responses import JSONResponse
|
|
5
5
|
from utils.telemetry import TelemetryClient, Category, MessageId
|
|
6
|
+
from utils.version_utils import OPENRAG_VERSION
|
|
7
|
+
from utils.logging_config import get_logger
|
|
8
|
+
|
|
9
|
+
logger = get_logger(__name__)
|
|
6
10
|
|
|
7
11
|
from dependencies import (
|
|
8
12
|
get_auth_service,
|
|
@@ -20,6 +24,8 @@ class AuthInitBody(BaseModel):
|
|
|
20
24
|
redirect_uri: Optional[str] = None
|
|
21
25
|
|
|
22
26
|
|
|
27
|
+
|
|
28
|
+
|
|
23
29
|
class AuthCallbackBody(BaseModel):
|
|
24
30
|
connection_id: str
|
|
25
31
|
authorization_code: str
|
|
@@ -47,9 +53,7 @@ async def auth_init(
|
|
|
47
53
|
return JSONResponse(result)
|
|
48
54
|
|
|
49
55
|
except Exception as e:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
traceback.print_exc()
|
|
56
|
+
logger.exception("[AUTH] OAuth init failed")
|
|
53
57
|
return JSONResponse(
|
|
54
58
|
{"error": f"Failed to initialize OAuth: {str(e)}"}, status_code=500
|
|
55
59
|
)
|
|
@@ -74,9 +78,14 @@ async def auth_callback(
|
|
|
74
78
|
response = JSONResponse(
|
|
75
79
|
{k: v for k, v in result.items() if k != "jwt_token"}
|
|
76
80
|
)
|
|
81
|
+
# Store only the raw JWT (without "Bearer " prefix) in the cookie.
|
|
82
|
+
# The prefix is added by the OpenSearch client when building the Authorization header.
|
|
83
|
+
jwt_value = result["jwt_token"]
|
|
84
|
+
if jwt_value.startswith("Bearer "):
|
|
85
|
+
jwt_value = jwt_value[len("Bearer "):]
|
|
77
86
|
response.set_cookie(
|
|
78
87
|
key="auth_token",
|
|
79
|
-
value=
|
|
88
|
+
value=jwt_value,
|
|
80
89
|
httponly=True,
|
|
81
90
|
secure=False,
|
|
82
91
|
samesite="lax",
|
|
@@ -87,9 +96,7 @@ async def auth_callback(
|
|
|
87
96
|
return JSONResponse(result)
|
|
88
97
|
|
|
89
98
|
except Exception as e:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
traceback.print_exc()
|
|
99
|
+
logger.exception("[AUTH] OAuth callback failed")
|
|
93
100
|
await TelemetryClient.send_event(Category.AUTHENTICATION, MessageId.ORB_AUTH_OAUTH_FAILED)
|
|
94
101
|
return JSONResponse({"error": f"Callback failed: {str(e)}"}, status_code=500)
|
|
95
102
|
|
|
@@ -101,6 +108,7 @@ async def auth_me(
|
|
|
101
108
|
):
|
|
102
109
|
"""Get current user information"""
|
|
103
110
|
result = await auth_service.get_user_info(request)
|
|
111
|
+
result["version"] = OPENRAG_VERSION
|
|
104
112
|
return JSONResponse(result)
|
|
105
113
|
|
|
106
114
|
|
|
@@ -108,8 +116,28 @@ async def auth_logout(
|
|
|
108
116
|
auth_service=Depends(get_auth_service),
|
|
109
117
|
user: User = Depends(get_current_user),
|
|
110
118
|
):
|
|
111
|
-
"""Logout user by clearing auth cookie"""
|
|
119
|
+
"""Logout user by clearing auth cookie(s)"""
|
|
120
|
+
from config.settings import IBM_AUTH_ENABLED, IBM_SESSION_COOKIE_NAME
|
|
121
|
+
|
|
112
122
|
await TelemetryClient.send_event(Category.AUTHENTICATION, MessageId.ORB_AUTH_LOGOUT)
|
|
123
|
+
|
|
124
|
+
if IBM_AUTH_ENABLED:
|
|
125
|
+
# Best-effort: clear cookies from the browser, but warn that the
|
|
126
|
+
# server-side AMS session is NOT terminated. The IBM session cookie
|
|
127
|
+
# is owned by Traefik/AMS — it may be re-injected on the next
|
|
128
|
+
# proxied request if AMS still considers the session active.
|
|
129
|
+
response = JSONResponse(
|
|
130
|
+
{
|
|
131
|
+
"status": "partial_logout",
|
|
132
|
+
"message": "Browser cookies cleared, but the IBM session is "
|
|
133
|
+
"managed by the identity provider and may still be active. "
|
|
134
|
+
"Please log out through IBM Watsonx Data for full session termination.",
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
response.delete_cookie(key=IBM_SESSION_COOKIE_NAME, httponly=True, samesite="lax")
|
|
138
|
+
response.delete_cookie(key="ibm-auth-basic", httponly=True, samesite="lax")
|
|
139
|
+
return response
|
|
140
|
+
|
|
113
141
|
response = JSONResponse(
|
|
114
142
|
{"status": "logged_out", "message": "Successfully logged out"}
|
|
115
143
|
)
|
|
@@ -120,3 +148,35 @@ async def auth_logout(
|
|
|
120
148
|
)
|
|
121
149
|
|
|
122
150
|
return response
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
async def ibm_login(request: Request):
|
|
154
|
+
"""IBM login endpoint.
|
|
155
|
+
|
|
156
|
+
Production: Traefik intercepts the request, validates Basic credentials
|
|
157
|
+
with AMS, and sets the ibm-openrag-session cookie before forwarding here.
|
|
158
|
+
This handler just returns 200 — no cookie work needed.
|
|
159
|
+
|
|
160
|
+
Local dev (no Traefik): stores the Basic Auth header in ibm-auth-basic
|
|
161
|
+
cookie so subsequent requests can be authenticated by _get_ibm_user.
|
|
162
|
+
"""
|
|
163
|
+
from config.settings import IBM_AUTH_ENABLED, IBM_SESSION_COOKIE_NAME
|
|
164
|
+
|
|
165
|
+
if not IBM_AUTH_ENABLED:
|
|
166
|
+
raise HTTPException(status_code=404, detail="IBM auth is not enabled")
|
|
167
|
+
|
|
168
|
+
response = JSONResponse({"status": "ok"})
|
|
169
|
+
|
|
170
|
+
# Local dev fallback only — in production Traefik sets the session cookie.
|
|
171
|
+
if not request.cookies.get(IBM_SESSION_COOKIE_NAME):
|
|
172
|
+
auth_header = request.headers.get("Authorization", "")
|
|
173
|
+
if auth_header.startswith("Basic "):
|
|
174
|
+
# secure =True not needed for local development
|
|
175
|
+
response.set_cookie(
|
|
176
|
+
"ibm-auth-basic",
|
|
177
|
+
auth_header,
|
|
178
|
+
httponly=True,
|
|
179
|
+
samesite="lax",
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return response
|
|
@@ -101,6 +101,9 @@ async def langflow_endpoint(
|
|
|
101
101
|
previous_response_id=body.previous_response_id,
|
|
102
102
|
stream=True,
|
|
103
103
|
filter_id=body.filter_id,
|
|
104
|
+
owner=user.user_id,
|
|
105
|
+
owner_name=user.name,
|
|
106
|
+
owner_email=user.email,
|
|
104
107
|
),
|
|
105
108
|
media_type="text/event-stream",
|
|
106
109
|
headers={
|
|
@@ -118,13 +121,14 @@ async def langflow_endpoint(
|
|
|
118
121
|
previous_response_id=body.previous_response_id,
|
|
119
122
|
stream=False,
|
|
120
123
|
filter_id=body.filter_id,
|
|
124
|
+
owner=user.user_id,
|
|
125
|
+
owner_name=user.name,
|
|
126
|
+
owner_email=user.email,
|
|
121
127
|
)
|
|
122
128
|
return JSONResponse(result)
|
|
123
129
|
|
|
124
130
|
except Exception as e:
|
|
125
|
-
|
|
126
|
-
traceback.print_exc()
|
|
127
|
-
logger.error("Langflow request failed", error=str(e))
|
|
131
|
+
logger.exception("[CHAT] Langflow request failed")
|
|
128
132
|
return JSONResponse(
|
|
129
133
|
{"error": f"Langflow request failed: {str(e)}"}, status_code=500
|
|
130
134
|
)
|
|
@@ -139,6 +143,7 @@ async def chat_history_endpoint(
|
|
|
139
143
|
history = await chat_service.get_chat_history(user.user_id)
|
|
140
144
|
return JSONResponse(history)
|
|
141
145
|
except Exception as e:
|
|
146
|
+
logger.exception("[CHAT] Failed to get chat history")
|
|
142
147
|
return JSONResponse(
|
|
143
148
|
{"error": f"Failed to get chat history: {str(e)}"}, status_code=500
|
|
144
149
|
)
|
|
@@ -153,6 +158,7 @@ async def langflow_history_endpoint(
|
|
|
153
158
|
history = await chat_service.get_langflow_history(user.user_id)
|
|
154
159
|
return JSONResponse(history)
|
|
155
160
|
except Exception as e:
|
|
161
|
+
logger.exception("[CHAT] Failed to get langflow history")
|
|
156
162
|
return JSONResponse(
|
|
157
163
|
{"error": f"Failed to get langflow history: {str(e)}"}, status_code=500
|
|
158
164
|
)
|
|
@@ -50,11 +50,22 @@ class ConnectorRouter:
|
|
|
50
50
|
return await self.get_active_service().get_connector(connection_id)
|
|
51
51
|
|
|
52
52
|
async def sync_specific_files(
|
|
53
|
-
self,
|
|
53
|
+
self,
|
|
54
|
+
connection_id: str,
|
|
55
|
+
user_id: str,
|
|
56
|
+
file_list: list,
|
|
57
|
+
jwt_token: str = None,
|
|
58
|
+
file_infos: list = None,
|
|
59
|
+
ingest_settings: dict = None,
|
|
54
60
|
):
|
|
55
61
|
"""Sync specific files using the active service."""
|
|
56
62
|
return await self.get_active_service().sync_specific_files(
|
|
57
|
-
connection_id,
|
|
63
|
+
connection_id,
|
|
64
|
+
user_id,
|
|
65
|
+
file_list,
|
|
66
|
+
jwt_token,
|
|
67
|
+
file_infos=file_infos,
|
|
68
|
+
ingest_settings=ingest_settings,
|
|
58
69
|
)
|
|
59
70
|
|
|
60
71
|
def __getattr__(self, name):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, List, Optional
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
2
|
|
|
3
3
|
from fastapi import Depends, Request
|
|
4
4
|
from pydantic import BaseModel
|
|
@@ -93,6 +93,8 @@ class ConnectorSyncBody(BaseModel):
|
|
|
93
93
|
sync_all: bool = False
|
|
94
94
|
# When set, only ingest files from these buckets (IBM COS specific).
|
|
95
95
|
bucket_filter: Optional[List[str]] = None
|
|
96
|
+
# Per-request ingest options from the connector upload UI (overrides saved Knowledge for this sync).
|
|
97
|
+
settings: Optional[Dict[str, Any]] = None
|
|
96
98
|
|
|
97
99
|
|
|
98
100
|
async def list_connectors(
|
|
@@ -106,7 +108,7 @@ async def list_connectors(
|
|
|
106
108
|
)
|
|
107
109
|
return JSONResponse({"connectors": connector_types})
|
|
108
110
|
except Exception as e:
|
|
109
|
-
logger.
|
|
111
|
+
logger.error("[CONNECTOR] Error listing connectors", error=str(e))
|
|
110
112
|
return JSONResponse({"connectors": []})
|
|
111
113
|
|
|
112
114
|
|
|
@@ -197,13 +199,14 @@ async def connector_sync(
|
|
|
197
199
|
if selected_files:
|
|
198
200
|
# Explicit files selected (e.g., from file picker) - sync those specific files
|
|
199
201
|
from .documents import _ensure_index_exists
|
|
200
|
-
await _ensure_index_exists()
|
|
202
|
+
await _ensure_index_exists(jwt_token)
|
|
201
203
|
task_id = await connector_service.sync_specific_files(
|
|
202
204
|
working_connection.connection_id,
|
|
203
205
|
user.user_id,
|
|
204
206
|
selected_files,
|
|
205
207
|
jwt_token=jwt_token,
|
|
206
208
|
file_infos=file_infos,
|
|
209
|
+
ingest_settings=body.settings,
|
|
207
210
|
)
|
|
208
211
|
elif body.sync_all or body.bucket_filter:
|
|
209
212
|
# Full ingest: discover and ingest all files (or files from specific buckets).
|
|
@@ -241,6 +244,7 @@ async def connector_sync(
|
|
|
241
244
|
user.user_id,
|
|
242
245
|
all_file_ids,
|
|
243
246
|
jwt_token=jwt_token,
|
|
247
|
+
ingest_settings=body.settings,
|
|
244
248
|
)
|
|
245
249
|
else:
|
|
246
250
|
# sync_all: ingest everything the connector can see
|
|
@@ -549,15 +553,10 @@ async def connector_webhook(
|
|
|
549
553
|
)
|
|
550
554
|
|
|
551
555
|
except Exception as e:
|
|
552
|
-
logger.
|
|
553
|
-
"Failed to process webhook
|
|
556
|
+
logger.exception(
|
|
557
|
+
"[CONNECTOR] Failed to process webhook",
|
|
554
558
|
connection_id=connection.connection_id,
|
|
555
|
-
error=str(e),
|
|
556
559
|
)
|
|
557
|
-
import traceback
|
|
558
|
-
|
|
559
|
-
traceback.print_exc()
|
|
560
|
-
|
|
561
560
|
return JSONResponse(
|
|
562
561
|
{
|
|
563
562
|
"status": "error",
|
|
@@ -99,10 +99,16 @@ async def delete_documents_by_filename_core(
|
|
|
99
99
|
)
|
|
100
100
|
|
|
101
101
|
|
|
102
|
-
async def _ensure_index_exists():
|
|
102
|
+
async def _ensure_index_exists(jwt_token: str = None):
|
|
103
103
|
"""Create the OpenSearch index if it doesn't exist yet."""
|
|
104
104
|
from main import init_index
|
|
105
|
-
|
|
105
|
+
from config.settings import IBM_AUTH_ENABLED, clients as app_clients
|
|
106
|
+
|
|
107
|
+
opensearch_client = None
|
|
108
|
+
if IBM_AUTH_ENABLED and jwt_token:
|
|
109
|
+
opensearch_client = app_clients.create_user_opensearch_client(jwt_token)
|
|
110
|
+
|
|
111
|
+
await init_index(opensearch_client)
|
|
106
112
|
|
|
107
113
|
|
|
108
114
|
async def check_filename_exists(
|
|
@@ -144,7 +150,7 @@ async def check_filename_exists(
|
|
|
144
150
|
except Exception as search_err:
|
|
145
151
|
if "index_not_found_exception" in str(search_err):
|
|
146
152
|
logger.info("Index does not exist, creating it now before upload")
|
|
147
|
-
await _ensure_index_exists()
|
|
153
|
+
await _ensure_index_exists(jwt_token)
|
|
148
154
|
return JSONResponse({"exists": False, "filename": filename}, status_code=200)
|
|
149
155
|
raise
|
|
150
156
|
|
|
@@ -418,12 +418,9 @@ async def knowledge_filter_webhook(
|
|
|
418
418
|
)
|
|
419
419
|
|
|
420
420
|
except Exception as e:
|
|
421
|
-
logger.
|
|
422
|
-
"
|
|
421
|
+
logger.exception(
|
|
422
|
+
"[API] Knowledge filter webhook failed",
|
|
423
423
|
filter_id=filter_id,
|
|
424
424
|
subscription_id=subscription_id,
|
|
425
|
-
error=str(e),
|
|
426
425
|
)
|
|
427
|
-
import traceback
|
|
428
|
-
traceback.print_exc()
|
|
429
426
|
return JSONResponse({"error": f"Webhook processing failed: {str(e)}"}, status_code=500)
|
|
@@ -316,7 +316,7 @@ async def _test_openai_completion_with_tools(api_key: str, llm_model: str) -> No
|
|
|
316
316
|
|
|
317
317
|
# If max_tokens doesn't work, try with max_completion_tokens
|
|
318
318
|
if response.status_code != 200:
|
|
319
|
-
logger.
|
|
319
|
+
logger.warning("[API] max_tokens parameter failed, trying max_completion_tokens instead")
|
|
320
320
|
payload = {**base_payload, "max_completion_tokens": 50}
|
|
321
321
|
response = await client.post(
|
|
322
322
|
"https://api.openai.com/v1/chat/completions",
|
|
@@ -454,7 +454,7 @@ async def _test_watsonx_completion_with_tools(
|
|
|
454
454
|
|
|
455
455
|
# Test completion with tools
|
|
456
456
|
url = f"{endpoint}/ml/v1/text/chat"
|
|
457
|
-
params = {"version": "
|
|
457
|
+
params = {"version": "2026-04-15"}
|
|
458
458
|
payload = {
|
|
459
459
|
"model_id": llm_model,
|
|
460
460
|
"project_id": project_id,
|
|
@@ -549,7 +549,7 @@ async def _test_watsonx_embedding(
|
|
|
549
549
|
|
|
550
550
|
# Test embedding
|
|
551
551
|
url = f"{endpoint}/ml/v1/text/embeddings"
|
|
552
|
-
params = {"version": "
|
|
552
|
+
params = {"version": "2026-04-15"}
|
|
553
553
|
payload = {
|
|
554
554
|
"model_id": embedding_model,
|
|
555
555
|
"project_id": project_id,
|