chore: import upstream snapshot with attribution
CI / Run CI (push) Has been cancelled
CI / check-backend (push) Has been cancelled
CI / check-frontend (push) Has been cancelled
CI / tests (push) Has been cancelled
CI / e2e-tests (push) Has been cancelled
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:48:47 +08:00
commit b7f52be4c9
653 changed files with 105877 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
* @hayescode @asvishnyakov @sandangel
+41
View File
@@ -0,0 +1,41 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: needs-triage
assignees: ''
type: 'Bug'
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: needs-triage
assignees: ''
type: 'Feature'
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
@@ -0,0 +1,26 @@
name: Install Node, pnpm and dependencies.
description: Install Node, pnpm and dependencies using cache.
inputs:
node-version:
description: Node.js version
required: true
default: 'lts/*'
runs:
using: composite
steps:
- uses: pnpm/action-setup@v5.0.0
name: Install pnpm
with:
run_install: false
- name: Use Node.js
uses: actions/setup-node@v6.3.0
with:
node-version: ${{ inputs.node-version }}
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- name: Install JS dependencies
run: pnpm install
shell: bash
@@ -0,0 +1,37 @@
name: Install Python, uv and dependencies.
description: Install Python, uv and project dependencies using cache
inputs:
python-version:
description: Python version
required: true
default: '3.10'
uv-version:
description: uv version
required: true
default: 'latest'
uv-args:
description: Extra uv args, for example dependencies to install, e.g. --extra tests --extra dev.
required: false
working-directory:
description: Working directory for uv command.
required: false
default: .
runs:
using: composite
steps:
- name: Install uv
uses: astral-sh/setup-uv@v8.0.0
with:
version: ${{ inputs.uv-version }}
enable-cache: true
- name: Set up Python ${{ inputs.python-version }}
id: setup_python
uses: actions/setup-python@v6.2.0
with:
python-version: ${{ inputs.python-version }}
- name: Install Python dependencies
run: uv sync --all-packages ${{ inputs.uv-args }}
shell: bash
working-directory: ${{ inputs.working-directory }}
+194
View File
@@ -0,0 +1,194 @@
# Chainlit Development Instructions
Chainlit is a Python framework for building conversational AI applications with Python backend and React frontend. It uses uv for Python dependency management and pnpm for Node.js packages.
Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
## Working Effectively
### Bootstrap, Build, and Test the Repository
**CRITICAL**: All commands must complete - NEVER CANCEL any build or test operations. Use appropriate timeouts.
1. **Install Dependencies (Required first)**:
```bash
# Install uv (if not available)
python3 -m pip install pipx
python3 -m pipx install uv
export PATH="$HOME/.local/bin:$PATH"
# Install pnpm (if not available)
npm install -g pnpm
# Install Python dependencies - takes ~2 minutes, NEVER CANCEL
cd backend
uv sync --extra tests --extra mypy --extra dev --extra custom-data
# Timeout: Use 300+ seconds (5+ minutes)
# Install Node.js dependencies - takes ~3 minutes, NEVER CANCEL
cd ..
pnpm install --frozen-lockfile
# Timeout: Use 600+ seconds (10+ minutes)
# NOTE: Cypress download may fail due to network restrictions - this is expected in CI environments
```
2. **Run Tests**:
```bash
# Backend tests - takes ~17 seconds, NEVER CANCEL
cd backend
export PATH="$HOME/.local/bin:$PATH"
uv run pytest --cov=chainlit/
# Timeout: Use 120+ seconds (2+ minutes)
# Frontend tests - takes ~4 seconds
cd ../frontend
pnpm test
# Timeout: Use 60 seconds
# E2E tests require Cypress download - may not work in restricted environments
# If available: pnpm test:e2e (takes variable time depending on tests)
```
3. **Run Development Servers**:
```bash
# Start backend (in one terminal)
cd backend
export PATH="$HOME/.local/bin:$PATH"
uv run chainlit run chainlit/sample/hello.py -h
# Available at http://localhost:8000
# Start frontend dev server (in another terminal)
cd frontend
pnpm run dev
# Available at http://localhost:5173/
```
## Validation
### Manual Validation Requirements
- **ALWAYS** manually validate any changes by running complete scenarios.
- **ALWAYS** test the Chainlit application after making changes.
- Create a test app and verify it runs: `uv run chainlit run /path/to/test.py -h`
- **ALWAYS** run through at least one complete user workflow after making changes.
### Linting and Formatting - takes ~2 minutes, NEVER CANCEL
```bash
# Lint (check)
pnpm lint
# Timeout: Use 300+ seconds (5+ minutes)
# Lint (auto-fix)
pnpm lint:fix
# Check formatting
pnpm format-check
# Fix formatting
pnpm format
# Python (scripts/ wrappers around ruff and mypy)
uv run scripts/lint.py
uv run scripts/format.py
uv run scripts/format.py --check
```
### CI Requirements
- **ALWAYS** run `pnpm lint` and `pnpm format-check` before committing or the CI (.github/workflows/ci.yaml) will fail.
- The CI runs: pytest, lint-backend, lint-ui, and e2e-tests.
- **NEVER CANCEL** any CI commands - they take time but must complete.
## Key Project Structure
### Repository Root
```
/
├── README.md
├── CONTRIBUTING.md
├── package.json # Root pnpm workspace config
├── pnpm-workspace.yaml # Workspace definition
├── backend/ # Python backend with uv
├── frontend/ # React frontend app
├── libs/
│ ├── react-client/ # React client library
│ └── copilot/ # Copilot functionality
├── cypress/ # E2E tests
└── .github/
├── workflows/ # CI/CD pipelines
└── actions/ # Reusable GitHub actions
```
### Working with the Backend
- **Technology**: Python 3.10+ with uv, FastAPI, SocketIO
- **Entry point**: `backend/chainlit/`
- **Tests**: `backend/tests/`
- **Dependencies**: Defined in `backend/pyproject.toml`
- **Hello app**: `backend/chainlit/sample/hello.py`
### Working with the Frontend
- **Technology**: React 18+ with Vite, TypeScript, Tailwind CSS
- **Entry point**: `frontend/src/`
- **Dependencies**: Defined in `frontend/package.json`
- **Build output**: `frontend/dist/`
## Common Tasks
### Creating a New Chainlit App
```python
# Create app.py
import chainlit as cl
@cl.on_message
async def main(message: cl.Message):
await cl.Message(content=f"You said: {message.content}").send()
# Run it
uv run chainlit run app.py -w
```
### Timing Expectations
- **pnpm install**: ~3 minutes (may fail on Cypress - this is normal)
- **uv install**: ~2 minutes
- **pnpm build**: ~1 minute
- **pnpm run lint**: ~2 minutes
- **Backend tests**: ~17 seconds
- **Frontend tests**: ~4 seconds
- **pnpm format-check**: ~12 seconds
- **pnpm format**: ~12 seconds
### Common Gotchas
- **NEVER CANCEL** long-running operations - they need time to complete.
- Cypress download often fails in CI environments - this is expected.
- Use `uv run` prefix for all Python commands in backend.
- Use `export PATH="$HOME/.local/bin:$PATH"` to ensure uv is available.
- Python lint/format/type-check: use `uv run scripts/lint.py`, `uv run scripts/format.py`, `uv run scripts/type_check.py` from repo root.
- Frontend dev server connects to backend at localhost:8000.
- Always start backend before frontend for development.
### File Locations for Quick Reference
- **Main CLI**: `backend/chainlit/cli/`
- **Server code**: `backend/chainlit/server.py`
- **Frontend app**: `frontend/src/App.tsx`
- **React client**: `libs/react-client/src/`
- **CI workflows**: `.github/workflows/ci.yaml`
- **uv config**: `backend/pyproject.toml`
- **Frontend config**: `frontend/package.json`
## Requirements
- **Python**: >= 3.10
- **Node.js**: >= 20 (24+ recommended)
- **uv**: 2.1.3 (install via pipx)
- **pnpm**: Latest (install via npm)
+29
View File
@@ -0,0 +1,29 @@
name: Check backend
on: [workflow_call]
permissions:
contents: read
jobs:
check-backend:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: 'Linting: backend'
command: uv run --no-project scripts/lint.py
- name: 'Formatting: backend'
command: uv run --no-project scripts/format.py --check
- name: 'Type checking: backend'
command: uv run --no-project scripts/type_check.py
name: ${{ matrix.name }}
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/uv-python-install
name: Install Python, uv and Python dependencies
with:
uv-args: --no-install-workspace --all-extras --dev
- name: ${{ matrix.name }}
run: ${{ matrix.command }}
+29
View File
@@ -0,0 +1,29 @@
name: Check frontend & libs
on: [workflow_call]
permissions:
contents: read
jobs:
check-frontend:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: 'Linting: frontend'
command: pnpm lint
- name: 'Formatting: frontend'
command: pnpm format-check
- name: 'Type checking: frontend'
command: pnpm type-check
name: ${{ matrix.name }}
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/pnpm-node-install
name: Install Node, pnpm and dependencies.
- name: Build @chainlit/react-client
run: pnpm --filter @chainlit/react-client build
- name: ${{ matrix.name }}
run: ${{ matrix.command }}
+42
View File
@@ -0,0 +1,42 @@
name: CI
on:
workflow_call:
workflow_dispatch:
merge_group:
pull_request:
branches: [main, dev, 'release/**']
push:
branches: [main, dev, 'release/**']
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref_name != 'main' }}
permissions: read-all
jobs:
check-backend:
uses: ./.github/workflows/check-backend.yaml
secrets: inherit
check-frontend:
uses: ./.github/workflows/check-frontend.yaml
secrets: inherit
tests:
uses: ./.github/workflows/tests.yaml
secrets: inherit
e2e-tests:
uses: ./.github/workflows/e2e-tests.yaml
secrets: inherit
ci:
runs-on: ubuntu-slim
name: Run CI
if: always() # This ensures the job always runs
needs: [check-backend, check-frontend, tests, e2e-tests]
steps:
# Propagate failure
- name: Check dependent jobs
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'action_required') || contains(needs.*.result, 'timed_out')
run: |
echo "Not all required jobs succeeded"
exit 1
+30
View File
@@ -0,0 +1,30 @@
name: Close inactive issues and pull requests
on:
schedule:
- cron: '30 1 * * *'
workflow_dispatch:
jobs:
close-issues:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
operations-per-run: 400
ascending: true
days-before-issue-stale: 14
days-before-issue-close: 7
stale-issue-label: 'stale'
exempt-issue-labels: 'enhancement,dev-tooling,e2e-tests,unit-tests,keep-for-a-while'
stale-issue-message: 'This issue is stale because it has been open for 14 days with no activity.'
close-issue-message: 'This issue was closed because it has been inactive for 7 days since being marked as stale.'
days-before-pr-stale: 14
days-before-pr-close: 7
stale-pr-label: 'stale'
exempt-pr-labels: 'enhancement,dev-tooling,e2e-tests,unit-tests,keep-for-a-while'
stale-pr-message: 'This PR is stale because it has been open for 14 days with no activity.'
close-pr-message: 'This PR was closed because it has been inactive for 7 days since being marked as stale.'
repo-token: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,41 @@
name: 'Copilot Setup Steps'
# Automatically run the setup steps when they are changed to allow for easy validation, and
# allow manual testing through the repository's "Actions" tab
# This workflow optimizes the GitHub Copilot coding agent's ephemeral development environment
on:
workflow_dispatch:
push:
paths:
- .github/workflows/copilot-setup-steps.yaml
pull_request:
paths:
- .github/workflows/copilot-setup-steps.yaml
jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
copilot-setup-steps:
runs-on: ubuntu-latest
timeout-minutes: 15
# Set the permissions to the lowest permissions possible needed for your steps.
# Copilot will be given its own token for its operations.
permissions:
# If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
contents: read
# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install Node.js, pnpm and dependencies
uses: ./.github/actions/pnpm-node-install
- name: Install Python, uv and dependencies
uses: ./.github/actions/uv-python-install
with:
python-version: '3.10'
uv-version: 'latest'
uv-args: '--all-extras --dev'
+72
View File
@@ -0,0 +1,72 @@
name: E2E tests
on:
workflow_call:
inputs:
e2e_parallel_shards:
description: Number of parallel E2E shards per OS.
type: number
default: 5
permissions: read-all
jobs:
prepare:
name: Validate inputs and compute shard matrix
runs-on: ubuntu-slim
outputs:
indexes: ${{ steps.shard-indexes.outputs.indexes }}
steps:
- name: Validate e2e_parallel_shards
run: |
n="${{ inputs.e2e_parallel_shards }}"
if ! [[ "$n" =~ ^[0-9]+$ ]] || [[ "$n" -lt 1 ]]; then
echo "❌ Error: e2e_parallel_shards must be at least 1, got: $n"
exit 1
fi
echo "✅ Validation passed"
- id: shard-indexes
name: Compute shard indexes
run: |
json=$(jq -nc --argjson n "${{ inputs.e2e_parallel_shards }}" '[range(1; $n + 1)]')
echo "indexes=$json" >> "$GITHUB_OUTPUT"
e2e-tests:
needs: prepare
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
containers: ${{ fromJSON(needs.prepare.outputs.indexes) }}
name: ${{ matrix.os }}-${{ matrix.containers }}
env:
BACKEND_DIR: ./backend
# Single path for actions/cache on Linux + Windows (default Cypress dirs differ by OS).
CYPRESS_CACHE_FOLDER: ${{ github.workspace }}/.cypress-cache
steps:
- uses: actions/checkout@v6
- name: Cache Cypress binary
uses: actions/cache@v5
with:
path: .cypress-cache
key: cypress-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- uses: ./.github/actions/pnpm-node-install
name: Install Node, pnpm and dependencies.
- uses: ./.github/actions/uv-python-install
name: Install Python, uv and Python & pnpm (uv does it automatically) dependencies
with:
working-directory: ${{ env.BACKEND_DIR }}
uv-args: --extra tests
- name: Run tests
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
SPLIT: ${{ inputs.e2e_parallel_shards }}
SPLIT_INDEX1: ${{ matrix.containers }}
run: pnpm test:e2e
shell: bash
- name: Upload screenshots
uses: actions/upload-artifact@v7
if: always() && hashFiles('cypress/screenshots/**') != ''
with:
name: cypress-screenshots-${{ matrix.os }}-${{ matrix.containers }}
path: cypress/screenshots
+52
View File
@@ -0,0 +1,52 @@
name: Publish libs
on:
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run (test publishing)'
required: false
default: false
type: boolean
release:
types: [published]
permissions: read-all
jobs:
validate:
name: Validate inputs
runs-on: ubuntu-slim
steps:
- name: Validate publishing branch and destination package index
run: |
if [[ "${{ github.ref_name }}" != "main" && "${{ github.event_name }}" != "release" ]]; then
if [[ "${{ inputs.dry_run }}" != "true" ]]; then
echo "❌ Error: Only build from main branch or release tag can be published to npm registry."
echo "Please check 'Dry run (test publishing)' when running from branch: ${{ github.ref_name }}"
exit 1
fi
fi
echo "✅ Validation passed"
ci:
needs: [validate]
uses: ./.github/workflows/ci.yaml
secrets: inherit
build-n-publish:
name: Upload libs release to npm registry
runs-on: ubuntu-latest
needs: [ci]
permissions:
contents: read
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/pnpm-node-install
name: Install Node, pnpm and dependencies.
- name: Build react-client
run: pnpm --filter @chainlit/react-client build
- name: Publish packages to npm
# --no-git-checks allows testing from non-main branches and publishing from release tags
run: pnpm publish --recursive --no-git-checks ${{ inputs.dry_run && '--dry-run' || '' }}
+80
View File
@@ -0,0 +1,80 @@
name: Publish
on:
workflow_dispatch:
inputs:
use_testpypi:
description: 'Publish to TestPyPI instead of PyPI'
required: false
default: false
type: boolean
release:
types: [published]
permissions: read-all
jobs:
validate:
name: Validate inputs
runs-on: ubuntu-slim
steps:
- name: Validate publishing branch and destination package index
run: |
if [[ "${{ github.ref_name }}" != "main" && "${{ github.event_name }}" != "release" ]]; then
if [[ "${{ inputs.use_testpypi }}" != "true" ]]; then
echo "❌ Error: Only build from main branch or release tag can be published to PyPI."
echo "Please check 'Publish to TestPyPI instead of PyPI' when running from branch: ${{ github.ref_name }}"
exit 1
fi
fi
echo "✅ Validation passed"
ci:
needs: [validate]
uses: ./.github/workflows/ci.yaml
secrets: inherit
build-n-publish:
name: Upload release to PyPI/TestPyPI
runs-on: ubuntu-latest
needs: [ci]
env:
name: ${{ inputs.use_testpypi && 'testpypi' || 'pypi' }}
url: ${{ inputs.use_testpypi && 'https://test.pypi.org/project/chainlit' || 'https://pypi.org/project/chainlit' }}
BACKEND_DIR: ./backend
permissions:
contents: read
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/pnpm-node-install
name: Install Node, pnpm and dependencies.
- uses: ./.github/actions/uv-python-install
name: Install Python, uv and Python dependencies
with:
working-directory: ${{ env.BACKEND_DIR }}
- name: Build Python distribution
run: uv build
working-directory: ${{ env.BACKEND_DIR }}
- name: Check frontend and copilot folder included
run: |
pip install wheel
python -m wheel unpack dist/chainlit-*.whl -d unpacked
ls unpacked/chainlit-*/chainlit/frontend/dist
ls unpacked/chainlit-*/chainlit/copilot/dist
- name: Publish package distributions to TestPyPI
if: inputs.use_testpypi
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
repository-url: https://test.pypi.org/legacy/
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
verbose: true
- name: Publish package distributions to PyPI
if: ${{ !inputs.use_testpypi }}
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
password: ${{ secrets.PYPI_API_TOKEN }}
+28
View File
@@ -0,0 +1,28 @@
name: Unit & integration tests
on: [workflow_call]
permissions: read-all
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
name: python ${{ matrix.python-version }}
env:
BACKEND_DIR: ./backend
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/pnpm-node-install
name: Install Node, pnpm and dependencies.
- uses: ./.github/actions/uv-python-install
name: Install Python, uv and Python dependencies
with:
python-version: ${{ matrix.python-version }}
uv-args: --extra tests --extra custom-data
- name: Run backend tests
run: uv run --no-project pytest --cov=chainlit/
- name: Run frontend tests
run: pnpm run test