Scripts & Automation

Developer scripts for building, testing, and releasing PraisonAI

The src/praisonai/scripts/ folder contains automation scripts for development, testing, and release workflows.

Script Overview

ScriptPurpose
install.shFrictionless, environment-isolated one-liner installer (uv tool → pipx → venv fallback)
install.ps1One-liner installer for Windows
bump_and_release.pyAutomated version bump and release
bump_version.pyVersion management utility
check_version_sync.pyVerify version consistency across packages
release.pyPyPI release automation
test-install-smoke.shSmoke test the installer

One-Liner Installer

The installer scripts provide a frictionless installation experience:

macOS/Linux:

bash
curl -fsSL https://praison.ai/install.sh | bash

Windows PowerShell:

powershell
iwr -useb https://praison.ai/install.ps1 | iex

Features

  • OS Detection – Automatically detects macOS, Linux (various distros), Windows, WSL
  • Isolation Backend – Auto-selects uv tool → pipx → venv fallback; override with --backend
  • Python Management – Installs Python 3.10+ if not available (venv path only)
  • Package Manager Support – brew, apt, dnf, pacman, winget, chocolatey
  • PATH Shim – Drops ~/.local/bin/praisonai so the CLI is available without activating a venv
  • Idempotent PATH Block – Appends a clearly-marked # >>> PraisonAI PATH >>> block to shell rc; skip with --no-modify-path
  • Shell Completions – Offers to install bash/zsh/fish completions via praisonai completion <shell>
  • Interactive Onboarding – Prompts for LLM setup and bot configuration after installation
  • Dry Run Mode – Preview changes before applying

Environment Variables

VariableDefaultDescription
PRAISONAI_VERSIONlatestSpecific version to install
PRAISONAI_EXTRAS""Comma-separated extras (defaults to all)
PRAISONAI_BACKENDautoForce backend: uv / pipx / venv / system / auto
PRAISONAI_INSTALL_DIR~/.praisonaiBase dir for the venv fallback
PRAISONAI_NO_MODIFY_PATH0Skip shell rc PATH modification (1 to enable)
PRAISONAI_SKIP_VENV0Skip isolation entirely (1 to enable)
PRAISONAI_DRY_RUN0Preview mode
PRAISONAI_NO_ONBOARD0Skip interactive onboarding entirely

Examples

bash
# Basic install (isolated: uv tool -> pipx -> venv)
curl -fsSL https://praison.ai/install.sh | bash

# Force pipx backend
curl -fsSL https://praison.ai/install.sh | bash -s -- --backend pipx

# Install with extras
PRAISONAI_EXTRAS=ui,chat curl -fsSL https://praison.ai/install.sh | bash

# Don't touch shell rc
curl -fsSL https://praison.ai/install.sh | bash -s -- --no-modify-path

# Dry run (preview only)
PRAISONAI_DRY_RUN=1 curl -fsSL https://praison.ai/install.sh | bash

# Non-interactive for CI/CD
curl -fsSL https://praison.ai/install.sh | bash -s -- --no-prompt

Version Management

bump_version.py

Updates version across all package files:

bash
cd src/praisonai
python scripts/bump_version.py 2.3.0

Updates:

  • praisonai/version.py
  • pyproject.toml

check_version_sync.py

Verifies all packages have consistent versions:

bash
python src/praisonai/scripts/check_version_sync.py

Release Workflow

bump_and_release.py

Automated release pipeline:

bash
python src/praisonai/scripts/bump_and_release.py
  1. Bumps version
  2. Updates changelog
  3. Creates git tag
  4. Pushes to GitHub
  5. Triggers PyPI release

release.py

Manual PyPI release:

bash
python src/praisonai/scripts/release.py

Smoke Testing

test-install-smoke.sh

Tests the installer in isolated Docker containers:

bash
cd src/praisonai/scripts
./test-install-smoke.sh

Tests across:

  • Ubuntu 22.04
  • Debian 12
  • Alpine Linux

Docker Test Files

Located in scripts/docker/install-smoke/:

FilePurpose
DockerfileTest container image
run.shInstallation test script

Adding New Scripts

When adding new scripts:

  1. Location: Place in src/praisonai/scripts/
  2. Permissions: Make executable with chmod +x script.sh
  3. Documentation: Update this page
  4. Testing: Add to CI/CD if applicable
bash
# Make script executable
chmod +x src/praisonai/scripts/my-script.sh

# Test locally
./src/praisonai/scripts/my-script.sh

TypeScript SDK Scripts

The src/praisonai-ts/scripts/ folder holds Node scripts that run as part of the TypeScript SDK’s dual-build pipeline.

ScriptPurpose
clean (npm script)Deletes dist/ before each build (prebuild → clean). Uses the Node builtin fs.rmSync instead of a rimraf binary, so it runs before npm install populates devDependencies.
esm-shim.jsPost-processes the emitted ESM build so files that still use CJS globals (require, __dirname, __filename, module.exports) keep working under Node ESM. See TypeScript SDK Dual Build.
verify-dist.mjsSmoke-checks that both published entry points load and export Agent — CJS via require and ESM via import.
webview-gate.mjsFails the build if a Node builtin (fs, crypto, events, …) becomes reachable at import time from a webview/mobile entry point, and if the entry does not parse at FLOOR_TARGET = "chrome58" (the Android 8 WebView floor). Inspects both TypeScript sources and the built dist/esm/… artifacts.

clean (prebuild)

  • Runs before every build via the prebuild hook (npm run build → prebuild → clean).
  • Implemented as a Node one-liner: node -e "require('fs').rmSync('dist',{recursive:true,force:true})".
  • Needs no installed devDependencies — it runs even before npm install has populated node_modules. This lets npm ci succeed in a fresh worktree when a sibling package (e.g. praisonai-mobile) pulls praisonai-ts in via a file: link and triggers its prepare hook.
  • force: true makes it idempotent (no error when dist/ is absent), and fs.rmSync is cross-platform (Windows-safe).
  • Changed from rimraf dist in PR #4849.

esm-shim.js

  • Runs after the ESM build (npm run build:esm → tsc -p tsconfig.esm.json && node scripts/esm-shim.js).
  • Prepends a createRequire banner only to files that genuinely use CJS.
  • The banner is browser-safe: it uses guarded top-level await import('module' | 'url' | 'path').catch(() => null), so a bundler defers the imports rather than failing on them. Node behaviour is byte-identical.
  • In a browser, require is stubbed to a function that throws only if a lazy provider path is actually taken — the shim imposes no runtime cost on the webview path.
  • Fixed in PR #4484; the previous static-import form broke browser bundles of dist/esm/mobile.js.
  • Detection uses stripStringsAndComments to blank literal text and comments, but keeps template-literal ${...} interpolations intact so a real require(...) inside one is still detected.
  • Regression tests: src/praisonai-ts/tests/unit/packaging/esm-shim-banner.test.ts.

webview-gate.mjs

  • Inspects both the TypeScript sources (src/mobile.ts, src/agent/simple.ts) and the built artifacts (dist/esm/mobile.js, dist/esm/agent/simple.js) when dist/ exists.
  • On a fresh clone with no dist/, the gate prints a note and continues with the source-only check.
  • CI runs npm run build before the gate, so the built-artifact check runs on every PR — the gate sees exactly what ships.

# The two checks per entry

Checkesbuild targetUses metafile?Fails when
loadable in a webview["safari16", "chrome108"]yesa Node builtin is imported statically from the graph
bundles for chrome58["chrome58"]noesbuild refuses to lower the syntax (in practice: a top-level await anywhere on the graph, dynamically imported or not)

The chrome58 check is the one to reach for when a merge suddenly turns praisonai/mobile unbuildable on Android 8. The most common cause is that a source file added a require() or a __dirname, which made scripts/esm-shim.js prepend the createRequire banner to the emitted ESM file — and the banner IS a top-level await, so the entry stops parsing at chrome58. The gate reports the file and line; the fix is to convert the require() to a static import (no cycle) or to await import(…) (inside a function, not at module scope).

verify-dist.mjs

  • Runs as npm run verify:dist, wired into the release / publish smoke checks so a broken dist/ never ships.
  • Loads dist/index.js via CommonJS require(...) and dist/esm/index.js via ESM dynamic import(...), then asserts that each entry exports Agent. Exits non-zero if either entry fails to load or Agent is missing.
  • Cross-platform ESM path handling. path.join(root, 'dist', 'esm', 'index.js') returns a native path — on Windows that starts with a drive letter (e.g. F:\...\dist\esm\index.js), which Node’s ESM loader would reject as an unsupported URL scheme (ERR_UNSUPPORTED_ESM_URL_SCHEME, protocol f:). The script therefore converts the path with pathToFileURL(...).href before the dynamic import(...). The CJS require(...) line accepts native paths on every platform and is unchanged.
  • Fixed in PR #4923 (issue #4922).

Related