Compare commits
No commits in common. "main" and "gh-pages" have entirely different histories.
607 changed files with 3907 additions and 135594 deletions
|
|
@ -1,49 +0,0 @@
|
||||||
# Environment files
|
|
||||||
.env
|
|
||||||
.env.local
|
|
||||||
.env.development
|
|
||||||
.env.production
|
|
||||||
|
|
||||||
# Auth files
|
|
||||||
.drive.json
|
|
||||||
*.json
|
|
||||||
|
|
||||||
# Dependencies
|
|
||||||
node_modules/
|
|
||||||
*/node_modules/
|
|
||||||
**/node_modules/
|
|
||||||
|
|
||||||
# Python cache
|
|
||||||
__pycache__/
|
|
||||||
*/__pycache__/
|
|
||||||
**/__pycache__/
|
|
||||||
*.pyc
|
|
||||||
*.pyo
|
|
||||||
*.pyd
|
|
||||||
.Python
|
|
||||||
|
|
||||||
# Build outputs
|
|
||||||
build/
|
|
||||||
dist/
|
|
||||||
.next/
|
|
||||||
out/
|
|
||||||
|
|
||||||
# Development files
|
|
||||||
.git/
|
|
||||||
.gitignore
|
|
||||||
README.md
|
|
||||||
*.md
|
|
||||||
.vscode/
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
*.log
|
|
||||||
logs/
|
|
||||||
|
|
||||||
# OS files
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# Temporary files
|
|
||||||
tmp/
|
|
||||||
temp/
|
|
||||||
88
.env.example
88
.env.example
|
|
@ -1,88 +0,0 @@
|
||||||
# Ingestion Configuration
|
|
||||||
# Set to true to disable Langflow ingestion and use traditional OpenRAG processor
|
|
||||||
# If unset or false, Langflow pipeline will be used (default: upload -> ingest -> delete)
|
|
||||||
DISABLE_INGEST_WITH_LANGFLOW=false
|
|
||||||
|
|
||||||
# Langflow HTTP timeout configuration (in seconds)
|
|
||||||
# For large documents (300+ pages), ingestion can take 30+ minutes
|
|
||||||
# Increase these values if you experience timeouts with very large PDFs
|
|
||||||
# Default: 2400 seconds (40 minutes) total timeout, 30 seconds connection timeout
|
|
||||||
# LANGFLOW_TIMEOUT=2400
|
|
||||||
# LANGFLOW_CONNECT_TIMEOUT=30
|
|
||||||
|
|
||||||
# make one like so https://docs.langflow.org/api-keys-and-authentication#langflow-secret-key
|
|
||||||
LANGFLOW_SECRET_KEY=
|
|
||||||
|
|
||||||
# flow ids for chat and ingestion flows
|
|
||||||
LANGFLOW_CHAT_FLOW_ID=1098eea1-6649-4e1d-aed1-b77249fb8dd0
|
|
||||||
LANGFLOW_INGEST_FLOW_ID=5488df7c-b93f-4f87-a446-b67028bc0813
|
|
||||||
LANGFLOW_URL_INGEST_FLOW_ID=72c3d17c-2dac-4a73-b48a-6518473d7830
|
|
||||||
# Ingest flow using docling
|
|
||||||
# LANGFLOW_INGEST_FLOW_ID=1402618b-e6d1-4ff2-9a11-d6ce71186915
|
|
||||||
NUDGES_FLOW_ID=ebc01d31-1976-46ce-a385-b0240327226c
|
|
||||||
|
|
||||||
# Set a strong admin password for OpenSearch; a bcrypt hash is generated at
|
|
||||||
# container startup from this value. Do not commit real secrets.
|
|
||||||
# must match the hashed password in secureconfig, must change for secure deployment!!!
|
|
||||||
# NOTE: if you set this by hand, it must be a complex password:
|
|
||||||
# The password must contain at least 8 characters, and must contain at least one uppercase letter, one lowercase letter, one digit, and one special character.
|
|
||||||
OPENSEARCH_PASSWORD=
|
|
||||||
|
|
||||||
# Path to persist OpenSearch data (indices, documents, cluster state)
|
|
||||||
# Default: ./opensearch-data
|
|
||||||
OPENSEARCH_DATA_PATH=./opensearch-data
|
|
||||||
|
|
||||||
# make here https://console.cloud.google.com/apis/credentials
|
|
||||||
GOOGLE_OAUTH_CLIENT_ID=
|
|
||||||
GOOGLE_OAUTH_CLIENT_SECRET=
|
|
||||||
|
|
||||||
# Azure app registration credentials for SharePoint/OneDrive
|
|
||||||
MICROSOFT_GRAPH_OAUTH_CLIENT_ID=
|
|
||||||
MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET=
|
|
||||||
|
|
||||||
# AWS Access Key ID and Secret Access Key with access to your S3 instance
|
|
||||||
AWS_ACCESS_KEY_ID=
|
|
||||||
AWS_SECRET_ACCESS_KEY=
|
|
||||||
|
|
||||||
# OPTIONAL: dns routable from google (etc.) to handle continous ingest (something like ngrok works). This enables continous ingestion
|
|
||||||
WEBHOOK_BASE_URL=
|
|
||||||
|
|
||||||
# Model Provider API Keys
|
|
||||||
OPENAI_API_KEY=
|
|
||||||
ANTHROPIC_API_KEY=
|
|
||||||
OLLAMA_ENDPOINT=
|
|
||||||
WATSONX_API_KEY=
|
|
||||||
WATSONX_ENDPOINT=
|
|
||||||
WATSONX_PROJECT_ID=
|
|
||||||
|
|
||||||
# LLM Provider configuration. Providers can be "anthropic", "watsonx", "ibm" or "ollama".
|
|
||||||
LLM_PROVIDER=
|
|
||||||
LLM_MODEL=
|
|
||||||
|
|
||||||
# Embedding provider configuration. Providers can be "watsonx", "ibm" or "ollama".
|
|
||||||
EMBEDDING_PROVIDER=
|
|
||||||
EMBEDDING_MODEL=
|
|
||||||
|
|
||||||
# OPTIONAL url for openrag link to langflow in the UI
|
|
||||||
LANGFLOW_PUBLIC_URL=
|
|
||||||
|
|
||||||
# OPTIONAL: Override the full docling-serve URL (e.g., for remote instances)
|
|
||||||
# If not set, auto-detects host and uses port 5001
|
|
||||||
# DOCLING_SERVE_URL=http://my-docling-server:5001
|
|
||||||
|
|
||||||
# OPTIONAL: Override host for docling service (for special networking setups)
|
|
||||||
# HOST_DOCKER_INTERNAL=host.containers.internal
|
|
||||||
|
|
||||||
# Langflow auth
|
|
||||||
LANGFLOW_AUTO_LOGIN=False
|
|
||||||
LANGFLOW_SUPERUSER=
|
|
||||||
LANGFLOW_SUPERUSER_PASSWORD=
|
|
||||||
LANGFLOW_NEW_USER_IS_ACTIVE=False
|
|
||||||
LANGFLOW_ENABLE_SUPERUSER_CLI=False
|
|
||||||
|
|
||||||
# Langfuse tracing (optional)
|
|
||||||
# Get keys from https://cloud.langfuse.com or your self-hosted instance
|
|
||||||
LANGFUSE_SECRET_KEY=
|
|
||||||
LANGFUSE_PUBLIC_KEY=
|
|
||||||
# Leave empty for Langfuse Cloud, or set for self-hosted (e.g., http://localhost:3002)
|
|
||||||
LANGFUSE_HOST=
|
|
||||||
155
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
155
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -1,155 +0,0 @@
|
||||||
name: Bug Report
|
|
||||||
description: Report a bug or unexpected behavior in OpenRAG
|
|
||||||
title: "[Bug]: "
|
|
||||||
labels: ["bug"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to report a bug! Please fill out the form below to help us understand and fix the issue.
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: openrag-version
|
|
||||||
attributes:
|
|
||||||
label: OpenRAG Version
|
|
||||||
description: What version of OpenRAG are you using? Run `openrag --version` or check your package version.
|
|
||||||
placeholder: "e.g., 0.1.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: deployment-method
|
|
||||||
attributes:
|
|
||||||
label: Deployment Method
|
|
||||||
description: How are you running OpenRAG?
|
|
||||||
options:
|
|
||||||
- uvx (uvx openrag)
|
|
||||||
- uv add (installed in project)
|
|
||||||
- Docker
|
|
||||||
- Podman
|
|
||||||
- Local development (make dev)
|
|
||||||
- Other
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: os
|
|
||||||
attributes:
|
|
||||||
label: Operating System
|
|
||||||
description: What operating system are you using?
|
|
||||||
placeholder: "e.g., macOS 14.0, Ubuntu 22.04, Windows 11"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: python-version
|
|
||||||
attributes:
|
|
||||||
label: Python Version
|
|
||||||
description: What Python version are you using? Run `python --version` to check.
|
|
||||||
placeholder: "e.g., 3.13.0"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: affected-area
|
|
||||||
attributes:
|
|
||||||
label: Affected Area
|
|
||||||
description: Which area(s) of OpenRAG does this bug affect? Select all that apply.
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Ingestion (document processing, upload, Docling)
|
|
||||||
- Retrieval (search, OpenSearch, hybrid search)
|
|
||||||
- Chat (chat interface, conversations, AI responses)
|
|
||||||
- Knowledge Filters (partitions, document filtering)
|
|
||||||
- Settings (configuration, model providers)
|
|
||||||
- TUI (Terminal User Interface)
|
|
||||||
- Connectors (Google Drive, OneDrive, SharePoint)
|
|
||||||
- Frontend (Next.js UI, components)
|
|
||||||
- Backend/API (Python/Starlette)
|
|
||||||
- Infrastructure (Docker, OpenSearch, Langflow)
|
|
||||||
- SDK (Python or TypeScript SDK)
|
|
||||||
- Onboarding (setup wizard, initial configuration)
|
|
||||||
- Authentication (OIDC, API keys)
|
|
||||||
- Other
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: bug-description
|
|
||||||
attributes:
|
|
||||||
label: Bug Description
|
|
||||||
description: A clear and concise description of what the bug is.
|
|
||||||
placeholder: Describe the bug...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: steps-to-reproduce
|
|
||||||
attributes:
|
|
||||||
label: Steps to Reproduce
|
|
||||||
description: Steps to reproduce the behavior.
|
|
||||||
placeholder: |
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '...'
|
|
||||||
3. Scroll down to '...'
|
|
||||||
4. See error
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: expected-behavior
|
|
||||||
attributes:
|
|
||||||
label: Expected Behavior
|
|
||||||
description: A clear and concise description of what you expected to happen.
|
|
||||||
placeholder: What should have happened?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: actual-behavior
|
|
||||||
attributes:
|
|
||||||
label: Actual Behavior
|
|
||||||
description: A clear and concise description of what actually happened.
|
|
||||||
placeholder: What actually happened?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant Logs
|
|
||||||
description: |
|
|
||||||
Please copy and paste any relevant log output.
|
|
||||||
You can get logs using `make logs` for Docker deployments or check the terminal output.
|
|
||||||
This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: screenshots
|
|
||||||
attributes:
|
|
||||||
label: Screenshots
|
|
||||||
description: If applicable, add screenshots to help explain your problem.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: additional-context
|
|
||||||
attributes:
|
|
||||||
label: Additional Context
|
|
||||||
description: Add any other context about the problem here (e.g., browser version, specific document types, model provider being used).
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: checklist
|
|
||||||
attributes:
|
|
||||||
label: Checklist
|
|
||||||
description: Please confirm the following before submitting.
|
|
||||||
options:
|
|
||||||
- label: I have searched existing issues to ensure this bug hasn't been reported before.
|
|
||||||
required: true
|
|
||||||
- label: I have provided all the requested information.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
15
.github/ISSUE_TEMPLATE/config.yml
vendored
15
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: OpenRAG Documentation
|
|
||||||
url: https://docs.openr.ag/
|
|
||||||
about: Learn more about OpenRAG's features, installation, and configuration.
|
|
||||||
- name: Troubleshooting Guide
|
|
||||||
url: https://docs.openr.ag/support/troubleshoot
|
|
||||||
about: Check the troubleshooting guide for common issues and solutions.
|
|
||||||
- name: GitHub Discussions
|
|
||||||
url: https://github.com/langflow-ai/openrag/discussions
|
|
||||||
about: Ask questions and discuss ideas with the community.
|
|
||||||
- name: Contributing Guide
|
|
||||||
url: https://github.com/langflow-ai/openrag/blob/main/CONTRIBUTING.md
|
|
||||||
about: Learn how to contribute to OpenRAG development.
|
|
||||||
|
|
||||||
106
.github/ISSUE_TEMPLATE/documentation.yml
vendored
106
.github/ISSUE_TEMPLATE/documentation.yml
vendored
|
|
@ -1,106 +0,0 @@
|
||||||
name: Documentation Issue
|
|
||||||
description: Report an issue with documentation or request new documentation
|
|
||||||
title: "[Docs]: "
|
|
||||||
labels: ["documentation"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for helping improve OpenRAG's documentation! Please provide details about the issue or your request.
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: issue-type
|
|
||||||
attributes:
|
|
||||||
label: Issue Type
|
|
||||||
description: What type of documentation issue is this?
|
|
||||||
options:
|
|
||||||
- Incorrect information
|
|
||||||
- Missing documentation
|
|
||||||
- Outdated content
|
|
||||||
- Unclear or confusing
|
|
||||||
- Typo or grammatical error
|
|
||||||
- Broken links
|
|
||||||
- Request for new documentation
|
|
||||||
- Other
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: doc-area
|
|
||||||
attributes:
|
|
||||||
label: Documentation Area
|
|
||||||
description: Which area of documentation does this relate to?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Getting Started / Quickstart
|
|
||||||
- Installation (uvx, Docker, Podman)
|
|
||||||
- Configuration / Settings
|
|
||||||
- Ingestion & Document Processing
|
|
||||||
- Search & Retrieval
|
|
||||||
- Chat Interface
|
|
||||||
- Knowledge Filters
|
|
||||||
- Connectors (Google Drive, OneDrive, SharePoint)
|
|
||||||
- TUI (Terminal User Interface)
|
|
||||||
- API Reference
|
|
||||||
- SDK Documentation (Python/TypeScript)
|
|
||||||
- Troubleshooting
|
|
||||||
- Contributing Guide
|
|
||||||
- Other
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: doc-url
|
|
||||||
attributes:
|
|
||||||
label: Documentation URL
|
|
||||||
description: If applicable, provide a link to the specific documentation page.
|
|
||||||
placeholder: "https://docs.openr.ag/..."
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: current-content
|
|
||||||
attributes:
|
|
||||||
label: Current Content
|
|
||||||
description: If reporting an issue, what does the documentation currently say?
|
|
||||||
placeholder: Quote or describe the current documentation content.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: issue-description
|
|
||||||
attributes:
|
|
||||||
label: Issue Description
|
|
||||||
description: Describe the problem or what documentation you'd like to see added.
|
|
||||||
placeholder: |
|
|
||||||
For issues: Explain what's wrong or confusing about the current documentation.
|
|
||||||
For requests: Describe what topic you'd like documented and why it would be helpful.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: suggested-content
|
|
||||||
attributes:
|
|
||||||
label: Suggested Content
|
|
||||||
description: If you have suggestions for how to fix or improve the documentation, please share them.
|
|
||||||
placeholder: Provide suggested text, corrections, or an outline for new documentation.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: additional-context
|
|
||||||
attributes:
|
|
||||||
label: Additional Context
|
|
||||||
description: Add any other context, screenshots, or examples here.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: contribution
|
|
||||||
attributes:
|
|
||||||
label: Contribution
|
|
||||||
description: Would you be interested in contributing to fix this documentation issue?
|
|
||||||
options:
|
|
||||||
- label: I would be willing to submit a pull request to fix this issue.
|
|
||||||
required: false
|
|
||||||
|
|
||||||
113
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
113
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
|
|
@ -1,113 +0,0 @@
|
||||||
name: Feature Request
|
|
||||||
description: Suggest a new feature or enhancement for OpenRAG
|
|
||||||
title: "[Feature]: "
|
|
||||||
labels: ["enhancement"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for suggesting a feature! Please provide as much detail as possible to help us understand your request.
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: feature-area
|
|
||||||
attributes:
|
|
||||||
label: Feature Area
|
|
||||||
description: Which area(s) of OpenRAG does this feature relate to?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Ingestion (document processing, upload, Docling)
|
|
||||||
- Retrieval (search, OpenSearch, hybrid search)
|
|
||||||
- Chat (chat interface, conversations, AI responses)
|
|
||||||
- Knowledge Filters (partitions, document filtering)
|
|
||||||
- Settings (configuration, model providers)
|
|
||||||
- TUI (Terminal User Interface)
|
|
||||||
- Connectors (Google Drive, OneDrive, SharePoint)
|
|
||||||
- Frontend (Next.js UI, components)
|
|
||||||
- Backend/API (Python/Starlette)
|
|
||||||
- Infrastructure (Docker, OpenSearch, Langflow)
|
|
||||||
- SDK (Python or TypeScript SDK)
|
|
||||||
- Onboarding (setup wizard, initial configuration)
|
|
||||||
- Authentication (OIDC, API keys)
|
|
||||||
- New Area
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: problem-description
|
|
||||||
attributes:
|
|
||||||
label: Problem Description
|
|
||||||
description: Is your feature request related to a problem? Please describe.
|
|
||||||
placeholder: A clear and concise description of what the problem is. E.g., "I'm always frustrated when..."
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: proposed-solution
|
|
||||||
attributes:
|
|
||||||
label: Proposed Solution
|
|
||||||
description: Describe the solution you'd like to see implemented.
|
|
||||||
placeholder: A clear and concise description of what you want to happen.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: use-case
|
|
||||||
attributes:
|
|
||||||
label: Use Case
|
|
||||||
description: Describe your use case and how this feature would benefit you or others.
|
|
||||||
placeholder: |
|
|
||||||
As a [type of user], I want [goal] so that [benefit].
|
|
||||||
|
|
||||||
Example: As a developer, I want to filter documents by custom metadata so that I can organize my knowledge base more effectively.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: alternatives
|
|
||||||
attributes:
|
|
||||||
label: Alternatives Considered
|
|
||||||
description: Describe any alternative solutions or features you've considered.
|
|
||||||
placeholder: What other approaches have you thought about? Why wouldn't they work as well?
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: priority
|
|
||||||
attributes:
|
|
||||||
label: Priority
|
|
||||||
description: How important is this feature to your workflow?
|
|
||||||
options:
|
|
||||||
- Nice to have
|
|
||||||
- Would improve my workflow
|
|
||||||
- Critical for my use case
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: additional-context
|
|
||||||
attributes:
|
|
||||||
label: Additional Context
|
|
||||||
description: Add any other context, mockups, screenshots, or examples about the feature request here.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: contribution
|
|
||||||
attributes:
|
|
||||||
label: Contribution
|
|
||||||
description: Would you be interested in contributing to this feature?
|
|
||||||
options:
|
|
||||||
- label: I would be willing to help implement this feature.
|
|
||||||
required: false
|
|
||||||
- label: I can help test this feature once implemented.
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: checklist
|
|
||||||
attributes:
|
|
||||||
label: Checklist
|
|
||||||
description: Please confirm the following before submitting.
|
|
||||||
options:
|
|
||||||
- label: I have searched existing issues and discussions to ensure this feature hasn't been requested before.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
11
.github/dependabot.yml
vendored
11
.github/dependabot.yml
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
version: 2
|
|
||||||
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "monthly"
|
|
||||||
commit-message:
|
|
||||||
prefix: "build(deps):"
|
|
||||||
include: scope
|
|
||||||
|
|
||||||
253
.github/workflows/build-multiarch.yml
vendored
253
.github/workflows/build-multiarch.yml
vendored
|
|
@ -1,253 +0,0 @@
|
||||||
name: Release + Docker Images (multi-arch)
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'pyproject.toml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-version:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
skip_release: ${{ steps.version.outputs.skip_release }}
|
|
||||||
version: ${{ steps.version.outputs.version }}
|
|
||||||
docker_version: ${{ steps.version.outputs.docker_version }}
|
|
||||||
is_prerelease: ${{ steps.version.outputs.is_prerelease }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Extract version from pyproject.toml
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
VERSION=$(grep '^version = ' pyproject.toml | cut -d '"' -f 2)
|
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
echo "Version: $VERSION"
|
|
||||||
|
|
||||||
# Normalize version per PEP 440 for Docker tags
|
|
||||||
# e.g., "0.1.53-rc2" -> "0.1.53rc2" to match Python's importlib.metadata
|
|
||||||
DOCKER_VERSION=$(echo "$VERSION" | sed -E 's/-?(rc|alpha|beta|dev|post)/\1/g')
|
|
||||||
echo "docker_version=$DOCKER_VERSION" >> $GITHUB_OUTPUT
|
|
||||||
echo "Docker Version: $DOCKER_VERSION"
|
|
||||||
|
|
||||||
# Check if tag already exists
|
|
||||||
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
|
|
||||||
echo "Tag v$VERSION already exists, skipping release"
|
|
||||||
echo "skip_release=true" >> $GITHUB_OUTPUT
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo "skip_release=false" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# Check if version is numeric (e.g., 0.1.16) vs prerelease (e.g., 0.1.16-rc1)
|
|
||||||
if [[ "$VERSION" =~ ^[0-9.-]+$ ]]; then
|
|
||||||
echo "is_prerelease=false" >> $GITHUB_OUTPUT
|
|
||||||
echo "Release type: Production"
|
|
||||||
else
|
|
||||||
echo "is_prerelease=true" >> $GITHUB_OUTPUT
|
|
||||||
echo "Release type: Prerelease"
|
|
||||||
fi
|
|
||||||
|
|
||||||
build:
|
|
||||||
needs: check-version
|
|
||||||
if: needs.check-version.outputs.skip_release != 'true'
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
# backend
|
|
||||||
- image: backend
|
|
||||||
file: ./Dockerfile.backend
|
|
||||||
tag: langflowai/openrag-backend
|
|
||||||
platform: linux/amd64
|
|
||||||
arch: amd64
|
|
||||||
runs-on: ubuntu-latest-16-cores
|
|
||||||
- image: backend
|
|
||||||
file: ./Dockerfile.backend
|
|
||||||
tag: langflowai/openrag-backend
|
|
||||||
platform: linux/arm64
|
|
||||||
arch: arm64
|
|
||||||
runs-on: [self-hosted, Linux, ARM64, langflow-ai-arm64-40gb-ephemeral]
|
|
||||||
|
|
||||||
# frontend
|
|
||||||
- image: frontend
|
|
||||||
file: ./Dockerfile.frontend
|
|
||||||
tag: langflowai/openrag-frontend
|
|
||||||
platform: linux/amd64
|
|
||||||
arch: amd64
|
|
||||||
runs-on: ubuntu-latest-16-cores
|
|
||||||
- image: frontend
|
|
||||||
file: ./Dockerfile.frontend
|
|
||||||
tag: langflowai/openrag-frontend
|
|
||||||
platform: linux/arm64
|
|
||||||
arch: arm64
|
|
||||||
runs-on: [self-hosted, Linux, ARM64, langflow-ai-arm64-40gb-ephemeral]
|
|
||||||
|
|
||||||
# langflow
|
|
||||||
- image: langflow
|
|
||||||
file: ./Dockerfile.langflow
|
|
||||||
tag: langflowai/openrag-langflow
|
|
||||||
platform: linux/amd64
|
|
||||||
arch: amd64
|
|
||||||
runs-on: ubuntu-latest-16-cores
|
|
||||||
- image: langflow
|
|
||||||
file: ./Dockerfile.langflow
|
|
||||||
tag: langflowai/openrag-langflow
|
|
||||||
platform: linux/arm64
|
|
||||||
arch: arm64
|
|
||||||
runs-on: [self-hosted, Linux, ARM64, langflow-ai-arm64-40gb-ephemeral]
|
|
||||||
|
|
||||||
# opensearch
|
|
||||||
- image: opensearch
|
|
||||||
file: ./Dockerfile
|
|
||||||
tag: langflowai/openrag-opensearch
|
|
||||||
platform: linux/amd64
|
|
||||||
arch: amd64
|
|
||||||
runs-on: ubuntu-latest-16-cores
|
|
||||||
- image: opensearch
|
|
||||||
file: ./Dockerfile
|
|
||||||
tag: langflowai/openrag-opensearch
|
|
||||||
platform: linux/arm64
|
|
||||||
arch: arm64
|
|
||||||
runs-on: [self-hosted, Linux, ARM64, langflow-ai-arm64-40gb-ephemeral]
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.runs-on }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Build and push ${{ matrix.image }} (${{ matrix.arch }})
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ${{ matrix.file }}
|
|
||||||
platforms: ${{ matrix.platform }}
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ matrix.tag }}:${{ needs.check-version.outputs.docker_version }}-${{ matrix.arch }}
|
|
||||||
cache-from: type=gha,scope=${{ matrix.image }}-${{ matrix.arch }}
|
|
||||||
cache-to: type=gha,mode=max,scope=${{ matrix.image }}-${{ matrix.arch }}
|
|
||||||
|
|
||||||
manifest:
|
|
||||||
needs: [build, check-version]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name != 'pull_request' && needs.check-version.outputs.skip_release != 'true'
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Create and push multi-arch manifests
|
|
||||||
run: |
|
|
||||||
VERSION=${{ needs.check-version.outputs.docker_version }}
|
|
||||||
|
|
||||||
# Create versioned tags
|
|
||||||
docker buildx imagetools create -t langflowai/openrag-backend:$VERSION \
|
|
||||||
langflowai/openrag-backend:$VERSION-amd64 \
|
|
||||||
langflowai/openrag-backend:$VERSION-arm64
|
|
||||||
|
|
||||||
docker buildx imagetools create -t langflowai/openrag-frontend:$VERSION \
|
|
||||||
langflowai/openrag-frontend:$VERSION-amd64 \
|
|
||||||
langflowai/openrag-frontend:$VERSION-arm64
|
|
||||||
|
|
||||||
docker buildx imagetools create -t langflowai/openrag-langflow:$VERSION \
|
|
||||||
langflowai/openrag-langflow:$VERSION-amd64 \
|
|
||||||
langflowai/openrag-langflow:$VERSION-arm64
|
|
||||||
|
|
||||||
docker buildx imagetools create -t langflowai/openrag-opensearch:$VERSION \
|
|
||||||
langflowai/openrag-opensearch:$VERSION-amd64 \
|
|
||||||
langflowai/openrag-opensearch:$VERSION-arm64
|
|
||||||
|
|
||||||
# Only update latest tags if version is numeric
|
|
||||||
if [[ "$VERSION" =~ ^[0-9.-]+$ ]]; then
|
|
||||||
echo "Updating latest tags for production release: $VERSION"
|
|
||||||
docker buildx imagetools create -t langflowai/openrag-backend:latest \
|
|
||||||
langflowai/openrag-backend:$VERSION-amd64 \
|
|
||||||
langflowai/openrag-backend:$VERSION-arm64
|
|
||||||
|
|
||||||
docker buildx imagetools create -t langflowai/openrag-frontend:latest \
|
|
||||||
langflowai/openrag-frontend:$VERSION-amd64 \
|
|
||||||
langflowai/openrag-frontend:$VERSION-arm64
|
|
||||||
|
|
||||||
docker buildx imagetools create -t langflowai/openrag-langflow:latest \
|
|
||||||
langflowai/openrag-langflow:$VERSION-amd64 \
|
|
||||||
langflowai/openrag-langflow:$VERSION-arm64
|
|
||||||
|
|
||||||
docker buildx imagetools create -t langflowai/openrag-opensearch:latest \
|
|
||||||
langflowai/openrag-opensearch:$VERSION-amd64 \
|
|
||||||
langflowai/openrag-opensearch:$VERSION-arm64
|
|
||||||
else
|
|
||||||
echo "Skipping latest tags - version: $VERSION (not numeric)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
build-python-packages:
|
|
||||||
needs: [manifest, check-version]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: needs.check-version.outputs.skip_release != 'true'
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: '3.13'
|
|
||||||
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v3
|
|
||||||
|
|
||||||
- name: Build wheel and source distribution
|
|
||||||
run: |
|
|
||||||
uv build
|
|
||||||
|
|
||||||
- name: List built artifacts
|
|
||||||
run: |
|
|
||||||
ls -la dist/
|
|
||||||
echo "Built artifacts:"
|
|
||||||
for file in dist/*; do
|
|
||||||
echo " - $(basename $file) ($(stat -c%s $file | numfmt --to=iec-i)B)"
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: python-packages
|
|
||||||
path: dist/
|
|
||||||
retention-days: 30
|
|
||||||
|
|
||||||
- name: Create Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
tag_name: v${{ needs.check-version.outputs.version }}
|
|
||||||
name: Release ${{ needs.check-version.outputs.version }}
|
|
||||||
draft: false
|
|
||||||
prerelease: ${{ needs.check-version.outputs.is_prerelease }}
|
|
||||||
generate_release_notes: true
|
|
||||||
files: |
|
|
||||||
dist/*.whl
|
|
||||||
dist/*.tar.gz
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Publish to PyPI
|
|
||||||
run: |
|
|
||||||
uv publish
|
|
||||||
env:
|
|
||||||
UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN }}
|
|
||||||
66
.github/workflows/codeql.yml
vendored
66
.github/workflows/codeql.yml
vendored
|
|
@ -1,66 +0,0 @@
|
||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ 'main' ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ 'main' ]
|
|
||||||
schedule:
|
|
||||||
- cron: '17 2 * * 1'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
|
||||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'python', 'javascript' ]
|
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
|
||||||
# Use only 'java' to analyze code written in Java, Kotlin or both
|
|
||||||
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
|
||||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
||||||
# By default, queries listed here will override any specified in a config file.
|
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
||||||
|
|
||||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
||||||
# queries: security-extended,security-and-quality
|
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
|
||||||
- name: Autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v3
|
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
||||||
|
|
||||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
|
||||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
|
||||||
|
|
||||||
# - run: |
|
|
||||||
# echo "Run, Build Application using script"
|
|
||||||
# ./location_of_script_within_repo/buildscript.sh
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
|
|
||||||
60
.github/workflows/dependency-audit.yml
vendored
60
.github/workflows/dependency-audit.yml
vendored
|
|
@ -1,60 +0,0 @@
|
||||||
name: Dependency Audit
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
# Run Monday, Thursday at 9am UTC
|
|
||||||
- cron: '0 9 * * 1,4'
|
|
||||||
workflow_dispatch: # Allow manual trigger
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
npm-audit:
|
|
||||||
name: NPM Audit
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
directory: ['frontend', 'docs', 'sdks/typescript']
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
|
|
||||||
- name: Run npm audit
|
|
||||||
working-directory: ${{ matrix.directory }}
|
|
||||||
run: |
|
|
||||||
echo "::group::NPM Audit for ${{ matrix.directory }}"
|
|
||||||
npm audit --audit-level=moderate || echo "::warning::NPM audit found vulnerabilities in ${{ matrix.directory }}"
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
- name: Check for outdated packages
|
|
||||||
working-directory: ${{ matrix.directory }}
|
|
||||||
run: |
|
|
||||||
echo "::group::Outdated packages in ${{ matrix.directory }}"
|
|
||||||
npm outdated || true
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
python-audit:
|
|
||||||
name: Python Audit
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
directory: ['.', 'sdks/python']
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Install pip-audit
|
|
||||||
run: pip install pip-audit
|
|
||||||
|
|
||||||
- name: Run pip-audit
|
|
||||||
working-directory: ${{ matrix.directory }}
|
|
||||||
run: |
|
|
||||||
echo "::group::Python Audit for ${{ matrix.directory }}"
|
|
||||||
pip-audit --desc || echo "::warning::pip-audit found vulnerabilities in ${{ matrix.directory }}"
|
|
||||||
echo "::endgroup::"
|
|
||||||
266
.github/workflows/deploy-docs-draft.yml
vendored
266
.github/workflows/deploy-docs-draft.yml
vendored
|
|
@ -1,266 +0,0 @@
|
||||||
name: Pull Request Docs Draft
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- '**'
|
|
||||||
paths:
|
|
||||||
- 'docs/**'
|
|
||||||
- '.github/workflows/deploy-docs-draft.yml'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: "! github.event.pull_request.head.repo.fork"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20.20.0
|
|
||||||
cache: npm
|
|
||||||
cache-dependency-path: ./docs/package-lock.json
|
|
||||||
|
|
||||||
- name: Validate Branch Names
|
|
||||||
run: |
|
|
||||||
# Check if branch names contain invalid characters. Only alphanumeric, _, -, ., and / are allowed.
|
|
||||||
validate_branch_name() {
|
|
||||||
local branch_name="$1"
|
|
||||||
if [[ ! "$branch_name" =~ ^[a-zA-Z0-9/_\.-]+$ ]]; then
|
|
||||||
echo "Error: Branch name contains invalid characters. Only alphanumeric, _, -, ., and / are allowed."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
validate_branch_name "${{ github.event.pull_request.head.ref }}"
|
|
||||||
|
|
||||||
- name: Extract Branch Names
|
|
||||||
id: extract_branch
|
|
||||||
run: |
|
|
||||||
# Extract and transform branch names
|
|
||||||
extract_branch() {
|
|
||||||
local input_branch="$1"
|
|
||||||
# Check if input_branch starts with "refs/heads/"
|
|
||||||
if [[ "$input_branch" == refs/heads/* ]]; then
|
|
||||||
# Remove "refs/heads/" prefix safely using parameter expansion
|
|
||||||
branch_name="${input_branch#refs/heads/}"
|
|
||||||
echo "$branch_name"
|
|
||||||
else
|
|
||||||
echo "$input_branch"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Transform branch names in form of `refs/heads/main` to `main`
|
|
||||||
draft_branch=$(extract_branch "${{ github.event.pull_request.head.ref }}")
|
|
||||||
|
|
||||||
# Replace / with - in the draft branch name to use as a directory name
|
|
||||||
draft_directory=$(echo "$draft_branch" | tr / -)
|
|
||||||
|
|
||||||
# Safe echo to $GITHUB_OUTPUT
|
|
||||||
{
|
|
||||||
echo "draft_branch=$draft_branch"
|
|
||||||
echo "draft_directory=$draft_directory"
|
|
||||||
} >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Set Draft URL
|
|
||||||
id: draft_url
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
echo "url=${{ vars.DOCS_DRAFT_BASE_URL }}/langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}/index.html" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: cd docs && npm install
|
|
||||||
|
|
||||||
- name: Build website
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
cd docs
|
|
||||||
npm run build |& tee $GITHUB_WORKSPACE/build.log
|
|
||||||
env:
|
|
||||||
BASE_URL: /langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}
|
|
||||||
FORCE_COLOR: 0 # Disable color output
|
|
||||||
# SEGMENT_PUBLIC_WRITE_KEY: ${{ vars.DOCS_DRAFT_SEGMENT_PUBLIC_WRITE_KEY }}
|
|
||||||
|
|
||||||
- name: Check Build Result
|
|
||||||
id: buildLogFail
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
MULTILINE_LOG=$(cat $GITHUB_WORKSPACE/build.log)
|
|
||||||
echo "BUILD_FAILURE<<EOF" >> $GITHUB_ENV
|
|
||||||
echo $MULTILINE_LOG >> $GITHUB_ENV
|
|
||||||
echo "EOF" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Hide Previous Build Comments
|
|
||||||
if: ${{ github.event.pull_request.number && (success() || failure()) }}
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Get all comments on the PR that match our build comments
|
|
||||||
comments=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments \
|
|
||||||
--jq '.[] | select(.body | test("Build failure! :x:|Build successful! :white_check_mark:")) | .node_id')
|
|
||||||
|
|
||||||
# Minimize each matching comment using GraphQL API
|
|
||||||
if [[ -n "$comments" ]]; then
|
|
||||||
echo "Found previous build comments to hide"
|
|
||||||
while IFS= read -r comment_id; do
|
|
||||||
if [[ -n "$comment_id" ]]; then
|
|
||||||
echo "Minimizing comment: $comment_id"
|
|
||||||
gh api graphql \
|
|
||||||
--field id="$comment_id" \
|
|
||||||
--field classifier="OUTDATED" \
|
|
||||||
--raw-field query='
|
|
||||||
mutation($id: ID!, $classifier: ReportedContentClassifiers!) {
|
|
||||||
minimizeComment(input: { subjectId: $id, classifier: $classifier }) {
|
|
||||||
minimizedComment {
|
|
||||||
isMinimized
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}' || echo "Failed to minimize comment $comment_id, continuing..."
|
|
||||||
echo
|
|
||||||
fi
|
|
||||||
done <<< "$comments"
|
|
||||||
else
|
|
||||||
echo "No previous build comments found to hide"
|
|
||||||
fi
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Assemble Build Success Comment
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
build_success_comment="Build successful! :white_check_mark:"
|
|
||||||
build_success_comment+="\nDeploying docs draft."
|
|
||||||
|
|
||||||
echo "BUILD_SUCCESS_COMMENT<<EOF" >> $GITHUB_ENV
|
|
||||||
echo -e "$build_success_comment" >> $GITHUB_ENV
|
|
||||||
echo "EOF" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Create Build Success Comment
|
|
||||||
if: success()
|
|
||||||
uses: peter-evans/create-or-update-comment@v4
|
|
||||||
with:
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body: "${{ env.BUILD_SUCCESS_COMMENT }}"
|
|
||||||
reactions: rocket
|
|
||||||
|
|
||||||
- name: Create Build Failure Comment
|
|
||||||
if: failure()
|
|
||||||
uses: peter-evans/create-or-update-comment@v4
|
|
||||||
with:
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body: |
|
|
||||||
Build failure! :x:
|
|
||||||
> ${{ env.BUILD_FAILURE }}
|
|
||||||
reactions: confused
|
|
||||||
|
|
||||||
- name: Find Comment
|
|
||||||
id: fc
|
|
||||||
if: success()
|
|
||||||
uses: peter-evans/find-comment@v3
|
|
||||||
with:
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body-includes: Build successful!
|
|
||||||
direction: last
|
|
||||||
|
|
||||||
- name: Configure AWS CLI
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
aws configure set aws_access_key_id ${{ secrets.DOCS_AWS_ACCESS_KEY_ID }}
|
|
||||||
aws configure set aws_secret_access_key ${{ secrets.DOCS_AWS_SECRET_ACCESS_KEY }}
|
|
||||||
aws configure set region us-west-2
|
|
||||||
|
|
||||||
- name: Check for New Assets
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
echo "Checking for new assets." |& tee -a $GITHUB_WORKSPACE/deploy.log
|
|
||||||
echo "aws s3 sync docs/build/assets/ s3://${{ vars.DOCS_DRAFT_S3_BUCKET_NAME }}/langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}/assets/ --size-only --dryrun --no-progress" | tee -a $GITHUB_WORKSPACE/deploy.log
|
|
||||||
aws s3 sync docs/build/assets/ "s3://${{ vars.DOCS_DRAFT_S3_BUCKET_NAME }}/langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}/assets/" --size-only --dryrun --no-progress | tee $GITHUB_WORKSPACE/assets.log
|
|
||||||
|
|
||||||
- name: Determine Standard or Full Publish
|
|
||||||
id: check_full_publish
|
|
||||||
run: |
|
|
||||||
# Determine if a full publish is required because of new assets.
|
|
||||||
if grep -qE '(upload:|delete:)' "$GITHUB_WORKSPACE/assets.log"; then
|
|
||||||
echo "New assets. Perform full publish: true" | tee -a "$GITHUB_WORKSPACE/deploy.log"
|
|
||||||
echo "perform_full_publish=true" >> "$GITHUB_OUTPUT"
|
|
||||||
else
|
|
||||||
echo "No new assets. Perform full publish: false" | tee -a "$GITHUB_WORKSPACE/deploy.log"
|
|
||||||
echo "perform_full_publish=false" >> "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Deploy to S3
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
set -o pipefail
|
|
||||||
cd docs
|
|
||||||
mkdir langflow-drafts
|
|
||||||
mv build langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}
|
|
||||||
cd langflow-drafts
|
|
||||||
|
|
||||||
# Records the repository that originally triggered the build so we can post back
|
|
||||||
# comments upon clean up of a stale draft if it still has an open pull request.
|
|
||||||
echo "${{ github.event.repository.full_name }}" > ${{ steps.extract_branch.outputs.draft_directory }}/.github_source_repository
|
|
||||||
|
|
||||||
s3_params=(
|
|
||||||
# Hide upload progress for a cleaner sync log
|
|
||||||
--no-progress
|
|
||||||
--delete
|
|
||||||
--exclude "*"
|
|
||||||
--include "${{ steps.extract_branch.outputs.draft_directory }}/*"
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ "${{ steps.check_full_publish.outputs.perform_full_publish }}" == "false" ]]; then
|
|
||||||
s3_params+=(--size-only)
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Deploying draft to S3." |& tee -a $GITHUB_WORKSPACE/deploy.log
|
|
||||||
echo "aws s3 sync . s3://${{ vars.DOCS_DRAFT_S3_BUCKET_NAME }}/langflow-drafts ${s3_params[@]}" |& tee -a $GITHUB_WORKSPACE/deploy.log
|
|
||||||
aws s3 sync . "s3://${{ vars.DOCS_DRAFT_S3_BUCKET_NAME }}/langflow-drafts" "${s3_params[@]}" |& tee -a $GITHUB_WORKSPACE/deploy.log
|
|
||||||
|
|
||||||
# Update .github_source_repository file metadata to mark last modified time of the draft.
|
|
||||||
# This will allow us to later determine if a draft is stale and needs to be cleaned up.
|
|
||||||
echo "Marking last modified time of the draft." |& tee -a $GITHUB_WORKSPACE/deploy.log
|
|
||||||
echo "aws s3 cp --metadata '{\"touched\": \"now\"}' \
|
|
||||||
s3://${{ vars.DOCS_DRAFT_S3_BUCKET_NAME }}/langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}/.github_source_repository \
|
|
||||||
s3://${{ vars.DOCS_DRAFT_S3_BUCKET_NAME }}/langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}/.github_source_repository" \
|
|
||||||
|& tee -a $GITHUB_WORKSPACE/deploy.log
|
|
||||||
|
|
||||||
aws s3 cp --metadata '{ "touched": "now" }' \
|
|
||||||
s3://${{ vars.DOCS_DRAFT_S3_BUCKET_NAME }}/langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}/.github_source_repository \
|
|
||||||
s3://${{ vars.DOCS_DRAFT_S3_BUCKET_NAME }}/langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}/.github_source_repository \
|
|
||||||
|& tee -a $GITHUB_WORKSPACE/deploy.log
|
|
||||||
|
|
||||||
- name: Invalidate CloudFront Cache
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
invalidation_batch="{ \"Paths\": { \"Quantity\": 1, \"Items\": [\"/langflow-drafts/${{ steps.extract_branch.outputs.draft_directory }}/*\"] }, \"CallerReference\": \"langflow-docs-draft-files-$(date +%s)\" }"
|
|
||||||
|
|
||||||
echo $invalidation_batch | jq . |& tee -a "$GITHUB_WORKSPACE/deploy.log"
|
|
||||||
echo "Creating invalidation." |& tee -a "$GITHUB_WORKSPACE/deploy.log"
|
|
||||||
invalidation_id=$(aws cloudfront create-invalidation --distribution-id "${{ vars.DOCS_DRAFT_CLOUD_FRONT_DISTRIBUTION_ID }}" --invalidation-batch "$invalidation_batch" --query 'Invalidation.Id' --output text |& tee -a "$GITHUB_WORKSPACE/deploy.log")
|
|
||||||
|
|
||||||
echo "Awaiting invalidation." |& tee -a "$GITHUB_WORKSPACE/deploy.log"
|
|
||||||
aws cloudfront wait invalidation-completed --distribution-id "${{ vars.DOCS_DRAFT_CLOUD_FRONT_DISTRIBUTION_ID }}" --id "$invalidation_id" |& tee -a "$GITHUB_WORKSPACE/deploy.log"
|
|
||||||
echo "Invalidation complete." |& tee -a "$GITHUB_WORKSPACE/deploy.log"
|
|
||||||
|
|
||||||
- name: Update Comment
|
|
||||||
if: ${{ steps.fc.outputs.comment-id != '' }}
|
|
||||||
uses: peter-evans/create-or-update-comment@v4
|
|
||||||
with:
|
|
||||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
|
||||||
body: |
|
|
||||||
Deploy successful! [View draft](${{ steps.draft_url.outputs.url }})
|
|
||||||
reactions: hooray
|
|
||||||
|
|
||||||
- name: Upload Deploy Log
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
name: deploy.log
|
|
||||||
path: ${{ github.workspace }}/deploy.log
|
|
||||||
42
.github/workflows/deploy-gh-pages.yml
vendored
42
.github/workflows/deploy-gh-pages.yml
vendored
|
|
@ -1,42 +0,0 @@
|
||||||
name: Deploy to GitHub Pages
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'docs/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
name: Deploy to GitHub Pages
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20.20.0
|
|
||||||
cache: npm
|
|
||||||
cache-dependency-path: ./docs/package-lock.json
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: cd docs && npm install
|
|
||||||
- name: Build website
|
|
||||||
run: cd docs && npm run build
|
|
||||||
# env:
|
|
||||||
# SEGMENT_PUBLIC_WRITE_KEY: ${{ vars.DOCS_PROD_SEGMENT_PUBLIC_WRITE_KEY }}
|
|
||||||
|
|
||||||
# Popular action to deploy to GitHub Pages:
|
|
||||||
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
|
|
||||||
- name: Deploy to GitHub Pages
|
|
||||||
uses: peaceiris/actions-gh-pages@v4
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
# Build output to publish to the `gh-pages` branch:
|
|
||||||
publish_dir: ./docs/build
|
|
||||||
# The following lines assign commit authorship to the official
|
|
||||||
# GH-Actions bot for deploys to `gh-pages` branch:
|
|
||||||
# https://github.com/actions/checkout/issues/13#issuecomment-724415212
|
|
||||||
# The GH actions bot is used by default if you didn't specify the two fields.
|
|
||||||
# You can swap them out with your own user credentials.
|
|
||||||
59
.github/workflows/publish-sdk-python.yml
vendored
59
.github/workflows/publish-sdk-python.yml
vendored
|
|
@ -1,59 +0,0 @@
|
||||||
name: Publish Python SDK
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'sdks/python/pyproject.toml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Publish to PyPI
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: sdks/python
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: '3.12'
|
|
||||||
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v4
|
|
||||||
|
|
||||||
- name: Extract version from pyproject.toml
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
VERSION=$(grep -Po '(?<=^version = ")[^"]*' pyproject.toml)
|
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Check if version already published
|
|
||||||
id: check
|
|
||||||
run: |
|
|
||||||
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://pypi.org/pypi/openrag-sdk/${{ steps.version.outputs.version }}/json)
|
|
||||||
if [ "$HTTP_STATUS" = "200" ]; then
|
|
||||||
echo "exists=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "exists=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Build package
|
|
||||||
if: steps.check.outputs.exists == 'false'
|
|
||||||
run: uv build
|
|
||||||
|
|
||||||
- name: Publish to PyPI
|
|
||||||
if: steps.check.outputs.exists == 'false'
|
|
||||||
run: uv publish
|
|
||||||
env:
|
|
||||||
UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN }}
|
|
||||||
|
|
||||||
- name: Skip publish (version exists)
|
|
||||||
if: steps.check.outputs.exists == 'true'
|
|
||||||
run: echo "Version ${{ steps.version.outputs.version }} already exists on PyPI, skipping publish"
|
|
||||||
64
.github/workflows/publish-sdk-typescript.yml
vendored
64
.github/workflows/publish-sdk-typescript.yml
vendored
|
|
@ -1,64 +0,0 @@
|
||||||
name: Publish TypeScript SDK
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'sdks/typescript/package.json'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Publish to npm
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
id-token: write
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: sdks/typescript
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
registry-url: 'https://registry.npmjs.org'
|
|
||||||
|
|
||||||
- name: Update npm to latest
|
|
||||||
run: npm install -g npm@latest
|
|
||||||
|
|
||||||
- name: Extract version from package.json
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
VERSION=$(node -p "require('./package.json').version")
|
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Check if version already published
|
|
||||||
id: check
|
|
||||||
run: |
|
|
||||||
if npm view openrag-sdk@${{ steps.version.outputs.version }} version 2>/dev/null; then
|
|
||||||
echo "exists=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "exists=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
if: steps.check.outputs.exists == 'false'
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
if: steps.check.outputs.exists == 'false'
|
|
||||||
run: npm run build
|
|
||||||
|
|
||||||
- name: Publish to npm
|
|
||||||
if: steps.check.outputs.exists == 'false'
|
|
||||||
run: npm publish --access public --provenance
|
|
||||||
|
|
||||||
- name: Skip publish (version exists)
|
|
||||||
if: steps.check.outputs.exists == 'true'
|
|
||||||
run: echo "Version ${{ steps.version.outputs.version }} already exists on npm, skipping publish"
|
|
||||||
102
.github/workflows/test-integration.yml
vendored
102
.github/workflows/test-integration.yml
vendored
|
|
@ -1,102 +0,0 @@
|
||||||
name: Integration Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- 'src/**.py'
|
|
||||||
- 'tests/**.py'
|
|
||||||
- 'pyproject.toml'
|
|
||||||
- 'uv.lock'
|
|
||||||
- 'sdks/**'
|
|
||||||
- '.github/workflows/test-integration.yml'
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
use_local_images:
|
|
||||||
description: 'Build images locally instead of pulling from DockerHub'
|
|
||||||
required: false
|
|
||||||
type: boolean
|
|
||||||
default: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tests:
|
|
||||||
runs-on: [self-hosted, linux, ARM64, langflow-ai-arm64-40gb]
|
|
||||||
env:
|
|
||||||
# Prefer repository/environment variable first, then secret, then a sane fallback
|
|
||||||
OPENSEARCH_PASSWORD: ${{ vars.OPENSEARCH_PASSWORD || secrets.OPENSEARCH_PASSWORD || 'OpenRag#2025!' }}
|
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
||||||
LANGFLOW_AUTO_LOGIN: "True"
|
|
||||||
LANGFLOW_NEW_USER_IS_ACTIVE: "True"
|
|
||||||
LANGFLOW_ENABLE_SUPERUSER_CLI: "True"
|
|
||||||
LANGFLOW_CHAT_FLOW_ID: ${{ vars.LANGFLOW_CHAT_FLOW_ID || '1098eea1-6649-4e1d-aed1-b77249fb8dd0' }}
|
|
||||||
LANGFLOW_INGEST_FLOW_ID: ${{ vars.LANGFLOW_INGEST_FLOW_ID || '5488df7c-b93f-4f87-a446-b67028bc0813' }}
|
|
||||||
NUDGES_FLOW_ID: ${{ vars.NUDGES_FLOW_ID || 'ebc01d31-1976-46ce-a385-b0240327226c' }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- run: df -h
|
|
||||||
|
|
||||||
- name: Cleanup Docker cache
|
|
||||||
run: |
|
|
||||||
docker system prune -af || true
|
|
||||||
docker builder prune -af || true
|
|
||||||
docker-compose -f docker-compose.yml down -v --remove-orphans || true
|
|
||||||
|
|
||||||
- name: Cleanup root-owned files (OpenSearch data, config)
|
|
||||||
run: |
|
|
||||||
for i in 1 2 3; do
|
|
||||||
docker run --rm -v $(pwd):/work alpine sh -c "rm -rf /work/opensearch-data /work/config" && break
|
|
||||||
echo "Attempt $i failed, retrying in 5s..."
|
|
||||||
sleep 5
|
|
||||||
done || true
|
|
||||||
|
|
||||||
- run: df -h
|
|
||||||
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Verify workspace
|
|
||||||
run: |
|
|
||||||
echo "Current directory: $(pwd)"
|
|
||||||
echo "Workspace: ${GITHUB_WORKSPACE}"
|
|
||||||
ls -la
|
|
||||||
|
|
||||||
- name: Set up UV
|
|
||||||
uses: astral-sh/setup-uv@v3
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
|
|
||||||
- name: Python version
|
|
||||||
run: uv python install 3.13
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: uv sync
|
|
||||||
|
|
||||||
- name: Run integration tests
|
|
||||||
env:
|
|
||||||
OPENSEARCH_HOST: localhost
|
|
||||||
OPENSEARCH_PORT: 9200
|
|
||||||
OPENSEARCH_USERNAME: admin
|
|
||||||
OPENSEARCH_PASSWORD: ${{ env.OPENSEARCH_PASSWORD }}
|
|
||||||
LOG_LEVEL: DEBUG
|
|
||||||
# Force no-auth mode so tests bypass OAuth
|
|
||||||
GOOGLE_OAUTH_CLIENT_ID: ""
|
|
||||||
GOOGLE_OAUTH_CLIENT_SECRET: ""
|
|
||||||
# Disable startup ingest noise unless a test enables it
|
|
||||||
DISABLE_STARTUP_INGEST: "true"
|
|
||||||
run: |
|
|
||||||
# For PRs, always build locally since we're testing new code
|
|
||||||
# For workflow_dispatch, use the input (defaults to true)
|
|
||||||
USE_LOCAL="${{ inputs.use_local_images }}"
|
|
||||||
if [ "${{ github.event_name }}" == "pull_request" ] || [ "$USE_LOCAL" != "false" ]; then
|
|
||||||
echo "Running tests with locally built images..."
|
|
||||||
make test-ci-local
|
|
||||||
else
|
|
||||||
echo "Running tests with DockerHub images..."
|
|
||||||
make test-ci
|
|
||||||
fi
|
|
||||||
echo "Keys directory after tests:"
|
|
||||||
ls -la keys/ || echo "No keys directory"
|
|
||||||
52
.github/workflows/update-uv-lock.yml
vendored
52
.github/workflows/update-uv-lock.yml
vendored
|
|
@ -1,52 +0,0 @@
|
||||||
name: Update uv.lock on version bump
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'pyproject.toml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-lock:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: '3.13'
|
|
||||||
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v3
|
|
||||||
|
|
||||||
- name: Update uv.lock
|
|
||||||
run: uv sync
|
|
||||||
|
|
||||||
- name: Check for changes
|
|
||||||
id: changes
|
|
||||||
run: |
|
|
||||||
if git diff --quiet uv.lock; then
|
|
||||||
echo "changed=false" >> $GITHUB_OUTPUT
|
|
||||||
echo "No changes to uv.lock"
|
|
||||||
else
|
|
||||||
echo "changed=true" >> $GITHUB_OUTPUT
|
|
||||||
echo "uv.lock has been updated"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Commit and push uv.lock
|
|
||||||
if: steps.changes.outputs.changed == 'true'
|
|
||||||
run: |
|
|
||||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git config --local user.name "github-actions[bot]"
|
|
||||||
git add uv.lock
|
|
||||||
git commit -m "chore: update uv.lock after version bump [skip ci]"
|
|
||||||
git push
|
|
||||||
|
|
||||||
36
.gitignore
vendored
36
.gitignore
vendored
|
|
@ -1,36 +0,0 @@
|
||||||
# Python-generated files
|
|
||||||
__pycache__/
|
|
||||||
*.py[oc]
|
|
||||||
build/
|
|
||||||
dist/
|
|
||||||
wheels/
|
|
||||||
*.egg-info
|
|
||||||
|
|
||||||
# Virtual environments
|
|
||||||
.venv
|
|
||||||
.env
|
|
||||||
|
|
||||||
# RSA keys for JWT signing
|
|
||||||
*.pem
|
|
||||||
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
1001*.pdf
|
|
||||||
*.json
|
|
||||||
!**/package.json
|
|
||||||
!**/package-lock.json
|
|
||||||
!**/tsconfig.json
|
|
||||||
!flows/*.json
|
|
||||||
!src/tui/_assets/flows/*.json
|
|
||||||
!src/tui/_assets/flows/components/*.json
|
|
||||||
!frontend/*.json
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
config/
|
|
||||||
|
|
||||||
.docling.pid
|
|
||||||
|
|
||||||
# OpenSearch data directory
|
|
||||||
opensearch-data/
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
repos:
|
|
||||||
- repo: https://github.com/Yelp/detect-secrets
|
|
||||||
rev: v1.5.0
|
|
||||||
hooks:
|
|
||||||
- id: detect-secrets
|
|
||||||
args: ["--baseline", ".secrets.baseline", "--exclude-lines", "code_hash"]
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
3.13
|
|
||||||
|
|
@ -1,180 +0,0 @@
|
||||||
{
|
|
||||||
"version": "1.5.0",
|
|
||||||
"plugins_used": [
|
|
||||||
{
|
|
||||||
"name": "ArtifactoryDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AWSKeyDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AzureStorageKeyDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Base64HighEntropyString",
|
|
||||||
"limit": 4.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "BasicAuthDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CloudantDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "DiscordBotTokenDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "GitHubTokenDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "GitLabTokenDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "HexHighEntropyString",
|
|
||||||
"limit": 3.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "IbmCloudIamDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "IbmCosHmacDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "IPPublicDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "JwtTokenDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "KeywordDetector",
|
|
||||||
"keyword_exclude": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "MailchimpDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "NpmDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "OpenAIDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PrivateKeyDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PypiTokenDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SendGridDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SlackDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SoftlayerDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SquareOAuthDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "StripeDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "TelegramBotTokenDetector"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "TwilioKeyDetector"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filters_used": [
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.common.is_baseline_file",
|
|
||||||
"filename": ".secrets.baseline"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
|
||||||
"min_level": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.regex.should_exclude_file",
|
|
||||||
"pattern": [
|
|
||||||
"flows/.*\\.json$"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "detect_secrets.filters.regex.should_exclude_line",
|
|
||||||
"pattern": [
|
|
||||||
"code_hash"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"results": {
|
|
||||||
"docs/docs/_partial-integrate-chat.mdx": [
|
|
||||||
{
|
|
||||||
"type": "Secret Keyword",
|
|
||||||
"filename": "docs/docs/_partial-integrate-chat.mdx",
|
|
||||||
"hashed_secret": "e42fd8b9ad15d8fa5f4718cad7cf19b522807996",
|
|
||||||
"is_verified": false,
|
|
||||||
"line_number": 30
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src/main.py": [
|
|
||||||
{
|
|
||||||
"type": "Base64 High Entropy String",
|
|
||||||
"filename": "src/main.py",
|
|
||||||
"hashed_secret": "131a83e9ef8660d7dd0771da7ce5954d9ea801ee",
|
|
||||||
"is_verified": false,
|
|
||||||
"line_number": 404
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src/models/processors.py": [
|
|
||||||
{
|
|
||||||
"type": "Base64 High Entropy String",
|
|
||||||
"filename": "src/models/processors.py",
|
|
||||||
"hashed_secret": "131a83e9ef8660d7dd0771da7ce5954d9ea801ee",
|
|
||||||
"is_verified": false,
|
|
||||||
"line_number": 763
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src/services/langflow_file_service.py": [
|
|
||||||
{
|
|
||||||
"type": "Base64 High Entropy String",
|
|
||||||
"filename": "src/services/langflow_file_service.py",
|
|
||||||
"hashed_secret": "131a83e9ef8660d7dd0771da7ce5954d9ea801ee",
|
|
||||||
"is_verified": false,
|
|
||||||
"line_number": 97
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"generated_at": "2025-12-09T20:33:13Z"
|
|
||||||
}
|
|
||||||
25
404.html
Normal file
25
404.html
Normal file
File diff suppressed because one or more lines are too long
317
CONTRIBUTING.md
317
CONTRIBUTING.md
|
|
@ -1,317 +0,0 @@
|
||||||
# Contributing to OpenRAG
|
|
||||||
|
|
||||||
Thank you for your interest in contributing to OpenRAG! This guide will help you set up your development environment and understand the development workflow.
|
|
||||||
|
|
||||||
## 🛠️ Development Setup
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
- Docker or Podman with Compose installed
|
|
||||||
- Make (for development commands)
|
|
||||||
- Python 3.13+ with uv package manager
|
|
||||||
- Node.js 18+ and npm
|
|
||||||
|
|
||||||
### Set up OpenRAG for development
|
|
||||||
|
|
||||||
1. Set up your development environment.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Clone and setup environment
|
|
||||||
git clone https://github.com/langflow-ai/openrag.git
|
|
||||||
cd openrag
|
|
||||||
make setup # Creates .env and installs dependencies
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Configure the `.env` file with your API keys and credentials.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Required
|
|
||||||
OPENAI_API_KEY=your_openai_api_key
|
|
||||||
OPENSEARCH_PASSWORD=your_secure_password
|
|
||||||
LANGFLOW_SUPERUSER=admin
|
|
||||||
LANGFLOW_SUPERUSER_PASSWORD=your_secure_password
|
|
||||||
LANGFLOW_CHAT_FLOW_ID=your_chat_flow_id
|
|
||||||
LANGFLOW_INGEST_FLOW_ID=your_ingest_flow_id
|
|
||||||
NUDGES_FLOW_ID=your_nudges_flow_id
|
|
||||||
```
|
|
||||||
|
|
||||||
For extended configuration, including ingestion and optional variables, see [docs/reference/configuration.mdx](docs/docs/reference/configuration.mdx).
|
|
||||||
|
|
||||||
3. Start OpenRAG.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Full stack with GPU support
|
|
||||||
make dev
|
|
||||||
|
|
||||||
# Or CPU only
|
|
||||||
make dev-cpu
|
|
||||||
```
|
|
||||||
|
|
||||||
Access the services:
|
|
||||||
- **Frontend**: http://localhost:3000
|
|
||||||
- **Backend API**: http://localhost:8000
|
|
||||||
- **Langflow**: http://localhost:7860
|
|
||||||
- **OpenSearch**: http://localhost:9200
|
|
||||||
- **OpenSearch Dashboards**: http://localhost:5601
|
|
||||||
|
|
||||||
## 🔧 Development Commands
|
|
||||||
|
|
||||||
All development tasks are managed through the Makefile. Run `make help` to see all available commands.
|
|
||||||
|
|
||||||
### Environment Management
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Setup development environment
|
|
||||||
make setup # Initial setup: creates .env, installs dependencies
|
|
||||||
|
|
||||||
# Start development environments
|
|
||||||
make dev # Full stack with GPU support
|
|
||||||
make dev-cpu # Full stack with CPU only
|
|
||||||
make infra # Infrastructure only (for local development)
|
|
||||||
|
|
||||||
# Container management
|
|
||||||
make stop # Stop all containers
|
|
||||||
make restart # Restart all containers
|
|
||||||
make clean # Stop and remove containers/volumes
|
|
||||||
make status # Show container status
|
|
||||||
make health # Check service health
|
|
||||||
```
|
|
||||||
|
|
||||||
### Local Development Workflow
|
|
||||||
|
|
||||||
For faster development iteration, run infrastructure in Docker and backend/frontend locally:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Terminal 1: Start infrastructure
|
|
||||||
make infra
|
|
||||||
|
|
||||||
# Terminal 2: Run backend locally
|
|
||||||
make backend
|
|
||||||
|
|
||||||
# Terminal 3: Run frontend locally
|
|
||||||
make frontend
|
|
||||||
```
|
|
||||||
|
|
||||||
This setup provides:
|
|
||||||
- Faster code reloading
|
|
||||||
- Direct access to logs and debugging
|
|
||||||
- Easier testing and iteration
|
|
||||||
|
|
||||||
### Dependency Management
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make install # Install all dependencies
|
|
||||||
make install-be # Install backend dependencies (uv)
|
|
||||||
make install-fe # Install frontend dependencies (npm)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building and Testing
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build Docker images
|
|
||||||
make build # Build all images
|
|
||||||
make build-be # Build backend image only
|
|
||||||
make build-fe # Build frontend image only
|
|
||||||
|
|
||||||
# Testing and quality
|
|
||||||
make test # Run backend tests
|
|
||||||
make lint # Run linting checks
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debugging
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# View logs
|
|
||||||
make logs # All container logs
|
|
||||||
make logs-be # Backend logs only
|
|
||||||
make logs-fe # Frontend logs only
|
|
||||||
make logs-lf # Langflow logs only
|
|
||||||
make logs-os # OpenSearch logs only
|
|
||||||
|
|
||||||
# Shell access
|
|
||||||
make shell-be # Shell into backend container
|
|
||||||
make shell-lf # Shell into langflow container
|
|
||||||
make shell-os # Shell into opensearch container
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database Operations
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Reset OpenSearch indices
|
|
||||||
make db-reset # Delete and recreate indices
|
|
||||||
```
|
|
||||||
|
|
||||||
### Flow Management
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Upload flow to Langflow
|
|
||||||
make flow-upload FLOW_FILE=path/to/flow.json
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🏗️ Architecture Overview
|
|
||||||
|
|
||||||
### Backend (Python/Starlette)
|
|
||||||
- **API Layer**: RESTful endpoints in `src/api/`
|
|
||||||
- **Services**: Business logic in `src/services/`
|
|
||||||
- **Models**: Data models and processors in `src/models/`
|
|
||||||
- **Connectors**: External service integrations in `src/connectors/`
|
|
||||||
- **Configuration**: Settings management in `src/config/`
|
|
||||||
|
|
||||||
### Frontend (Next.js/React)
|
|
||||||
- **Pages**: Next.js app router in `frontend/src/app/`
|
|
||||||
- **Components**: Reusable UI components in `frontend/src/components/`
|
|
||||||
- **Contexts**: State management in `frontend/src/contexts/`
|
|
||||||
- **Hooks**: Custom React hooks in `frontend/hooks/`
|
|
||||||
|
|
||||||
### Infrastructure
|
|
||||||
- **OpenSearch**: Vector database and search engine
|
|
||||||
- **Langflow**: Visual flow builder for LLM workflows
|
|
||||||
- **Docker**: Containerization and orchestration
|
|
||||||
|
|
||||||
## 🧪 Testing
|
|
||||||
|
|
||||||
### Backend Tests
|
|
||||||
```bash
|
|
||||||
make test # Run all backend tests
|
|
||||||
uv run pytest # Direct pytest execution
|
|
||||||
uv run pytest -v # Verbose test output
|
|
||||||
```
|
|
||||||
|
|
||||||
### Frontend Tests
|
|
||||||
```bash
|
|
||||||
cd frontend && npm test # Run frontend tests
|
|
||||||
cd frontend && npm run lint # Frontend linting
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📝 Code Style
|
|
||||||
|
|
||||||
### Backend
|
|
||||||
- Follow PEP 8 style guidelines
|
|
||||||
- Use type hints where appropriate
|
|
||||||
- Document functions and classes with docstrings
|
|
||||||
- Use structured logging with `structlog`
|
|
||||||
|
|
||||||
### Frontend
|
|
||||||
- Follow React/Next.js best practices
|
|
||||||
- Use TypeScript for type safety
|
|
||||||
- Follow the established component structure
|
|
||||||
- Use Tailwind CSS for styling
|
|
||||||
|
|
||||||
## 🔍 Debugging Tips
|
|
||||||
|
|
||||||
### Backend Debugging
|
|
||||||
```bash
|
|
||||||
# Enable debug logging
|
|
||||||
export LOG_LEVEL=DEBUG
|
|
||||||
|
|
||||||
# Run backend locally for debugging
|
|
||||||
make infra && make backend
|
|
||||||
|
|
||||||
# Check OpenSearch indices
|
|
||||||
curl -X GET "http://localhost:9200/_cat/indices?v" \
|
|
||||||
-u admin:$(grep OPENSEARCH_PASSWORD .env | cut -d= -f2)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Frontend Debugging
|
|
||||||
```bash
|
|
||||||
# Run with detailed logs
|
|
||||||
cd frontend && npm run dev
|
|
||||||
|
|
||||||
# Build and analyze bundle
|
|
||||||
cd frontend && npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Container Debugging
|
|
||||||
```bash
|
|
||||||
# Check container status
|
|
||||||
make status
|
|
||||||
|
|
||||||
# View real-time logs
|
|
||||||
make logs
|
|
||||||
|
|
||||||
# Shell into containers
|
|
||||||
make shell-be # Backend container
|
|
||||||
make shell-lf # Langflow container
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 Deployment Testing
|
|
||||||
|
|
||||||
### Local Testing
|
|
||||||
```bash
|
|
||||||
# Test full stack deployment
|
|
||||||
make clean && make dev
|
|
||||||
|
|
||||||
# Test CPU-only deployment
|
|
||||||
make clean && make dev-cpu
|
|
||||||
```
|
|
||||||
|
|
||||||
### Performance Testing
|
|
||||||
```bash
|
|
||||||
# Monitor resource usage
|
|
||||||
docker stats
|
|
||||||
|
|
||||||
# Check service health
|
|
||||||
make health
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📚 Development Resources
|
|
||||||
|
|
||||||
### Key Files
|
|
||||||
- `src/main.py` - Backend application entry point
|
|
||||||
- `src/config/settings.py` - Configuration management
|
|
||||||
- `frontend/src/app/layout.tsx` - Frontend root layout
|
|
||||||
- `docker-compose.yml` - Container orchestration
|
|
||||||
- `Makefile` - Development commands
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
- API documentation: Available at `http://localhost:8000/docs` when backend is running
|
|
||||||
- Component Storybook: (if implemented) at `http://localhost:6006`
|
|
||||||
- OpenSearch: `http://localhost:5601` (Dashboards)
|
|
||||||
- Langflow: `http://localhost:7860`
|
|
||||||
|
|
||||||
## 🐛 Common Issues
|
|
||||||
|
|
||||||
### Port Conflicts
|
|
||||||
Ensure these ports are available:
|
|
||||||
- 3000 (Frontend)
|
|
||||||
- 7860 (Langflow)
|
|
||||||
- 8000 (Backend)
|
|
||||||
- 9200 (OpenSearch)
|
|
||||||
- 5601 (OpenSearch Dashboards)
|
|
||||||
|
|
||||||
### Memory Issues
|
|
||||||
- Use `make dev-cpu` for CPU-only mode
|
|
||||||
- Increase Docker memory allocation
|
|
||||||
- Podman on macOS: increase the VM memory if needed
|
|
||||||
|
|
||||||
```bash
|
|
||||||
podman machine stop
|
|
||||||
podman machine rm
|
|
||||||
podman machine init --memory 8192 # 8 GB example
|
|
||||||
podman machine start
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment Issues
|
|
||||||
```bash
|
|
||||||
# Reset environment
|
|
||||||
make clean
|
|
||||||
cp .env.example .env # Reconfigure as needed
|
|
||||||
make setup
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📋 Pull Request Guidelines
|
|
||||||
|
|
||||||
1. **Fork and Branch**: Create a feature branch from `main`
|
|
||||||
2. **Test**: Ensure all tests pass with `make test` and `make lint`
|
|
||||||
3. **Documentation**: Update relevant documentation
|
|
||||||
4. **Commit Messages**: Use clear, descriptive commit messages
|
|
||||||
5. **PR Description**: Explain changes and include testing instructions
|
|
||||||
|
|
||||||
## 🤝 Getting Help
|
|
||||||
|
|
||||||
- Check existing issues and discussions
|
|
||||||
- Use `make status` and `make health` for debugging
|
|
||||||
- Review logs with `make logs`
|
|
||||||
- Join our community discussions
|
|
||||||
|
|
||||||
Thank you for contributing to OpenRAG! 🚀
|
|
||||||
138
Dockerfile
138
Dockerfile
|
|
@ -1,138 +0,0 @@
|
||||||
########################################
|
|
||||||
# Stage 1: Upstream OpenSearch with plugins
|
|
||||||
########################################
|
|
||||||
FROM opensearchproject/opensearch:3.2.0 AS upstream_opensearch
|
|
||||||
|
|
||||||
# Remove plugins
|
|
||||||
RUN opensearch-plugin remove opensearch-neural-search || true && \
|
|
||||||
opensearch-plugin remove opensearch-knn || true && \
|
|
||||||
# removing this one due to Netty CVE-2025-58056, can bring it back in the future
|
|
||||||
opensearch-plugin remove opensearch-security-analytics || true
|
|
||||||
|
|
||||||
# Prepare jvector plugin artifacts
|
|
||||||
RUN mkdir -p /tmp/opensearch-jvector-plugin && \
|
|
||||||
curl -L -s https://github.com/opensearch-project/opensearch-jvector/releases/download/3.2.0.0/artifacts.tar.gz \
|
|
||||||
| tar zxvf - -C /tmp/opensearch-jvector-plugin
|
|
||||||
|
|
||||||
# Prepare neural-search plugin
|
|
||||||
RUN mkdir -p /tmp/opensearch-neural-search && \
|
|
||||||
curl -L -s https://storage.googleapis.com/opensearch-jvector/opensearch-neural-search-3.2.0.0-20251029200300.zip \
|
|
||||||
> /tmp/opensearch-neural-search/plugin.zip
|
|
||||||
|
|
||||||
# Install additional plugins
|
|
||||||
RUN opensearch-plugin install --batch file:///tmp/opensearch-jvector-plugin/repository/org/opensearch/plugin/opensearch-jvector-plugin/3.2.0.0/opensearch-jvector-plugin-3.2.0.0.zip && \
|
|
||||||
opensearch-plugin install --batch file:///tmp/opensearch-neural-search/plugin.zip && \
|
|
||||||
opensearch-plugin install --batch repository-gcs && \
|
|
||||||
opensearch-plugin install --batch repository-azure && \
|
|
||||||
# opensearch-plugin install --batch repository-s3 && \
|
|
||||||
opensearch-plugin install --batch https://github.com/opensearch-project/opensearch-prometheus-exporter/releases/download/3.2.0.0/prometheus-exporter-3.2.0.0.zip
|
|
||||||
|
|
||||||
# Apply Netty patch
|
|
||||||
COPY patch-netty.sh /tmp/
|
|
||||||
RUN whoami && bash /tmp/patch-netty.sh
|
|
||||||
|
|
||||||
# Set permissions for OpenShift compatibility before copying
|
|
||||||
RUN chmod -R g=u /usr/share/opensearch
|
|
||||||
|
|
||||||
|
|
||||||
########################################
|
|
||||||
# Stage 2: UBI9 runtime image
|
|
||||||
########################################
|
|
||||||
FROM registry.access.redhat.com/ubi9/ubi:latest
|
|
||||||
|
|
||||||
USER root
|
|
||||||
|
|
||||||
# Update packages and install required tools
|
|
||||||
# TODO bring back iostat somehow? sysstat isn't in ubi
|
|
||||||
# TODO bring back 'perf' package, but what did we need it for?
|
|
||||||
RUN dnf update -y && \
|
|
||||||
dnf install -y --allowerasing \
|
|
||||||
less procps-ng findutils sudo curl tar gzip shadow-utils which && \
|
|
||||||
dnf clean all
|
|
||||||
|
|
||||||
# Create opensearch user and group
|
|
||||||
ARG UID=1000
|
|
||||||
ARG GID=1000
|
|
||||||
ARG OPENSEARCH_HOME=/usr/share/opensearch
|
|
||||||
|
|
||||||
WORKDIR $OPENSEARCH_HOME
|
|
||||||
|
|
||||||
RUN groupadd -g $GID opensearch && \
|
|
||||||
adduser -u $UID -g $GID -d $OPENSEARCH_HOME opensearch
|
|
||||||
|
|
||||||
# Grant the opensearch user sudo privileges (passwordless sudo)
|
|
||||||
RUN usermod -aG wheel opensearch && \
|
|
||||||
echo "opensearch ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
|
||||||
|
|
||||||
# Copy OpenSearch from the upstream stage
|
|
||||||
COPY --from=upstream_opensearch --chown=$UID:0 $OPENSEARCH_HOME $OPENSEARCH_HOME
|
|
||||||
|
|
||||||
ARG OPENSEARCH_VERSION=3.2.0
|
|
||||||
|
|
||||||
########################################
|
|
||||||
# Async-profiler (multi-arch like your original)
|
|
||||||
########################################
|
|
||||||
ARG TARGETARCH
|
|
||||||
|
|
||||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
|
||||||
export ASYNC_PROFILER_URL=https://github.com/async-profiler/async-profiler/releases/download/v4.0/async-profiler-4.0-linux-x64.tar.gz; \
|
|
||||||
elif [ "$TARGETARCH" = "arm64" ]; then \
|
|
||||||
export ASYNC_PROFILER_URL=https://github.com/async-profiler/async-profiler/releases/download/v4.0/async-profiler-4.0-linux-arm64.tar.gz; \
|
|
||||||
else \
|
|
||||||
echo "Unsupported architecture: $TARGETARCH" && exit 1; \
|
|
||||||
fi && \
|
|
||||||
mkdir /opt/async-profiler && \
|
|
||||||
curl -s -L $ASYNC_PROFILER_URL | tar zxvf - --strip-components=1 -C /opt/async-profiler && \
|
|
||||||
chown -R opensearch:opensearch /opt/async-profiler
|
|
||||||
|
|
||||||
# Create profiling script (as in your original Dockerfile)
|
|
||||||
RUN echo "#!/bin/bash" > /usr/share/opensearch/profile.sh && \
|
|
||||||
echo "export PATH=\$PATH:/opt/async-profiler/bin" >> /usr/share/opensearch/profile.sh && \
|
|
||||||
echo "echo 1 | sudo tee /proc/sys/kernel/perf_event_paranoid >/dev/null" >> /usr/share/opensearch/profile.sh && \
|
|
||||||
echo "echo 0 | sudo tee /proc/sys/kernel/kptr_restrict >/dev/null" >> /usr/share/opensearch/profile.sh && \
|
|
||||||
echo "asprof \$@" >> /usr/share/opensearch/profile.sh && \
|
|
||||||
chmod 777 /usr/share/opensearch/profile.sh
|
|
||||||
|
|
||||||
########################################
|
|
||||||
# Security config (OIDC/DLS) and setup script
|
|
||||||
########################################
|
|
||||||
|
|
||||||
# Copy OIDC and DLS security configuration (as root, like before)
|
|
||||||
COPY securityconfig/ /usr/share/opensearch/securityconfig/
|
|
||||||
RUN chown -R opensearch:opensearch /usr/share/opensearch/securityconfig/
|
|
||||||
|
|
||||||
# Create a script to apply security configuration after OpenSearch starts
|
|
||||||
RUN echo '#!/bin/bash' > /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'echo "Waiting for OpenSearch to start..."' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'PASSWORD=${OPENSEARCH_INITIAL_ADMIN_PASSWORD:-${OPENSEARCH_PASSWORD}}' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'if [ -z "$PASSWORD" ]; then echo "[ERROR] OPENSEARCH_INITIAL_ADMIN_PASSWORD or OPENSEARCH_PASSWORD must be set"; exit 1; fi' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'until curl -s -k -u admin:$PASSWORD https://localhost:9200; do sleep 1; done' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'echo "Generating admin hash from configured password..."' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'HASH=$(/usr/share/opensearch/plugins/opensearch-security/tools/hash.sh -p "$PASSWORD")' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'if [ -z "$HASH" ]; then echo "[ERROR] Failed to generate admin hash"; exit 1; fi' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'sed -i "s|^ hash: \".*\"| hash: \"$HASH\"|" /usr/share/opensearch/securityconfig/internal_users.yml' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'echo "Updated internal_users.yml with runtime-generated admin hash"' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'echo "Applying OIDC and DLS security configuration..."' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo '/usr/share/opensearch/plugins/opensearch-security/tools/securityadmin.sh \' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo ' -cd /usr/share/opensearch/securityconfig \' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo ' -icl -nhnv \' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo ' -cacert /usr/share/opensearch/config/root-ca.pem \' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo ' -cert /usr/share/opensearch/config/kirk.pem \' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo ' -key /usr/share/opensearch/config/kirk-key.pem' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
echo 'echo "Security configuration applied successfully"' >> /usr/share/opensearch/setup-security.sh && \
|
|
||||||
chmod +x /usr/share/opensearch/setup-security.sh
|
|
||||||
|
|
||||||
########################################
|
|
||||||
# Final runtime settings
|
|
||||||
########################################
|
|
||||||
USER opensearch
|
|
||||||
WORKDIR $OPENSEARCH_HOME
|
|
||||||
ENV JAVA_HOME=$OPENSEARCH_HOME/jdk
|
|
||||||
ENV PATH=$PATH:$JAVA_HOME/bin:$OPENSEARCH_HOME/bin
|
|
||||||
|
|
||||||
# Expose ports
|
|
||||||
EXPOSE 9200 9300 9600 9650
|
|
||||||
|
|
||||||
ENTRYPOINT ["./opensearch-docker-entrypoint.sh"]
|
|
||||||
CMD ["opensearch"]
|
|
||||||
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
FROM python:3.13-slim
|
|
||||||
|
|
||||||
# Install curl for uv installation and openssl for RSA key generation
|
|
||||||
# Also install git for potential dependencies and build-essential for native compilations
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
curl \
|
|
||||||
openssl \
|
|
||||||
git \
|
|
||||||
build-essential \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install uv
|
|
||||||
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
||||||
ENV PATH="/root/.local/bin:$PATH"
|
|
||||||
|
|
||||||
# Set working directory
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy Python dependencies
|
|
||||||
COPY pyproject.toml uv.lock ./
|
|
||||||
RUN uv sync
|
|
||||||
|
|
||||||
# Copy sample document and warmup script for docling
|
|
||||||
COPY openrag-documents/warmup_ocr.pdf ./
|
|
||||||
COPY warm_up_docling.py ./
|
|
||||||
RUN uv run docling-tools models download
|
|
||||||
RUN uv run python - <<'PY'
|
|
||||||
import pathlib, easyocr
|
|
||||||
cache = pathlib.Path("/root/.EasyOCR/model")
|
|
||||||
cache.mkdir(parents=True, exist_ok=True)
|
|
||||||
# Prewarm the detector + recog for Docling’s default langs
|
|
||||||
easyocr.Reader(['fr','de','es','en'],
|
|
||||||
download_enabled=True,
|
|
||||||
model_storage_directory=str(cache))
|
|
||||||
print("EasyOCR cache ready at", cache)
|
|
||||||
PY
|
|
||||||
|
|
||||||
# RUN uv run python warm_up_docling.py && rm warm_up_docling.py warmup_ocr.pdf
|
|
||||||
|
|
||||||
|
|
||||||
#ENV EASYOCR_MODULE_PATH=~/.cache/docling/models/EasyOcr/
|
|
||||||
|
|
||||||
# Copy Python source and flows
|
|
||||||
COPY src/ ./src/
|
|
||||||
COPY flows/ ./flows/
|
|
||||||
|
|
||||||
# Expose backend port
|
|
||||||
EXPOSE 8000
|
|
||||||
|
|
||||||
# Start backend in foreground
|
|
||||||
CMD ["uv", "run", "python", "src/main.py"]
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
FROM node:20.20.0-slim
|
|
||||||
|
|
||||||
# Set working directory
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy frontend dependencies
|
|
||||||
COPY frontend/package*.json ./
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
# Copy frontend source
|
|
||||||
COPY frontend/ ./
|
|
||||||
|
|
||||||
# Build frontend
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Expose frontend port
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
# Start frontend in foreground
|
|
||||||
CMD ["npm", "start"]
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
FROM langflowai/langflow-nightly:1.7.0.dev21
|
|
||||||
|
|
||||||
EXPOSE 7860
|
|
||||||
|
|
||||||
CMD ["langflow", "run", "--host", "0.0.0.0", "--port", "7860"]
|
|
||||||
201
LICENSE
201
LICENSE
|
|
@ -1,201 +0,0 @@
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright 2025 IBM
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
recursive-include src/tui/_assets *
|
|
||||||
459
Makefile
459
Makefile
|
|
@ -1,459 +0,0 @@
|
||||||
# OpenRAG Development Makefile
|
|
||||||
# Provides easy commands for development workflow
|
|
||||||
|
|
||||||
# Load variables from .env if present so `make` commands pick them up
|
|
||||||
# Strip quotes from values to avoid issues with tools that don't handle them like python-dotenv does
|
|
||||||
ifneq (,$(wildcard .env))
|
|
||||||
include .env
|
|
||||||
export $(shell sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=.*/\1/p' .env)
|
|
||||||
# Strip single quotes from all exported variables
|
|
||||||
$(foreach var,$(shell sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=.*/\1/p' .env),$(eval $(var):=$(shell echo $($(var)) | sed "s/^'//;s/'$$//")))
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: help dev dev-cpu dev-local infra stop clean build logs shell-backend shell-frontend install \
|
|
||||||
test test-integration test-ci test-ci-local test-sdk \
|
|
||||||
backend frontend install-be install-fe build-be build-fe logs-be logs-fe logs-lf logs-os \
|
|
||||||
shell-be shell-lf shell-os restart status health db-reset flow-upload quick setup
|
|
||||||
|
|
||||||
# Default target
|
|
||||||
help:
|
|
||||||
@echo "OpenRAG Development Commands"
|
|
||||||
@echo ""
|
|
||||||
@echo "Development:"
|
|
||||||
@echo " dev - Start full stack with GPU support (docker compose)"
|
|
||||||
@echo " dev-cpu - Start full stack with CPU only (docker compose)"
|
|
||||||
@echo " dev-local - Start infrastructure only, run backend/frontend locally"
|
|
||||||
@echo " infra - Start infrastructure services only (alias for dev-local)"
|
|
||||||
@echo " stop - Stop all containers"
|
|
||||||
@echo " restart - Restart all containers"
|
|
||||||
@echo ""
|
|
||||||
@echo "Local Development:"
|
|
||||||
@echo " backend - Run backend locally (requires infrastructure)"
|
|
||||||
@echo " frontend - Run frontend locally"
|
|
||||||
@echo " install - Install all dependencies"
|
|
||||||
@echo " install-be - Install backend dependencies (uv)"
|
|
||||||
@echo " install-fe - Install frontend dependencies (npm)"
|
|
||||||
@echo ""
|
|
||||||
@echo "Utilities:"
|
|
||||||
@echo " build - Build all Docker images"
|
|
||||||
@echo " clean - Stop containers and remove volumes"
|
|
||||||
@echo " logs - Show logs from all containers"
|
|
||||||
@echo " logs-be - Show backend container logs"
|
|
||||||
@echo " logs-lf - Show langflow container logs"
|
|
||||||
@echo " shell-be - Shell into backend container"
|
|
||||||
@echo " shell-lf - Shell into langflow container"
|
|
||||||
@echo ""
|
|
||||||
@echo "Testing:"
|
|
||||||
@echo " test - Run all backend tests"
|
|
||||||
@echo " test-integration - Run integration tests (requires infra)"
|
|
||||||
@echo " test-ci - Start infra, run integration + SDK tests, tear down (uses DockerHub images)"
|
|
||||||
@echo " test-ci-local - Same as test-ci but builds all images locally"
|
|
||||||
@echo " test-sdk - Run SDK integration tests (requires running OpenRAG at localhost:3000)"
|
|
||||||
@echo " lint - Run linting checks"
|
|
||||||
@echo ""
|
|
||||||
|
|
||||||
# Development environments
|
|
||||||
# Use centralized env file from TUI if it exists, otherwise fall back to local .env
|
|
||||||
OPENRAG_ENV_FILE := $(shell if [ -f ~/.openrag/tui/.env ]; then echo "--env-file ~/.openrag/tui/.env"; fi)
|
|
||||||
|
|
||||||
dev:
|
|
||||||
@echo "🚀 Starting OpenRAG with GPU support..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) -f docker-compose.yml -f docker-compose.gpu.yml up -d
|
|
||||||
@echo "✅ Services started!"
|
|
||||||
@echo " Backend: http://localhost:8000"
|
|
||||||
@echo " Frontend: http://localhost:3000"
|
|
||||||
@echo " Langflow: http://localhost:7860"
|
|
||||||
@echo " OpenSearch: http://localhost:9200"
|
|
||||||
@echo " Dashboards: http://localhost:5601"
|
|
||||||
|
|
||||||
dev-cpu:
|
|
||||||
@echo "🚀 Starting OpenRAG with CPU only..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) up -d
|
|
||||||
@echo "✅ Services started!"
|
|
||||||
@echo " Backend: http://localhost:8000"
|
|
||||||
@echo " Frontend: http://localhost:3000"
|
|
||||||
@echo " Langflow: http://localhost:7860"
|
|
||||||
@echo " OpenSearch: http://localhost:9200"
|
|
||||||
@echo " Dashboards: http://localhost:5601"
|
|
||||||
|
|
||||||
dev-local:
|
|
||||||
@echo "🔧 Starting infrastructure only (for local development)..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) up -d opensearch dashboards langflow
|
|
||||||
@echo "✅ Infrastructure started!"
|
|
||||||
@echo " Langflow: http://localhost:7860"
|
|
||||||
@echo " OpenSearch: http://localhost:9200"
|
|
||||||
@echo " Dashboards: http://localhost:5601"
|
|
||||||
@echo ""
|
|
||||||
@echo "Now run 'make backend' and 'make frontend' in separate terminals"
|
|
||||||
|
|
||||||
infra:
|
|
||||||
@echo "🔧 Starting infrastructure services only..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) up -d opensearch dashboards langflow
|
|
||||||
@echo "✅ Infrastructure services started!"
|
|
||||||
@echo " Langflow: http://localhost:7860"
|
|
||||||
@echo " OpenSearch: http://localhost:9200"
|
|
||||||
@echo " Dashboards: http://localhost:5601"
|
|
||||||
|
|
||||||
infra-cpu:
|
|
||||||
@echo "🔧 Starting infrastructure services only..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) up -d opensearch dashboards langflow
|
|
||||||
@echo "✅ Infrastructure services started!"
|
|
||||||
@echo " Langflow: http://localhost:7860"
|
|
||||||
@echo " OpenSearch: http://localhost:9200"
|
|
||||||
@echo " Dashboards: http://localhost:5601"
|
|
||||||
|
|
||||||
# Container management
|
|
||||||
stop:
|
|
||||||
@echo "🛑 Stopping all containers..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) down
|
|
||||||
|
|
||||||
restart: stop dev
|
|
||||||
|
|
||||||
clean: stop
|
|
||||||
@echo "🧹 Cleaning up containers and volumes..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) down -v --remove-orphans
|
|
||||||
docker system prune -f
|
|
||||||
|
|
||||||
# Local development
|
|
||||||
backend:
|
|
||||||
@echo "🐍 Starting backend locally..."
|
|
||||||
@if [ ! -f .env ]; then echo "⚠️ .env file not found. Copy .env.example to .env first"; exit 1; fi
|
|
||||||
uv run python src/main.py
|
|
||||||
|
|
||||||
frontend:
|
|
||||||
@echo "⚛️ Starting frontend locally..."
|
|
||||||
@if [ ! -d "frontend/node_modules" ]; then echo "📦 Installing frontend dependencies first..."; cd frontend && npm install; fi
|
|
||||||
cd frontend && npx next dev
|
|
||||||
|
|
||||||
# Installation
|
|
||||||
install: install-be install-fe
|
|
||||||
@echo "✅ All dependencies installed!"
|
|
||||||
|
|
||||||
install-be:
|
|
||||||
@echo "📦 Installing backend dependencies..."
|
|
||||||
uv sync --extra torch-cu128
|
|
||||||
|
|
||||||
install-fe:
|
|
||||||
@echo "📦 Installing frontend dependencies..."
|
|
||||||
cd frontend && npm install
|
|
||||||
|
|
||||||
# Building
|
|
||||||
build:
|
|
||||||
@echo "Building all Docker images locally..."
|
|
||||||
docker build -t langflowai/openrag-opensearch:latest -f Dockerfile .
|
|
||||||
docker build -t langflowai/openrag-backend:latest -f Dockerfile.backend .
|
|
||||||
docker build -t langflowai/openrag-frontend:latest -f Dockerfile.frontend .
|
|
||||||
docker build -t langflowai/openrag-langflow:latest -f Dockerfile.langflow .
|
|
||||||
|
|
||||||
build-be:
|
|
||||||
@echo "Building backend image..."
|
|
||||||
docker build -t langflowai/openrag-backend:latest -f Dockerfile.backend .
|
|
||||||
|
|
||||||
build-fe:
|
|
||||||
@echo "Building frontend image..."
|
|
||||||
docker build -t langflowai/openrag-frontend:latest -f Dockerfile.frontend .
|
|
||||||
|
|
||||||
# Logging and debugging
|
|
||||||
logs:
|
|
||||||
@echo "📋 Showing all container logs..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) logs -f
|
|
||||||
|
|
||||||
logs-be:
|
|
||||||
@echo "📋 Showing backend logs..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) logs -f openrag-backend
|
|
||||||
|
|
||||||
logs-fe:
|
|
||||||
@echo "📋 Showing frontend logs..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) logs -f openrag-frontend
|
|
||||||
|
|
||||||
logs-lf:
|
|
||||||
@echo "📋 Showing langflow logs..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) logs -f langflow
|
|
||||||
|
|
||||||
logs-os:
|
|
||||||
@echo "📋 Showing opensearch logs..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) logs -f opensearch
|
|
||||||
|
|
||||||
# Shell access
|
|
||||||
shell-be:
|
|
||||||
@echo "🐚 Opening shell in backend container..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) exec openrag-backend /bin/bash
|
|
||||||
|
|
||||||
shell-lf:
|
|
||||||
@echo "🐚 Opening shell in langflow container..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) exec langflow /bin/bash
|
|
||||||
|
|
||||||
shell-os:
|
|
||||||
@echo "🐚 Opening shell in opensearch container..."
|
|
||||||
docker compose $(OPENRAG_ENV_FILE) exec opensearch /bin/bash
|
|
||||||
|
|
||||||
# Testing and quality
|
|
||||||
test:
|
|
||||||
@echo "🧪 Running all backend tests..."
|
|
||||||
uv run pytest tests/ -v
|
|
||||||
|
|
||||||
test-integration:
|
|
||||||
@echo "🧪 Running integration tests (requires infrastructure)..."
|
|
||||||
@echo "💡 Make sure to run 'make infra' first!"
|
|
||||||
uv run pytest tests/integration/ -v
|
|
||||||
|
|
||||||
# CI-friendly integration test target: brings up infra, waits, runs tests, tears down
|
|
||||||
test-ci:
|
|
||||||
@set -e; \
|
|
||||||
echo "Installing test dependencies..."; \
|
|
||||||
uv sync --group dev; \
|
|
||||||
if [ ! -f keys/private_key.pem ]; then \
|
|
||||||
echo "Generating RSA keys for JWT signing..."; \
|
|
||||||
uv run python -c "from src.main import generate_jwt_keys; generate_jwt_keys()"; \
|
|
||||||
else \
|
|
||||||
echo "RSA keys already exist, ensuring correct permissions..."; \
|
|
||||||
chmod 600 keys/private_key.pem 2>/dev/null || true; \
|
|
||||||
chmod 644 keys/public_key.pem 2>/dev/null || true; \
|
|
||||||
fi; \
|
|
||||||
echo "Cleaning up old containers and volumes..."; \
|
|
||||||
docker compose down -v 2>/dev/null || true; \
|
|
||||||
echo "Pulling latest images..."; \
|
|
||||||
docker compose pull; \
|
|
||||||
echo "Building OpenSearch image override..."; \
|
|
||||||
docker build --no-cache -t langflowai/openrag-opensearch:latest -f Dockerfile .; \
|
|
||||||
echo "Starting infra (OpenSearch + Dashboards + Langflow + Backend + Frontend) with CPU containers"; \
|
|
||||||
docker compose up -d opensearch dashboards langflow openrag-backend openrag-frontend; \
|
|
||||||
echo "Starting docling-serve..."; \
|
|
||||||
DOCLING_ENDPOINT=$$(uv run python scripts/docling_ctl.py start --port 5001 | grep "Endpoint:" | awk '{print $$2}'); \
|
|
||||||
echo "Docling-serve started at $$DOCLING_ENDPOINT"; \
|
|
||||||
echo "Waiting for backend OIDC endpoint..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
docker exec openrag-backend curl -s http://localhost:8000/.well-known/openid-configuration >/dev/null 2>&1 && break || sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Waiting for OpenSearch security config to be fully applied..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
if docker logs os 2>&1 | grep -q "Security configuration applied successfully"; then \
|
|
||||||
echo "✓ Security configuration applied"; \
|
|
||||||
break; \
|
|
||||||
fi; \
|
|
||||||
sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Verifying OIDC authenticator is active in OpenSearch..."; \
|
|
||||||
AUTHC_CONFIG=$$(curl -k -s -u admin:$${OPENSEARCH_PASSWORD} https://localhost:9200/_opendistro/_security/api/securityconfig 2>/dev/null); \
|
|
||||||
if echo "$$AUTHC_CONFIG" | grep -q "openid_auth_domain"; then \
|
|
||||||
echo "✓ OIDC authenticator configured"; \
|
|
||||||
echo "$$AUTHC_CONFIG" | grep -A 5 "openid_auth_domain"; \
|
|
||||||
else \
|
|
||||||
echo "✗ OIDC authenticator NOT found in security config!"; \
|
|
||||||
echo "Security config:"; \
|
|
||||||
echo "$$AUTHC_CONFIG" | head -50; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
echo "Waiting for Langflow..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
curl -s http://localhost:7860/ >/dev/null 2>&1 && break || sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Waiting for docling-serve at $$DOCLING_ENDPOINT..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
curl -s $${DOCLING_ENDPOINT}/health >/dev/null 2>&1 && break || sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Running integration tests"; \
|
|
||||||
LOG_LEVEL=$${LOG_LEVEL:-DEBUG} \
|
|
||||||
GOOGLE_OAUTH_CLIENT_ID="" \
|
|
||||||
GOOGLE_OAUTH_CLIENT_SECRET="" \
|
|
||||||
OPENSEARCH_HOST=localhost OPENSEARCH_PORT=9200 \
|
|
||||||
OPENSEARCH_USERNAME=admin OPENSEARCH_PASSWORD=$${OPENSEARCH_PASSWORD} \
|
|
||||||
DISABLE_STARTUP_INGEST=$${DISABLE_STARTUP_INGEST:-true} \
|
|
||||||
uv run pytest tests/integration -vv -s -o log_cli=true --log-cli-level=DEBUG; \
|
|
||||||
TEST_RESULT=$$?; \
|
|
||||||
echo ""; \
|
|
||||||
echo "Waiting for frontend at http://localhost:3000..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
curl -s http://localhost:3000/ >/dev/null 2>&1 && break || sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Running Python SDK integration tests"; \
|
|
||||||
cd sdks/python && \
|
|
||||||
uv sync --extra dev && \
|
|
||||||
OPENRAG_URL=http://localhost:3000 uv run pytest tests/test_integration.py -vv -s || TEST_RESULT=1; \
|
|
||||||
cd ../..; \
|
|
||||||
echo "Running TypeScript SDK integration tests"; \
|
|
||||||
cd sdks/typescript && \
|
|
||||||
npm install && npm run build && \
|
|
||||||
OPENRAG_URL=http://localhost:3000 npm test || TEST_RESULT=1; \
|
|
||||||
cd ../..; \
|
|
||||||
echo ""; \
|
|
||||||
echo "=== Post-test JWT diagnostics ==="; \
|
|
||||||
echo "Generating test JWT token..."; \
|
|
||||||
TEST_TOKEN=$$(uv run python -c "from src.session_manager import SessionManager, AnonymousUser; sm = SessionManager('test'); print(sm.create_jwt_token(AnonymousUser()))" 2>/dev/null || echo ""); \
|
|
||||||
if [ -n "$$TEST_TOKEN" ]; then \
|
|
||||||
echo "Testing JWT against OpenSearch..."; \
|
|
||||||
HTTP_CODE=$$(curl -k -s -w "%{http_code}" -o /tmp/os_diag.txt -H "Authorization: Bearer $$TEST_TOKEN" -H "Content-Type: application/json" https://localhost:9200/documents/_search -d '{"query":{"match_all":{}}}' 2>&1); \
|
|
||||||
echo "HTTP $$HTTP_CODE: $$(cat /tmp/os_diag.txt | head -c 150)"; \
|
|
||||||
fi; \
|
|
||||||
echo "================================="; \
|
|
||||||
echo ""; \
|
|
||||||
echo "Tearing down infra"; \
|
|
||||||
uv run python scripts/docling_ctl.py stop || true; \
|
|
||||||
docker compose down -v 2>/dev/null || true; \
|
|
||||||
exit $$TEST_RESULT
|
|
||||||
|
|
||||||
# CI-friendly integration test target with local builds: builds all images, brings up infra, waits, runs tests, tears down
|
|
||||||
test-ci-local:
|
|
||||||
@set -e; \
|
|
||||||
echo "Installing test dependencies..."; \
|
|
||||||
uv sync --group dev; \
|
|
||||||
if [ ! -f keys/private_key.pem ]; then \
|
|
||||||
echo "Generating RSA keys for JWT signing..."; \
|
|
||||||
uv run python -c "from src.main import generate_jwt_keys; generate_jwt_keys()"; \
|
|
||||||
else \
|
|
||||||
echo "RSA keys already exist, ensuring correct permissions..."; \
|
|
||||||
chmod 600 keys/private_key.pem 2>/dev/null || true; \
|
|
||||||
chmod 644 keys/public_key.pem 2>/dev/null || true; \
|
|
||||||
fi; \
|
|
||||||
echo "Cleaning up old containers and volumes..."; \
|
|
||||||
docker compose down -v 2>/dev/null || true; \
|
|
||||||
echo "Building all images locally..."; \
|
|
||||||
docker build -t langflowai/openrag-opensearch:latest -f Dockerfile .; \
|
|
||||||
docker build -t langflowai/openrag-backend:latest -f Dockerfile.backend .; \
|
|
||||||
docker build -t langflowai/openrag-frontend:latest -f Dockerfile.frontend .; \
|
|
||||||
docker build -t langflowai/openrag-langflow:latest -f Dockerfile.langflow .; \
|
|
||||||
echo "Starting infra (OpenSearch + Dashboards + Langflow + Backend + Frontend) with CPU containers"; \
|
|
||||||
docker compose up -d opensearch dashboards langflow openrag-backend openrag-frontend; \
|
|
||||||
echo "Starting docling-serve..."; \
|
|
||||||
DOCLING_ENDPOINT=$$(uv run python scripts/docling_ctl.py start --port 5001 | grep "Endpoint:" | awk '{print $$2}'); \
|
|
||||||
echo "Docling-serve started at $$DOCLING_ENDPOINT"; \
|
|
||||||
echo "Waiting for backend OIDC endpoint..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
docker exec openrag-backend curl -s http://localhost:8000/.well-known/openid-configuration >/dev/null 2>&1 && break || sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Waiting for OpenSearch security config to be fully applied..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
if docker logs os 2>&1 | grep -q "Security configuration applied successfully"; then \
|
|
||||||
echo "✓ Security configuration applied"; \
|
|
||||||
break; \
|
|
||||||
fi; \
|
|
||||||
sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Verifying OIDC authenticator is active in OpenSearch..."; \
|
|
||||||
AUTHC_CONFIG=$$(curl -k -s -u admin:$${OPENSEARCH_PASSWORD} https://localhost:9200/_opendistro/_security/api/securityconfig 2>/dev/null); \
|
|
||||||
if echo "$$AUTHC_CONFIG" | grep -q "openid_auth_domain"; then \
|
|
||||||
echo "✓ OIDC authenticator configured"; \
|
|
||||||
echo "$$AUTHC_CONFIG" | grep -A 5 "openid_auth_domain"; \
|
|
||||||
else \
|
|
||||||
echo "✗ OIDC authenticator NOT found in security config!"; \
|
|
||||||
echo "Security config:"; \
|
|
||||||
echo "$$AUTHC_CONFIG" | head -50; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
echo "Waiting for Langflow..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
curl -s http://localhost:7860/ >/dev/null 2>&1 && break || sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Waiting for docling-serve at $$DOCLING_ENDPOINT..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
curl -s $${DOCLING_ENDPOINT}/health >/dev/null 2>&1 && break || sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Running integration tests"; \
|
|
||||||
LOG_LEVEL=$${LOG_LEVEL:-DEBUG} \
|
|
||||||
GOOGLE_OAUTH_CLIENT_ID="" \
|
|
||||||
GOOGLE_OAUTH_CLIENT_SECRET="" \
|
|
||||||
OPENSEARCH_HOST=localhost OPENSEARCH_PORT=9200 \
|
|
||||||
OPENSEARCH_USERNAME=admin OPENSEARCH_PASSWORD=$${OPENSEARCH_PASSWORD} \
|
|
||||||
DISABLE_STARTUP_INGEST=$${DISABLE_STARTUP_INGEST:-true} \
|
|
||||||
uv run pytest tests/integration -vv -s -o log_cli=true --log-cli-level=DEBUG; \
|
|
||||||
TEST_RESULT=$$?; \
|
|
||||||
echo ""; \
|
|
||||||
echo "Waiting for frontend at http://localhost:3000..."; \
|
|
||||||
for i in $$(seq 1 60); do \
|
|
||||||
curl -s http://localhost:3000/ >/dev/null 2>&1 && break || sleep 2; \
|
|
||||||
done; \
|
|
||||||
echo "Running Python SDK integration tests"; \
|
|
||||||
cd sdks/python && \
|
|
||||||
uv sync --extra dev && \
|
|
||||||
OPENRAG_URL=http://localhost:3000 uv run pytest tests/test_integration.py -vv -s || TEST_RESULT=1; \
|
|
||||||
cd ../..; \
|
|
||||||
echo "Running TypeScript SDK integration tests"; \
|
|
||||||
cd sdks/typescript && \
|
|
||||||
npm install && npm run build && \
|
|
||||||
OPENRAG_URL=http://localhost:3000 npm test || TEST_RESULT=1; \
|
|
||||||
cd ../..; \
|
|
||||||
echo ""; \
|
|
||||||
echo "=== Post-test JWT diagnostics ==="; \
|
|
||||||
echo "Generating test JWT token..."; \
|
|
||||||
TEST_TOKEN=$$(uv run python -c "from src.session_manager import SessionManager, AnonymousUser; sm = SessionManager('test'); print(sm.create_jwt_token(AnonymousUser()))" 2>/dev/null || echo ""); \
|
|
||||||
if [ -n "$$TEST_TOKEN" ]; then \
|
|
||||||
echo "Testing JWT against OpenSearch..."; \
|
|
||||||
HTTP_CODE=$$(curl -k -s -w "%{http_code}" -o /tmp/os_diag.txt -H "Authorization: Bearer $$TEST_TOKEN" -H "Content-Type: application/json" https://localhost:9200/documents/_search -d '{"query":{"match_all":{}}}' 2>&1); \
|
|
||||||
echo "HTTP $$HTTP_CODE: $$(cat /tmp/os_diag.txt | head -c 150)"; \
|
|
||||||
fi; \
|
|
||||||
echo "================================="; \
|
|
||||||
echo ""; \
|
|
||||||
if [ $$TEST_RESULT -ne 0 ]; then \
|
|
||||||
echo "=== Tests failed, dumping container logs ==="; \
|
|
||||||
echo ""; \
|
|
||||||
echo "=== Langflow logs (last 500 lines) ==="; \
|
|
||||||
docker logs langflow 2>&1 | tail -500 || echo "Could not get Langflow logs"; \
|
|
||||||
echo ""; \
|
|
||||||
echo "=== Backend logs (last 200 lines) ==="; \
|
|
||||||
docker logs openrag-backend 2>&1 | tail -200 || echo "Could not get backend logs"; \
|
|
||||||
echo ""; \
|
|
||||||
fi; \
|
|
||||||
echo "Tearing down infra"; \
|
|
||||||
uv run python scripts/docling_ctl.py stop || true; \
|
|
||||||
docker compose down -v 2>/dev/null || true; \
|
|
||||||
exit $$TEST_RESULT
|
|
||||||
|
|
||||||
# SDK integration tests (requires running OpenRAG instance)
|
|
||||||
test-sdk:
|
|
||||||
@echo "Running SDK integration tests..."
|
|
||||||
@echo "Make sure OpenRAG is running at localhost:3000 (make up)"
|
|
||||||
@echo ""
|
|
||||||
@echo "Running Python SDK tests..."
|
|
||||||
cd sdks/python && uv sync --extra dev && OPENRAG_URL=http://localhost:3000 uv run pytest tests/test_integration.py -vv -s
|
|
||||||
@echo ""
|
|
||||||
@echo "Running TypeScript SDK tests..."
|
|
||||||
cd sdks/typescript && npm install && npm run build && OPENRAG_URL=http://localhost:3000 npm test
|
|
||||||
|
|
||||||
lint:
|
|
||||||
@echo "🔍 Running linting checks..."
|
|
||||||
cd frontend && npm run lint
|
|
||||||
@echo "Frontend linting complete"
|
|
||||||
|
|
||||||
# Service status
|
|
||||||
status:
|
|
||||||
@echo "📊 Container status:"
|
|
||||||
@docker compose $(OPENRAG_ENV_FILE) ps 2>/dev/null || echo "No containers running"
|
|
||||||
|
|
||||||
health:
|
|
||||||
@echo "🏥 Health check:"
|
|
||||||
@echo "Backend: $$(curl -s http://localhost:8000/health 2>/dev/null || echo 'Not responding')"
|
|
||||||
@echo "Langflow: $$(curl -s http://localhost:7860/health 2>/dev/null || echo 'Not responding')"
|
|
||||||
@echo "OpenSearch: $$(curl -s -k -u admin:$${OPENSEARCH_PASSWORD} https://localhost:9200 2>/dev/null | jq -r .tagline 2>/dev/null || echo 'Not responding')"
|
|
||||||
|
|
||||||
# Database operations
|
|
||||||
db-reset:
|
|
||||||
@echo "🗄️ Resetting OpenSearch indices..."
|
|
||||||
curl -X DELETE "http://localhost:9200/documents" -u admin:$${OPENSEARCH_PASSWORD} || true
|
|
||||||
curl -X DELETE "http://localhost:9200/knowledge_filters" -u admin:$${OPENSEARCH_PASSWORD} || true
|
|
||||||
@echo "Indices reset. Restart backend to recreate."
|
|
||||||
|
|
||||||
clear-os-data:
|
|
||||||
@echo "🧹 Clearing OpenSearch data directory..."
|
|
||||||
@uv run python scripts/clear_opensearch_data.py
|
|
||||||
|
|
||||||
# Flow management
|
|
||||||
flow-upload:
|
|
||||||
@echo "📁 Uploading flow to Langflow..."
|
|
||||||
@if [ -z "$(FLOW_FILE)" ]; then echo "Usage: make flow-upload FLOW_FILE=path/to/flow.json"; exit 1; fi
|
|
||||||
curl -X POST "http://localhost:7860/api/v1/flows" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d @$(FLOW_FILE)
|
|
||||||
|
|
||||||
# Quick development shortcuts
|
|
||||||
quick: dev-local
|
|
||||||
@echo "🚀 Quick start: infrastructure running!"
|
|
||||||
@echo "Run these in separate terminals:"
|
|
||||||
@echo " make backend"
|
|
||||||
@echo " make frontend"
|
|
||||||
|
|
||||||
# Environment setup
|
|
||||||
setup:
|
|
||||||
@echo "⚙️ Setting up development environment..."
|
|
||||||
@if [ ! -f .env ]; then cp .env.example .env && echo "📝 Created .env from template"; fi
|
|
||||||
@$(MAKE) install
|
|
||||||
@echo "✅ Setup complete! Run 'make dev' to start."
|
|
||||||
34
README.md
34
README.md
|
|
@ -1,34 +0,0 @@
|
||||||
<div align="center">
|
|
||||||
|
|
||||||
# OpenRAG
|
|
||||||
|
|
||||||
<div align="center">
|
|
||||||
<a href="https://github.com/langflow-ai/langflow"><img src="https://img.shields.io/badge/Langflow-1C1C1E?style=flat&logo=langflow" alt="Langflow"></a>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<a href="https://github.com/docling-project/docling"><img src="https://img.shields.io/badge/Docling-000000?style=flat" alt="Langflow"></a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
<a href="https://deepwiki.com/langflow-ai/openrag"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
||||||
|
|
||||||
## Install OpenRAG
|
|
||||||
|
|
||||||
To get started with OpenRAG, see the installation guides in the OpenRAG documentation:
|
|
||||||
|
|
||||||
* [Quickstart](https://docs.openr.ag/quickstart)
|
|
||||||
* [Install the OpenRAG Python package](https://docs.openr.ag/install-options)
|
|
||||||
* [Deploy self-managed services with Docker or Podman](https://docs.openr.ag/docker)
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
To report a bug or submit a feature request, visit the [Issues page](https://github.com/langflow-ai/openrag/issues).
|
|
||||||
64
SECURITY.md
64
SECURITY.md
|
|
@ -1,64 +0,0 @@
|
||||||
# OpenRAG security policy and responsible disclosure
|
|
||||||
|
|
||||||
## Security policy
|
|
||||||
|
|
||||||
This security policy applies to all public projects under the langflow-ai organization on GitHub. We prioritize security and continuously work to safeguard our systems. However, vulnerabilities can still exist. If you identify a security issue, please report it to us so we can address it promptly.
|
|
||||||
|
|
||||||
### Security and bug fix versions
|
|
||||||
|
|
||||||
- Fixes are released either as part of the next minor version (e.g., 1.3.0 → 1.4.0) or as an on-demand patch version (e.g., 1.3.0 → 1.3.1)
|
|
||||||
- Security fixes are given priority and might be enough to cause a new version to be released
|
|
||||||
|
|
||||||
## Report a vulnerability
|
|
||||||
|
|
||||||
We encourage responsible disclosure of security vulnerabilities. If you find or suspect a security issue, please discreetly report it to us so we can address it promptly:
|
|
||||||
|
|
||||||
### Submit a report
|
|
||||||
|
|
||||||
Go to the [OpenRAG Security page](https://github.com/langflow-ai/openrag/security), and then click **Report a vulnerability** to start a private conversation between you and the repository's maintainers.
|
|
||||||
|
|
||||||
Provide as many specific details as possible to help us reproduce and fix the issue quickly, including the following:
|
|
||||||
|
|
||||||
- Steps to reproduce the issue
|
|
||||||
- Potential impact or concerns
|
|
||||||
- Any suggested fixes
|
|
||||||
|
|
||||||
Your report is kept confidential, and these details aren't shared without your consent.
|
|
||||||
|
|
||||||
### Response timeline
|
|
||||||
|
|
||||||
We will acknowledge your report within 5 business days.
|
|
||||||
|
|
||||||
We will provide an estimated resolution timeline.
|
|
||||||
|
|
||||||
We will keep you updated on our progress.
|
|
||||||
|
|
||||||
### Disclosure guidelines
|
|
||||||
|
|
||||||
- Don't publicly disclose vulnerabilities until we have assessed, resolved, and notified affected users.
|
|
||||||
- If you plan to present your research (e.g., at a conference or in a blog), share a draft with us at least 30 days in advance for review.
|
|
||||||
- Disclosures must not include the following:
|
|
||||||
- Data from any OpenRAG customer projects
|
|
||||||
- OpenRAG user/customer information
|
|
||||||
- Details about OpenRAG employees, contractors, or partners
|
|
||||||
|
|
||||||
We appreciate your efforts in helping us maintain a secure platform, and we look forward to working together to resolve any issues responsibly.
|
|
||||||
|
|
||||||
## Known vulnerabilities
|
|
||||||
|
|
||||||
The following known vulnerabilities are for the OpenRAG codebase.
|
|
||||||
|
|
||||||
This list doesn't include vulnerabilities within OpenRAG dependencies like OpenSearch and Langflow.
|
|
||||||
For Langflow vulnerabilities, see the [Langflow SECURITY.md](https://github.com/langflow-ai/langflow/blob/main/SECURITY.md).
|
|
||||||
|
|
||||||
There are no known vulnerabilities exclusive to the OpenRAG application at this time.
|
|
||||||
|
|
||||||
## Security configuration guidelines
|
|
||||||
|
|
||||||
### Start the Langflow server with authentication enabled
|
|
||||||
|
|
||||||
It is recommended that you set a Langflow password (`LANGFLOW_SUPERUSER_PASSWORD`) so the Langflow server starts with authentication enabled and the `langflow superuser` command disabled.
|
|
||||||
|
|
||||||
You can set this password when you install OpenRAG, or you can [edit the OpenRAG `.env` file and redeploy the OpenRAG containers](https://docs.openr.ag/reference/configuration#set-environment-variables).
|
|
||||||
|
|
||||||
For more information, see [OpenRAG's Langflow settings reference](https://docs.openr.ag/reference/configuration#langflow-settings).
|
|
||||||
95
agents/index.html
Normal file
95
agents/index.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 35 KiB |
1
assets/css/styles.29e42e49.css
Normal file
1
assets/css/styles.29e42e49.css
Normal file
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 1 MiB After Width: | Height: | Size: 1 MiB |
1
assets/js/03ef5215.0f05b0ce.js
Normal file
1
assets/js/03ef5215.0f05b0ce.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/0ba6a408.e094a5ab.js
Normal file
1
assets/js/0ba6a408.e094a5ab.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/1000.f9af7a41.js
Normal file
1
assets/js/1000.f9af7a41.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[1e3],{1e3:(e,a,s)=>{s.d(a,{createRadarServices:()=>c.f});var c=s(7846);s(7960)}}]);
|
||||||
1
assets/js/1203.b618bb61.js
Normal file
1
assets/js/1203.b618bb61.js
Normal file
File diff suppressed because one or more lines are too long
2
assets/js/165.7b1d067d.js
Normal file
2
assets/js/165.7b1d067d.js
Normal file
File diff suppressed because one or more lines are too long
9
assets/js/165.7b1d067d.js.LICENSE.txt
Normal file
9
assets/js/165.7b1d067d.js.LICENSE.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*!
|
||||||
|
Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable
|
||||||
|
Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com)
|
||||||
|
Licensed under The MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */
|
||||||
|
|
||||||
|
/*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */
|
||||||
1
assets/js/1741.b927934f.js
Normal file
1
assets/js/1741.b927934f.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/1746.1ce4b99b.js
Normal file
1
assets/js/1746.1ce4b99b.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/17896441.afd63cb1.js
Normal file
1
assets/js/17896441.afd63cb1.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/1a4e3797.f6ce627d.js
Normal file
1
assets/js/1a4e3797.f6ce627d.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/2130.09232a19.js
Normal file
1
assets/js/2130.09232a19.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/21afe7ac.a600b84a.js
Normal file
1
assets/js/21afe7ac.a600b84a.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/2237.10d4f561.js
Normal file
1
assets/js/2237.10d4f561.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[2237],{2237:(e,t,n)=>{n.r(t),n.d(t,{default:()=>h});n(6540);var o=n(1312),i=n(5500),s=n(2765),a=n(3363),r=n(4848);function h(){const e=(0,o.T)({id:"theme.NotFound.title",message:"Page Not Found"});return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(i.be,{title:e}),(0,r.jsx)(s.A,{children:(0,r.jsx)(a.A,{})})]})}},3363:(e,t,n)=>{n.d(t,{A:()=>r});n(6540);var o=n(4164),i=n(1312),s=n(1107),a=n(4848);function r({className:e}){return(0,a.jsx)("main",{className:(0,o.A)("container margin-vert--xl",e),children:(0,a.jsx)("div",{className:"row",children:(0,a.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,a.jsx)(s.A,{as:"h1",className:"hero__title",children:(0,a.jsx)(i.A,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,a.jsx)("p",{children:(0,a.jsx)(i.A,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,a.jsx)("p",{children:(0,a.jsx)(i.A,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}}}]);
|
||||||
2
assets/js/2279.632a870f.js
Normal file
2
assets/js/2279.632a870f.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/2279.632a870f.js.LICENSE.txt
Normal file
1
assets/js/2279.632a870f.js.LICENSE.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/*! @license DOMPurify 3.3.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.0/LICENSE */
|
||||||
1
assets/js/2291.2753844f.js
Normal file
1
assets/js/2291.2753844f.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/22dd74f7.5e930b31.js
Normal file
1
assets/js/22dd74f7.5e930b31.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/2325.7c4239a7.js
Normal file
1
assets/js/2325.7c4239a7.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[2325],{2325:(e,a,c)=>{c.d(a,{createPacketServices:()=>s.$});var s=c(1477);c(7960)}}]);
|
||||||
1
assets/js/2334.6d98e48e.js
Normal file
1
assets/js/2334.6d98e48e.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/2492.e6c78669.js
Normal file
1
assets/js/2492.e6c78669.js
Normal file
File diff suppressed because one or more lines are too long
2
assets/js/2693.3b80ab01.js
Normal file
2
assets/js/2693.3b80ab01.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/2693.3b80ab01.js.LICENSE.txt
Normal file
1
assets/js/2693.3b80ab01.js.LICENSE.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
||||||
1
assets/js/27b4a875.a1e62294.js
Normal file
1
assets/js/27b4a875.a1e62294.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/2821.7e574346.js
Normal file
1
assets/js/2821.7e574346.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/291.1b64972f.js
Normal file
1
assets/js/291.1b64972f.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/33362219.aaf41871.js
Normal file
1
assets/js/33362219.aaf41871.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/3490.026802f4.js
Normal file
1
assets/js/3490.026802f4.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[3490],{3490:(e,a,s)=>{s.d(a,{createInfoServices:()=>c.v});var c=s(1885);s(7960)}}]);
|
||||||
1
assets/js/3624.a9a49a51.js
Normal file
1
assets/js/3624.a9a49a51.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/3815.f87fc96a.js
Normal file
1
assets/js/3815.f87fc96a.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[3815],{3815:(r,s,a)=>{a.d(s,{diagram:()=>o});var e=a(1746),l=(a(2501),a(9625),a(1152),a(45),a(5164),a(8698),a(5894),a(3245),a(2387),a(92),a(3226),a(7633),a(797)),o={parser:e._$,get db(){return new e.NM},renderer:e.Lh,styles:e.tM,init:(0,l.K2)(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")}}}]);
|
||||||
1
assets/js/416.3273912b.js
Normal file
1
assets/js/416.3273912b.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[416],{416:(s,a,o)=>{o.r(a)}}]);
|
||||||
2
assets/js/4218.0662e556.js
Normal file
2
assets/js/4218.0662e556.js
Normal file
File diff suppressed because one or more lines are too long
6
assets/js/4218.0662e556.js.LICENSE.txt
Normal file
6
assets/js/4218.0662e556.js.LICENSE.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* @license lucide-react v0.555.0 - ISC
|
||||||
|
*
|
||||||
|
* This source code is licensed under the ISC license.
|
||||||
|
* See the LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
1
assets/js/4250.77e8e6c6.js
Normal file
1
assets/js/4250.77e8e6c6.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[4250],{1869:(a,e,s)=>{s.d(e,{createGitGraphServices:()=>c.b});var c=s(7539);s(7960)}}]);
|
||||||
1
assets/js/441f609b.a85f7d37.js
Normal file
1
assets/js/441f609b.a85f7d37.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/4616.0d0b0873.js
Normal file
1
assets/js/4616.0d0b0873.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/4802.a8b2857c.js
Normal file
1
assets/js/4802.a8b2857c.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[4802],{4802:(e,r,a)=>{a.d(r,{diagram:()=>o});var t=a(4616),s=(a(9625),a(1152),a(45),a(5164),a(8698),a(5894),a(3245),a(2387),a(92),a(3226),a(7633),a(797)),o={parser:t.Zk,get db(){return new t.u4(2)},renderer:t.q7,styles:t.tM,init:(0,s.K2)(e=>{e.state||(e.state={}),e.state.arrowMarkerAbsolute=e.arrowMarkerAbsolute},"init")}}}]);
|
||||||
1
assets/js/4981.61cf4b0a.js
Normal file
1
assets/js/4981.61cf4b0a.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/4ba45368.43d87797.js
Normal file
1
assets/js/4ba45368.43d87797.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/52896773.7edb6c39.js
Normal file
1
assets/js/52896773.7edb6c39.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/5480.23265b76.js
Normal file
1
assets/js/5480.23265b76.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/5901.f6ccb00b.js
Normal file
1
assets/js/5901.f6ccb00b.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[5901],{5901:(e,a,s)=>{s.d(a,{createTreemapServices:()=>c.d});var c=s(1633);s(7960)}}]);
|
||||||
1
assets/js/5955.14464ff3.js
Normal file
1
assets/js/5955.14464ff3.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/5996.b2d1663e.js
Normal file
1
assets/js/5996.b2d1663e.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/5e95c892.0eb8bcc6.js
Normal file
1
assets/js/5e95c892.0eb8bcc6.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[9647],{7121:(e,s,r)=>{r.r(s),r.d(s,{default:()=>d});r(6540);var a=r(4164),c=r(7559),o=r(5500),n=r(2831),u=r(2765),l=r(4848);function d(e){return(0,l.jsx)(o.e3,{className:(0,a.A)(c.G.wrapper.docsPages),children:(0,l.jsx)(u.A,{children:(0,n.v)(e.route.routes)})})}}}]);
|
||||||
1
assets/js/617.e8fa27b8.js
Normal file
1
assets/js/617.e8fa27b8.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[617],{617:(e,a,s)=>{s.d(a,{createPieServices:()=>c.f});var c=s(9150);s(7960)}}]);
|
||||||
1
assets/js/6241.a1fa513c.js
Normal file
1
assets/js/6241.a1fa513c.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/6319.9020eb44.js
Normal file
1
assets/js/6319.9020eb44.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/6366.0c77f825.js
Normal file
1
assets/js/6366.0c77f825.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[6366],{6366:(e,c,a)=>{a.d(c,{createArchitectureServices:()=>r.S});var r=a(8980);a(7960)}}]);
|
||||||
1
assets/js/6567.d8e34fb4.js
Normal file
1
assets/js/6567.d8e34fb4.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[6567],{5871:(t,e,a)=>{function r(t,e){t.accDescr&&e.setAccDescription?.(t.accDescr),t.accTitle&&e.setAccTitle?.(t.accTitle),t.title&&e.setDiagramTitle?.(t.title)}a.d(e,{S:()=>r}),(0,a(797).K2)(r,"populateCommonDb")},8948:(t,e,a)=>{a.d(e,{diagram:()=>m});var r=a(3590),i=a(5871),o=a(3226),n=a(7633),s=a(797),l=a(8731),c=n.UI.packet,d=class{constructor(){this.packet=[],this.setAccTitle=n.SV,this.getAccTitle=n.iN,this.setDiagramTitle=n.ke,this.getDiagramTitle=n.ab,this.getAccDescription=n.m7,this.setAccDescription=n.EI}static{(0,s.K2)(this,"PacketDB")}getConfig(){const t=(0,o.$t)({...c,...(0,n.zj)().packet});return t.showBits&&(t.paddingY+=10),t}getPacket(){return this.packet}pushWord(t){t.length>0&&this.packet.push(t)}clear(){(0,n.IU)(),this.packet=[]}},p=(0,s.K2)((t,e)=>{(0,i.S)(t,e);let a=-1,r=[],o=1;const{bitsPerRow:n}=e.getConfig();for(let{start:i,end:l,bits:c,label:d}of t.blocks){if(void 0!==i&&void 0!==l&&l<i)throw new Error(`Packet block ${i} - ${l} is invalid. End must be greater than start.`);if(i??=a+1,i!==a+1)throw new Error(`Packet block ${i} - ${l??i} is not contiguous. It should start from ${a+1}.`);if(0===c)throw new Error(`Packet block ${i} is invalid. Cannot have a zero bit field.`);for(l??=i+(c??1)-1,c??=l-i+1,a=l,s.Rm.debug(`Packet block ${i} - ${a} with label ${d}`);r.length<=n+1&&e.getPacket().length<1e4;){const[t,a]=b({start:i,end:l,bits:c,label:d},o,n);if(r.push(t),t.end+1===o*n&&(e.pushWord(r),r=[],o++),!a)break;({start:i,end:l,bits:c,label:d}=a)}}e.pushWord(r)},"populate"),b=(0,s.K2)((t,e,a)=>{if(void 0===t.start)throw new Error("start should have been set during first phase");if(void 0===t.end)throw new Error("end should have been set during first phase");if(t.start>t.end)throw new Error(`Block start ${t.start} is greater than block end ${t.end}.`);if(t.end+1<=e*a)return[t,void 0];const r=e*a-1,i=e*a;return[{start:t.start,end:r,label:t.label,bits:r-t.start},{start:i,end:t.end,label:t.label,bits:t.end-i}]},"getNextFittingBlock"),h={parser:{yy:void 0},parse:(0,s.K2)(async t=>{const e=await(0,l.qg)("packet",t),a=h.parser?.yy;if(!(a instanceof d))throw new Error("parser.parser?.yy was not a PacketDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues.");s.Rm.debug(e),p(e,a)},"parse")},k=(0,s.K2)((t,e,a,i)=>{const o=i.db,s=o.getConfig(),{rowHeight:l,paddingY:c,bitWidth:d,bitsPerRow:p}=s,b=o.getPacket(),h=o.getDiagramTitle(),k=l+c,u=k*(b.length+1)-(h?0:l),f=d*p+2,w=(0,r.D)(e);w.attr("viewbox",`0 0 ${f} ${u}`),(0,n.a$)(w,u,f,s.useMaxWidth);for(const[r,n]of b.entries())g(w,n,r,s);w.append("text").text(h).attr("x",f/2).attr("y",u-k/2).attr("dominant-baseline","middle").attr("text-anchor","middle").attr("class","packetTitle")},"draw"),g=(0,s.K2)((t,e,a,{rowHeight:r,paddingX:i,paddingY:o,bitWidth:n,bitsPerRow:s,showBits:l})=>{const c=t.append("g"),d=a*(r+o)+o;for(const p of e){const t=p.start%s*n+1,e=(p.end-p.start+1)*n-i;if(c.append("rect").attr("x",t).attr("y",d).attr("width",e).attr("height",r).attr("class","packetBlock"),c.append("text").attr("x",t+e/2).attr("y",d+r/2).attr("class","packetLabel").attr("dominant-baseline","middle").attr("text-anchor","middle").text(p.label),!l)continue;const a=p.end===p.start,o=d-2;c.append("text").attr("x",t+(a?e/2:0)).attr("y",o).attr("class","packetByte start").attr("dominant-baseline","auto").attr("text-anchor",a?"middle":"start").text(p.start),a||c.append("text").attr("x",t+e).attr("y",o).attr("class","packetByte end").attr("dominant-baseline","auto").attr("text-anchor","end").text(p.end)}},"drawWord"),u={draw:k},f={byteFontSize:"10px",startByteColor:"black",endByteColor:"black",labelColor:"black",labelFontSize:"12px",titleColor:"black",titleFontSize:"14px",blockStrokeColor:"black",blockStrokeWidth:"1",blockFillColor:"#efefef"},w=(0,s.K2)(({packet:t}={})=>{const e=(0,o.$t)(f,t);return`\n\t.packetByte {\n\t\tfont-size: ${e.byteFontSize};\n\t}\n\t.packetByte.start {\n\t\tfill: ${e.startByteColor};\n\t}\n\t.packetByte.end {\n\t\tfill: ${e.endByteColor};\n\t}\n\t.packetLabel {\n\t\tfill: ${e.labelColor};\n\t\tfont-size: ${e.labelFontSize};\n\t}\n\t.packetTitle {\n\t\tfill: ${e.titleColor};\n\t\tfont-size: ${e.titleFontSize};\n\t}\n\t.packetBlock {\n\t\tstroke: ${e.blockStrokeColor};\n\t\tstroke-width: ${e.blockStrokeWidth};\n\t\tfill: ${e.blockFillColor};\n\t}\n\t`},"styles"),m={parser:h,get db(){return new d},renderer:u,styles:w}}}]);
|
||||||
1
assets/js/6992.eb4cc2ed.js
Normal file
1
assets/js/6992.eb4cc2ed.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/71478a5d.d81ec55b.js
Normal file
1
assets/js/71478a5d.d81ec55b.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/7465.7e0b8008.js
Normal file
1
assets/js/7465.7e0b8008.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";(globalThis.webpackChunkopenrag_docs=globalThis.webpackChunkopenrag_docs||[]).push([[7465],{7465:(e,a,r)=>{r.d(a,{diagram:()=>p});var n=r(9264),s=r(3590),t=r(7633),o=r(797),i=r(8731),d={parse:(0,o.K2)(async e=>{const a=await(0,i.qg)("info",e);o.Rm.debug(a)},"parse")},g={version:n.n.version+""},p={parser:d,db:{getVersion:(0,o.K2)(()=>g.version,"getVersion")},renderer:{draw:(0,o.K2)((e,a,r)=>{o.Rm.debug("rendering info diagram\n"+e);const n=(0,s.D)(a);(0,t.a$)(n,100,400,!0);n.append("g").append("text").attr("x",100).attr("y",40).attr("class","version").attr("font-size",32).style("text-anchor","middle").text(`v${r}`)},"draw")}}}}]);
|
||||||
1
assets/js/749371cc.bcff9550.js
Normal file
1
assets/js/749371cc.bcff9550.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/7592.d6165eff.js
Normal file
1
assets/js/7592.d6165eff.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/7873.083fcc2e.js
Normal file
1
assets/js/7873.083fcc2e.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/7928.5f633e47.js
Normal file
1
assets/js/7928.5f633e47.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/7b5e550f.a397b62a.js
Normal file
1
assets/js/7b5e550f.a397b62a.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/8142.5edfc34d.js
Normal file
1
assets/js/8142.5edfc34d.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/8249.4f81048e.js
Normal file
1
assets/js/8249.4f81048e.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/8565.6a562290.js
Normal file
1
assets/js/8565.6a562290.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/8731.0fb86bab.js
Normal file
1
assets/js/8731.0fb86bab.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/8756.74d5516d.js
Normal file
1
assets/js/8756.74d5516d.js
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue