install.ps1
Rama main · réplica de lectura del repositorio original.
# OpenCompany Installer for Windows
# Usage: iwr -useb https://raw.githubusercontent.com/zeenie-ai/OpenCompany/main/install.ps1 | iex
#
# This script installs OpenCompany and its dependencies:
# - bun (the JavaScript runtime and package manager; no Node.js, no npm)
# - Python 3.12+ (via winget/choco)
# - uv (Python package manager)
#
# Prefer the desktop app if you just want to use OpenCompany on a laptop; this
# path is for terminal use.
$ErrorActionPreference = "Stop"
$MIN_PYTHON_VERSION = "3.12"
$PKG_NAME = "@zeenie-ai/opencompany"
# Colors
function Write-Color {
param([string]$Text, [string]$Color = "White")
Write-Host $Text -ForegroundColor $Color
}
function Info { Write-Color "[INFO] $args" "Cyan" }
function Success { Write-Color "[OK] $args" "Green" }
function Warn { Write-Color "[WARN] $args" "Yellow" }
function Error-Exit { Write-Color "[ERROR] $args" "Red"; exit 1 }
# Banner
Write-Host ""
Write-Color " OpenCompany" "Cyan"
Write-Host ""
Write-Host "Self-improving AI employees, running on your own computer"
Write-Host ""
# Check if command exists
function Has-Command {
param([string]$Command)
$null -ne (Get-Command $Command -ErrorAction SilentlyContinue)
}
# Get package manager
function Get-PackageManager {
if (Has-Command "winget") { return "winget" }
if (Has-Command "choco") { return "choco" }
return $null
}
# Refresh PATH from registry
function Refresh-Path {
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
}
# bun installs to $env:BUN_INSTALL (default ~\.bun) and puts global bin shims
# in its bin dir. Where it stores the global package itself varies, so nothing
# below depends on that: the `company` shim knows its own package root and
# `company provision` does the rest.
$BUN_HOME = if ($env:BUN_INSTALL) { $env:BUN_INSTALL } else { Join-Path $env:USERPROFILE ".bun" }
$BUN_BIN_DIR = Join-Path $BUN_HOME "bin"
# =============================================================================
# Dependency Checks and Installation
# =============================================================================
function Check-Bun {
if (Has-Command "bun") {
Success "bun $(bun --version)"
return $true
}
return $false
}
function Install-Bun {
Info "Installing bun (JavaScript runtime and package manager)..."
Invoke-RestMethod https://bun.sh/install.ps1 | Invoke-Expression
$env:Path = "$BUN_BIN_DIR;$env:Path"
Refresh-Path
$env:Path = "$BUN_BIN_DIR;$env:Path"
if (-not (Check-Bun)) {
Error-Exit "Failed to install bun. Install it manually from https://bun.sh and restart PowerShell."
}
}
function Check-Python {
foreach ($cmd in @("python", "python3")) {
if (Has-Command $cmd) {
$versionOutput = & $cmd --version 2>&1
if ($versionOutput -match "Python (\d+)\.(\d+)") {
$major = [int]$Matches[1]
$minor = [int]$Matches[2]
if ($major -ge 3 -and $minor -ge 12) {
Success "Python $major.$minor ($cmd)"
$script:PYTHON_CMD = $cmd
return $true
}
}
}
}
Warn "Python $MIN_PYTHON_VERSION+ not found"
return $false
}
function Install-Python {
Info "Installing Python $MIN_PYTHON_VERSION..."
$pm = Get-PackageManager
switch ($pm) {
"winget" {
winget install Python.Python.3.12 --accept-package-agreements --accept-source-agreements
}
"choco" {
choco install python312 -y
}
default {
Error-Exit "Please install winget or chocolatey, or install Python manually from https://python.org/"
}
}
Refresh-Path
if (-not (Check-Python)) {
Error-Exit "Failed to install Python. Please install manually and restart PowerShell."
}
}
function Check-Uv {
if (Has-Command "uv") {
$version = (uv --version) -replace "uv ", ""
Success "uv $version"
return $true
}
return $false
}
function Install-Uv {
Info "Installing uv (Python package manager)..."
# Try pip first
if ($script:PYTHON_CMD) {
try {
& $script:PYTHON_CMD -m pip install uv 2>&1 | Out-Null
Refresh-Path
if (Check-Uv) { return }
} catch {}
}
# Fallback to official installer
Invoke-RestMethod https://astral.sh/uv/install.ps1 | Invoke-Expression
$env:Path = "$env:USERPROFILE\.local\bin;$env:Path"
if (-not (Check-Uv)) {
Error-Exit "Failed to install uv"
}
}
# A previous npm-based install (or the pre-rebrand `machinaos` package) leaves
# a `company` / `machina` shim on PATH that would shadow the bun one. Remove it
# when npm happens to be around; skip silently otherwise.
function Remove-LegacyNpmInstalls {
if (-not (Has-Command "npm")) { return }
foreach ($pkg in @($PKG_NAME, "machinaos")) {
npm list -g --depth=0 $pkg *> $null
if ($LASTEXITCODE -eq 0) {
Info "Removing legacy npm install of $pkg..."
npm uninstall -g $pkg *> $null
if ($LASTEXITCODE -ne 0) { Warn "Could not remove $pkg; run: npm uninstall -g $pkg" }
}
}
}
# =============================================================================
# Main Installation Flow
# =============================================================================
function Main {
Write-Host ""
Info "Checking dependencies..."
Write-Host ""
# Check and install dependencies
if (-not (Check-Bun)) { Install-Bun }
if (-not (Check-Python)) { Install-Python }
if (-not (Check-Uv)) { Install-Uv }
Remove-LegacyNpmInstalls
Write-Host ""
Info "Installing OpenCompany..."
Write-Host ""
# bun finds its global "project" by walking up from $BUN_INSTALL\install\global
# until it meets a package.json. A stray package.json or package-lock.json in
# the user profile (an old npm mishap) therefore hijacks global installs and
# `bun add -g` fails with "InvalidNPMLockfile" (docs-internal/errors.md #23).
# Giving the global dir its own manifest stops the walk-up.
$globalDir = Join-Path $BUN_HOME "install\global"
New-Item -ItemType Directory -Force -Path $globalDir | Out-Null
$globalManifest = Join-Path $globalDir "package.json"
if (-not (Test-Path $globalManifest)) {
Set-Content -Path $globalManifest -Value '{ "private": true }' -Encoding utf8
}
# Global install as the current user (bun's global root is user-owned).
bun add -g $PKG_NAME
if ($LASTEXITCODE -ne 0) {
Error-Exit "bun add -g $PKG_NAME failed."
}
# bun runs no lifecycle scripts for a global package, so provision the
# Python side now rather than on the first `company` command. The shim is
# addressed through bun's own answer for the global bin dir.
$company = Join-Path (bun pm bin -g) "company.exe"
Info "Provisioning the Python environment..."
& $company provision
if ($LASTEXITCODE -ne 0) {
Error-Exit "Provisioning failed. Re-run with: company provision"
}
Write-Host ""
Write-Color "============================================" "Green"
Write-Color " OpenCompany installed successfully!" "Green"
Write-Color "============================================" "Green"
Write-Host ""
Write-Host " Start OpenCompany:"
Write-Host " company start"
Write-Host ""
Write-Host " Run diagnostics:"
Write-Host " company doctor"
Write-Host ""
Write-Host " If 'company' is not found, open a new PowerShell window (bun's bin dir"
Write-Host " was added to your PATH)."
Write-Host ""
}
# Run main
Main