Compare commits

...
Author SHA1 Message Date
MervinPraisonandClaude Opus 4.8 166091bc8e ci: add frontend build gate for BeautifulUI dashboard (fixes #295)
Adds a `frontend` job to CI that runs `npm ci && npm run build` for
src/frontend on every push/PR to main, failing on TypeScript/Vite build
errors. Uses Node 22 with npm caching keyed on the frontend lockfile.

Also documents the Node version, lockfile, and build/ship path in
src/frontend/README.md.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-09-23 13:50:39 +00:00
MervinPraisonandCursor 3058886312 chore: bump automation hub to v1.1.10 for merge gate fix
Co-authored-by: Cursor <[email protected]>
2026-09-22 15:30:07 +01:00
Mervin Praison 70d8610733 Merge pull request #291 from MervinPraison/claude/issue-290-20260916
docs: add SECURITY.md with private disclosure policy
2026-09-17 10:37:03 +01:00
MervinPraison 0f60ec41f1 Release v0.3.146 2026-09-17 03:02:10 +00:00
MervinPraisonandClaude Opus 4.8 2797667e04 docs: add SECURITY.md with private disclosure policy (fixes #290)
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-09-16 16:28:01 +00:00
Mervin Praison f23aacdec9 Merge pull request #289 from MervinPraison/claude/issue-286-20260915
fix: auto-load ~/.praisonai/.env on aiui run so env: channel tokens resolve
2026-09-16 14:43:31 +01:00
MervinPraisonandClaude Opus 4.8 8dc8b9f49f fix: auto-load ~/.praisonai/.env on aiui run so env: tokens resolve (fixes #286)
Channels configured with env:VAR token references silently resolved to
empty strings when the dashboard was started without the shell exporting
the tokens, so bots showed 'Connected' but never replied. aiui run now
loads the standard PraisonAI .env files (~/.praisonai/.env, then ./.env)
into the process environment at startup, matching the PraisonAI CLI
convention. Existing process vars are never overridden and parsing is
dependency-free (no python-dotenv).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-09-15 13:16:37 +00:00
15 changed files with 219 additions and 21 deletions

No files matched your search

+2 -2
View File
@@ -27,7 +27,7 @@ jobs:
permissions:
issues: write
pull-requests: write
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].8
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].10
secrets: inherit
with:
hub_ref: v1.1.8
hub_ref: v1.1.10
+2 -2
View File
@@ -16,8 +16,8 @@ permissions:
jobs:
recover:
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].8
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].10
secrets: inherit
with:
hub_ref: v1.1.8
hub_ref: v1.1.10
pr_number: ${{ github.event.inputs.pr_number || '' }}
+2 -2
View File
@@ -25,8 +25,8 @@ permissions:
jobs:
detect-and-trigger:
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].8
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].10
secrets: inherit
with:
hub_ref: v1.1.8
hub_ref: v1.1.10
pr_number: ${{ github.event.inputs.pr_number || '' }}
+24
View File
@@ -36,6 +36,30 @@ jobs:
- name: Integration smoke tests
run: pytest tests/integration/test_agentic_roundtrip.py tests/test_feature_sdk_backends.py -q --no-cov --timeout=120
frontend:
name: frontend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: src/frontend/package-lock.json
- name: Install dependencies
run: npm ci
working-directory: src/frontend
# `npm run build` is the dashboard ship path: dist/ is synced to
# src/praisonaiui/templates/frontend/ (see src/frontend/README.md).
- name: Build frontend
run: npm run build
working-directory: src/frontend
docs:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
+4 -4
View File
@@ -43,9 +43,9 @@ jobs:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: MervinPraison/github-automation-template/.github/actions/[email protected].8
- uses: MervinPraison/github-automation-template/.github/actions/[email protected].10
with:
hub_ref: v1.1.8
hub_ref: v1.1.10
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v1
@@ -87,9 +87,9 @@ jobs:
issues: write
actions: read
id-token: write
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].8
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].10
secrets: inherit
with:
hub_ref: v1.1.8
hub_ref: v1.1.10
pr_number: ${{ github.event.inputs.pr_number || github.event.client_payload.pr_number || '' }}
merge_method: ${{ github.event.inputs.merge_method || 'merge' }}
+2 -2
View File
@@ -18,7 +18,7 @@ jobs:
issues: write
actions: read
id-token: write
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].8
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].10
secrets: inherit
with:
hub_ref: v1.1.8
hub_ref: v1.1.10
+2 -2
View File
@@ -25,9 +25,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: MervinPraison/github-automation-template/.github/actions/[email protected].8
- uses: MervinPraison/github-automation-template/.github/actions/[email protected].10
with:
hub_ref: v1.1.8
hub_ref: v1.1.10
- name: Detect conflicting PRs and trigger Claude
uses: actions/github-script@v7
with:
+2 -2
View File
@@ -13,7 +13,7 @@ permissions:
jobs:
sync:
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].8
uses: MervinPraison/github-automation-template/.github/workflows/[email protected].10
secrets: inherit
with:
hub_ref: v1.1.8
hub_ref: v1.1.10
+37
View File
@@ -0,0 +1,37 @@
# Security Policy
We take the security of PraisonAIUI seriously and appreciate responsible
disclosure of vulnerabilities.
## Supported Versions
Security fixes are applied to the latest released version of PraisonAIUI.
Please make sure you are on the most recent release before reporting.
## Reporting a Vulnerability
**Please do not open a public issue for security vulnerabilities.**
Report privately through GitHub's **Private Vulnerability Reporting**:
1. Go to the [Security tab](https://github.com/MervinPraison/PraisonAIUI/security)
of this repository.
2. Click **"Report a vulnerability"** to open a private advisory.
3. Include as much detail as you can:
- Affected component(s) and version.
- Steps to reproduce.
- Impact assessment.
- Any suggested fix or mitigation.
If you are unable to use private reporting, you may open a public issue that
contains **no technical specifics** and requests a private channel, and a
maintainer will follow up.
## What to Expect
- We aim to acknowledge new reports within a few business days.
- We will keep you informed as we investigate and work on a fix.
- Once a fix is released, we are happy to credit you in the advisory (unless
you prefer to remain anonymous).
Thank you for helping keep PraisonAIUI and its users safe.
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "aiui"
version = "0.3.145"
version = "0.3.146"
description = "YAML-driven website generator - CLI and compiler"
readme = "README.md"
license = {text = "MIT"}
+23 -2
View File
@@ -1,6 +1,27 @@
# React + TypeScript + Vite
# PraisonAIUI Frontend (React + TypeScript + Vite)
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
The BeautifulUI dashboard source. Built with React 19 + Vite 7 + Tailwind v4.
## Build & CI
- **Node.js:** 22 (matches the `frontend` job in `.github/workflows/ci.yml`)
- **Lockfile:** `src/frontend/package-lock.json` — install with `npm ci`
```bash
cd src/frontend
npm ci
npm run build # SPA build → dist/ (dashboard ship path)
npm run build:lib # library build for the @praisonaiui/react package
npm run lint # eslint
```
`npm run build` output in `dist/` is synced to `src/praisonaiui/templates/frontend/`
(the committed bundle served by `aiui build`). The CI `frontend` job runs
`npm ci && npm run build` on PRs to `main` and fails on TypeScript/Vite errors.
## Vite template notes
This project uses a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
+1 -1
View File
@@ -1,3 +1,3 @@
"""Version information."""
__version__ = "0.3.145"
__version__ = "0.3.146"
+48
View File
@@ -44,6 +44,43 @@ def _icon(symbol: str, fallback: str) -> str:
return symbol if _supports_unicode() else fallback
def _load_env_files() -> int:
"""Load environment variables from the standard PraisonAI ``.env`` files.
Mirrors the PraisonAI CLI convention so ``env:VAR`` references (e.g. in
Channels config) resolve when the server was started without the shell
exporting the tokens. Reads ``~/.praisonai/.env`` first, then a ``.env`` in
the current working directory. Existing process env vars are never
overridden, and parsing is intentionally dependency-free (no python-dotenv).
Returns the number of variables newly set into ``os.environ``.
"""
import os
loaded = 0
for env_path in (Path.home() / ".praisonai" / ".env", Path.cwd() / ".env"):
try:
if not env_path.is_file():
continue
for line in env_path.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
if line.startswith("export "):
line = line[len("export "):]
key, value = line.split("=", 1)
key = key.strip()
value = value.strip().strip('"').strip("'")
if key and key not in os.environ:
os.environ[key] = value
loaded += 1
except Exception:
# Never let env loading break startup — resolution falls back to
# the existing process environment.
continue
return loaded
app = typer.Typer(
name="aiui",
help="PraisonAIUI - YAML-driven website generator",
@@ -1380,6 +1417,17 @@ def run(
console.print(f"[red]Error:[/red] App file not found: {app_file}")
raise typer.Exit(code=1)
# Auto-load standard PraisonAI env files so `env:VAR` references (e.g. in
# Channels config) resolve even when the shell did not export the tokens.
# This matches the PraisonAI CLI convention and fixes the "Connected but
# bot never replies" class of issues caused by empty env-resolved tokens.
_loaded = _load_env_files()
if _loaded:
console.print(
f"[green]{_icon('✓', 'OK')}[/green] Loaded {_loaded} environment "
f"variable(s) from PraisonAI config"
)
is_yaml = app_file.suffix in (".yaml", ".yml")
if is_yaml:
+68
View File
@@ -0,0 +1,68 @@
"""Unit tests for `_load_env_files` — auto-loading PraisonAI `.env` files.
Regression coverage for issue #286: `env:VAR` channel token references
resolved to empty strings because `aiui run` never loaded the standard
`~/.praisonai/.env` file, so bots showed "Connected" but never replied.
"""
import os
from praisonaiui.cli import _load_env_files
def _write_env(path, body):
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(body, encoding="utf-8")
def test_loads_home_praisonai_env(tmp_path, monkeypatch):
"""Variables in ~/.praisonai/.env are loaded into the process env."""
monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path)
monkeypatch.chdir(tmp_path)
monkeypatch.delenv("TELEGRAM_BOT_TOKEN", raising=False)
_write_env(tmp_path / ".praisonai" / ".env", 'TELEGRAM_BOT_TOKEN="123:AAtoken"\n')
loaded = _load_env_files()
assert loaded >= 1
assert os.environ["TELEGRAM_BOT_TOKEN"] == "123:AAtoken"
def test_does_not_override_existing_env(tmp_path, monkeypatch):
"""An already-set process variable is never clobbered by the file."""
monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path)
monkeypatch.chdir(tmp_path)
monkeypatch.setenv("SLACK_BOT_TOKEN", "xoxb-from-shell")
_write_env(tmp_path / ".praisonai" / ".env", "SLACK_BOT_TOKEN=xoxb-from-file\n")
_load_env_files()
assert os.environ["SLACK_BOT_TOKEN"] == "xoxb-from-shell"
def test_ignores_comments_blanks_and_export_prefix(tmp_path, monkeypatch):
"""Comments/blank lines are skipped and `export ` prefixes are stripped."""
monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path)
monkeypatch.chdir(tmp_path)
monkeypatch.delenv("FOO", raising=False)
monkeypatch.delenv("BAR", raising=False)
_write_env(
tmp_path / ".praisonai" / ".env",
"# a comment\n\nexport FOO=foo\nBAR='bar'\n",
)
_load_env_files()
assert os.environ["FOO"] == "foo"
assert os.environ["BAR"] == "bar"
def test_missing_files_are_harmless(tmp_path, monkeypatch):
"""No env files present → returns 0 and does not raise."""
monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path)
monkeypatch.chdir(tmp_path)
assert _load_env_files() == 0
Generated
+1 -1
View File
@@ -207,7 +207,7 @@ wheels = [
[[package]]
name = "aiui"
version = "0.3.145"
version = "0.3.146"
source = { editable = "." }
dependencies = [
{ name = "pydantic" },