Merge branch 'main' into codex/update-setup-guidance-and-cli-checks
This commit is contained in:
commit
23fcae67cb
28
README.md
28
README.md
|
|
@ -115,15 +115,43 @@ python .\server.py
|
|||
|
||||
## 📋 Prerequisites
|
||||
|
||||
### Linux/macOS
|
||||
|
||||
| Tool | Required? | Install |
|
||||
|------|-----------|---------|
|
||||
| Python 3.10+ | ✅ Required | Install from your OS package manager or [python.org](https://www.python.org/downloads/) |
|
||||
| Node.js 18+ | ⚠ For opencode and Gemini CLI | Install from your OS package manager or [nodejs.org](https://nodejs.org/) |
|
||||
| Python 3.10+ | ✅ Required | Linux/macOS: install from your package manager or `python.org`. Windows: install from `python.org` and select **Add Python to PATH**. Verify with `python --version` or `py -3 --version`. |
|
||||
| Node.js 18+ | ⚠ For opencode | `curl -fsSL https://deb.nodesource.com/setup_20.x \| sudo bash - && sudo apt install -y nodejs` |
|
||||
| opencode | ⚠ For code tasks | `npm install -g @opencode/cli` |
|
||||
| Hermes Agent | ⚠ For memory/scheduling | Follow the upstream Hermes Agent documentation. If native Windows support is unavailable, use WSL for Hermes. |
|
||||
| Gemini CLI | ⚠ For Google AI | `npm install -g @google/gemini-cli` |
|
||||
|
||||
> ⚠ = Optional — the dashboard starts and core pages work without all agent CLIs installed. Agent-specific chat, routing, health, and skill execution features will show offline or warning status until the relevant CLI is installed and authenticated.
|
||||
### Windows
|
||||
|
||||
| Tool | Required? | Install | Verify / Next Step |
|
||||
|------|-----------|---------|--------------------|
|
||||
| Python 3.10+ | ✅ Required | Install from [python.org/downloads/windows](https://www.python.org/downloads/windows/) and enable **“Add python.exe to PATH”** during setup. | `python --version` |
|
||||
| Node.js 18+ | ⚠ For opencode and Gemini CLI | Install from [nodejs.org](https://nodejs.org/). | `node --version` and `npm --version` |
|
||||
| opencode | ⚠ For code tasks | `npm install -g @opencode/cli` | Confirm the CLI is available in a new terminal session. |
|
||||
| Gemini CLI | ⚠ For Google AI | `npm install -g @google/gemini-cli` | Run `gemini auth login` and complete OAuth in the browser. |
|
||||
| Hermes Agent | ⚠ For memory/scheduling | Windows support must be verified separately if the upstream installer remains Bash-only. | Check the upstream Hermes Agent install docs before relying on native Windows support. |
|
||||
|
||||
> ⚠ = Optional — the dashboard works with any subset of installed agents.
|
||||
|
||||
### Windows Quick Start
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/modimihir07/agentic-os.git
|
||||
cd agentic-os
|
||||
.\install.ps1
|
||||
.\start.ps1
|
||||
# Open http://127.0.0.1:8080
|
||||
```
|
||||
|
||||
The PowerShell launchers resolve Python in this order: `py -3.10`, `py -3`, then `python`. For manual commands, prefer `python -m pip install -r requirements.txt` and `python server.py --port 8080` so the same interpreter runs both dependency installation and the server.
|
||||
> **PowerShell execution policy:** if you use PowerShell scripts, allow local scripts for your user with `Set-ExecutionPolicy -Scope CurrentUser RemoteSigned`, or run a single installer invocation with `powershell -ExecutionPolicy Bypass -File .\install.ps1`.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
73
install.ps1
73
install.ps1
|
|
@ -76,6 +76,77 @@ if (-not (Test-Path ".git")) {
|
|||
foreach ($entry in @("audit/*", "backups/*.tar.gz", "data/settings.json")) {
|
||||
if ($gitignore -notcontains $entry) {
|
||||
Add-Content ".gitignore" $entry
|
||||
Write-Host "=== Agentic OS Installer ==="
|
||||
Write-Host ""
|
||||
|
||||
function Resolve-Python {
|
||||
$candidates = @(
|
||||
@{ Command = "py"; Args = @("-3.10") },
|
||||
@{ Command = "py"; Args = @("-3") },
|
||||
@{ Command = "python"; Args = @() }
|
||||
)
|
||||
|
||||
foreach ($candidate in $candidates) {
|
||||
$cmd = Get-Command $candidate.Command -ErrorAction SilentlyContinue
|
||||
if (-not $cmd) { continue }
|
||||
|
||||
try {
|
||||
& $candidate.Command @($candidate.Args) --version *> $null
|
||||
return $candidate
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
throw "Python 3.10+ is required. Install it from https://www.python.org/downloads/ and check 'Add Python to PATH'."
|
||||
}
|
||||
|
||||
$python = Resolve-Python
|
||||
$pythonCommand = $python.Command
|
||||
$pythonArgs = @($python.Args)
|
||||
$pythonVersion = & $pythonCommand @pythonArgs --version
|
||||
Write-Host "Python: $pythonVersion"
|
||||
|
||||
Write-Host "Installing Python dependencies..."
|
||||
& $pythonCommand @pythonArgs -m pip install -r requirements.txt --quiet
|
||||
|
||||
# Check Node.js (for opencode)
|
||||
if (Get-Command node -ErrorAction SilentlyContinue) {
|
||||
Write-Host "Node.js: $(node --version)"
|
||||
} else {
|
||||
Write-Warning "Node.js not found. opencode requires Node 18+. Install from https://nodejs.org/."
|
||||
}
|
||||
|
||||
# Check opencode
|
||||
if (Get-Command opencode -ErrorAction SilentlyContinue) {
|
||||
$opencodeVersion = try { opencode --version } catch { "installed" }
|
||||
Write-Host "opencode: $opencodeVersion"
|
||||
} else {
|
||||
Write-Warning "opencode not found. Install via: npm install -g @opencode/cli"
|
||||
}
|
||||
|
||||
# Check Hermes
|
||||
if (Get-Command hermes -ErrorAction SilentlyContinue) {
|
||||
Write-Host "Hermes: found"
|
||||
} else {
|
||||
Write-Warning "Hermes Agent not found. See the Hermes Agent documentation for Windows installation guidance."
|
||||
}
|
||||
|
||||
# Check Gemini CLI
|
||||
if (Get-Command gemini -ErrorAction SilentlyContinue) {
|
||||
Write-Host "Gemini CLI: found"
|
||||
} else {
|
||||
Write-Warning "Gemini CLI not found. Install via: npm install -g @google/gemini-cli"
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Force -Path backups, audit | Out-Null
|
||||
|
||||
if (-not (Test-Path .git)) {
|
||||
Write-Host "Initializing git repository..."
|
||||
git init
|
||||
foreach ($entry in @("audit/*", "backups/*.tar.gz", "data/settings.json")) {
|
||||
if (-not (Test-Path .gitignore) -or -not (Select-String -Path .gitignore -Pattern ([regex]::Escape($entry)) -Quiet)) {
|
||||
Add-Content -Path .gitignore -Value $entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,3 +163,5 @@ Write-Host "Optional agent CLI reminders:"
|
|||
Write-Host " opencode: npm install -g @opencode/cli"
|
||||
Write-Host " Gemini: npm install -g @google/gemini-cli"
|
||||
Write-Host " Hermes: Use upstream docs for native Windows support, or WSL if native support is unavailable."
|
||||
Write-Host " 2. Run .\start.ps1 to launch the dashboard"
|
||||
Write-Host " 3. Open http://127.0.0.1:8080 in your browser"
|
||||
|
|
|
|||
15
install.sh
15
install.sh
|
|
@ -14,22 +14,25 @@ esac
|
|||
echo "Detected OS: $OS"
|
||||
|
||||
# Check Python
|
||||
if command -v python3 &>/dev/null; then
|
||||
echo "Python: $(python3 --version)"
|
||||
if command -v python &>/dev/null; then
|
||||
PYTHON="python"
|
||||
elif command -v python3 &>/dev/null; then
|
||||
PYTHON="python3"
|
||||
else
|
||||
echo "ERROR: Python 3.10+ required. Install via: sudo apt install python3 python3-pip"
|
||||
echo "ERROR: Python 3.10+ required. Install from https://www.python.org/downloads/ or your OS package manager."
|
||||
exit 1
|
||||
fi
|
||||
echo "Python: $($PYTHON --version)"
|
||||
|
||||
# Check pip
|
||||
if ! command -v pip3 &>/dev/null; then
|
||||
if ! $PYTHON -m pip --version &>/dev/null; then
|
||||
echo "Installing pip..."
|
||||
python3 -m ensurepip --upgrade
|
||||
$PYTHON -m ensurepip --upgrade
|
||||
fi
|
||||
|
||||
# Install Python deps
|
||||
echo "Installing Python dependencies..."
|
||||
pip3 install -r requirements.txt --quiet
|
||||
$PYTHON -m pip install -r requirements.txt --quiet
|
||||
|
||||
# Check Node.js (for opencode)
|
||||
if command -v node &>/dev/null; then
|
||||
|
|
|
|||
34
server.py
34
server.py
|
|
@ -21,6 +21,8 @@ from fastapi.responses import HTMLResponse, JSONResponse, Response
|
|||
from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import BaseModel
|
||||
|
||||
BASE_DIR = Path(__file__).parent.resolve()
|
||||
|
||||
app = FastAPI(title="Agentic OS", version="1.1.0")
|
||||
|
||||
# Load OpenRouter API key from Hermes .env
|
||||
|
|
@ -33,16 +35,44 @@ if HERMES_ENV.exists():
|
|||
if k == "OPENROUTER_API_KEY":
|
||||
os.environ[k] = v # last value wins (matches shell sourcing)
|
||||
|
||||
def get_cors_origins() -> list[str]:
|
||||
"""Return local dashboard origins allowed to call the API."""
|
||||
port = 8080
|
||||
settings_file = BASE_DIR / "data" / "settings.json"
|
||||
|
||||
if settings_file.exists():
|
||||
try:
|
||||
settings = json.loads(settings_file.read_text(encoding="utf-8"))
|
||||
port = int(settings.get("dashboard", {}).get("port", port))
|
||||
except (json.JSONDecodeError, OSError, TypeError, ValueError):
|
||||
port = 8080
|
||||
|
||||
origins = {
|
||||
"http://127.0.0.1:8080",
|
||||
"http://localhost:8080",
|
||||
f"http://127.0.0.1:{port}",
|
||||
f"http://localhost:{port}",
|
||||
}
|
||||
|
||||
extra_origins = os.environ.get("AGENTIC_OS_CORS_ORIGINS", "")
|
||||
origins.update(
|
||||
origin.strip()
|
||||
for origin in extra_origins.split(",")
|
||||
if origin.strip()
|
||||
)
|
||||
|
||||
return sorted(origins)
|
||||
|
||||
|
||||
# CORS for local dev
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["http://127.0.0.1:8080", "http://localhost:8080"],
|
||||
allow_origins=get_cors_origins(),
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
BASE_DIR = Path(__file__).parent.resolve()
|
||||
|
||||
# ─── Models ───────────────────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
$ErrorActionPreference = "Stop"
|
||||
|
||||
Write-Host "Starting Agentic OS Dashboard..."
|
||||
Write-Host ""
|
||||
|
||||
if (-not (Test-Path server.py)) {
|
||||
Write-Error "server.py not found. Are you in the right directory?"
|
||||
exit 1
|
||||
}
|
||||
|
||||
function Resolve-Python {
|
||||
$candidates = @(
|
||||
@{ Command = "py"; Args = @("-3.10") },
|
||||
@{ Command = "py"; Args = @("-3") },
|
||||
@{ Command = "python"; Args = @() }
|
||||
)
|
||||
|
||||
foreach ($candidate in $candidates) {
|
||||
$cmd = Get-Command $candidate.Command -ErrorAction SilentlyContinue
|
||||
if (-not $cmd) { continue }
|
||||
|
||||
try {
|
||||
& $candidate.Command @($candidate.Args) --version *> $null
|
||||
return $candidate
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
throw "Python 3.10+ is required. Install it from https://www.python.org/downloads/ and check 'Add Python to PATH'."
|
||||
}
|
||||
|
||||
$python = Resolve-Python
|
||||
$pythonCommand = $python.Command
|
||||
$pythonArgs = @($python.Args)
|
||||
|
||||
& $pythonCommand @pythonArgs -m pip install -r requirements.txt --quiet
|
||||
|
||||
$port = & $pythonCommand @pythonArgs -c "import json; f=open('data/settings.json'); d=json.load(f); print(d.get('dashboard',{}).get('port',8080)); f.close()" 2>$null
|
||||
if (-not $port) { $port = "8080" }
|
||||
|
||||
Write-Host "Dashboard: http://127.0.0.1:$port"
|
||||
Write-Host "Press Ctrl+C to stop"
|
||||
Write-Host ""
|
||||
|
||||
& $pythonCommand @pythonArgs server.py --port $port
|
||||
19
start.sh
19
start.sh
|
|
@ -10,18 +10,25 @@ if [ ! -f server.py ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Resolve Python
|
||||
if command -v python &>/dev/null; then
|
||||
PYTHON="python"
|
||||
elif command -v python3 &>/dev/null; then
|
||||
PYTHON="python3"
|
||||
else
|
||||
echo "ERROR: Python 3.10+ required. Install from https://www.python.org/downloads/ or your OS package manager."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check dependencies
|
||||
pip3 install -r requirements.txt --quiet 2>/dev/null
|
||||
$PYTHON -m pip install -r requirements.txt --quiet 2>/dev/null
|
||||
|
||||
# Get port from settings or default
|
||||
PORT=8080
|
||||
if command -v python3 &>/dev/null; then
|
||||
PORT=$(python3 -c "import json; f=open('data/settings.json'); d=json.load(f); print(d.get('dashboard',{}).get('port',8080)); f.close()" 2>/dev/null || echo "8080")
|
||||
fi
|
||||
PORT=$($PYTHON -c "import json; f=open('data/settings.json'); d=json.load(f); print(d.get('dashboard',{}).get('port',8080)); f.close()" 2>/dev/null || echo "8080")
|
||||
|
||||
echo "Dashboard: http://127.0.0.1:${PORT}"
|
||||
echo "Press Ctrl+C to stop"
|
||||
echo ""
|
||||
|
||||
# Start server
|
||||
python3 server.py --port "${PORT}"
|
||||
$PYTHON server.py --port "${PORT}"
|
||||
|
|
|
|||
Loading…
Reference in New Issue