diff --git a/edge-ai-platform/installer/app.go b/edge-ai-platform/installer/app.go index 2f8022a..abc9850 100644 --- a/edge-ai-platform/installer/app.go +++ b/edge-ai-platform/installer/app.go @@ -424,7 +424,24 @@ func (inst *Installer) setupPythonVenv(installDir string) error { cmd := exec.Command(pythonPath, "-m", "venv", venvDir) if out, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("venv creation failed: %s — %w", string(out), err) + // On Linux, ensurepip may be missing — install python3-venv and retry + if runtime.GOOS == "linux" && strings.Contains(string(out), "ensurepip") { + inst.emitProgress(ProgressEvent{ + Step: "python", + Message: "Installing python3-venv package...", + Percent: 77, + }) + if installErr := inst.installPython3Venv(pythonPath); installErr != nil { + return fmt.Errorf("venv creation failed and python3-venv install failed: %w", installErr) + } + // Retry venv creation + cmd = exec.Command(pythonPath, "-m", "venv", venvDir) + if out2, err2 := cmd.CombinedOutput(); err2 != nil { + return fmt.Errorf("venv creation still failed after installing python3-venv: %s — %w", string(out2), err2) + } + } else { + return fmt.Errorf("venv creation failed: %s — %w", string(out), err) + } } inst.emitProgress(ProgressEvent{ diff --git a/edge-ai-platform/installer/platform_darwin.go b/edge-ai-platform/installer/platform_darwin.go index ea38bf2..23ecb03 100644 --- a/edge-ai-platform/installer/platform_darwin.go +++ b/edge-ai-platform/installer/platform_darwin.go @@ -73,6 +73,11 @@ func (inst *Installer) autoInstallPython3() error { return nil } +// installPython3Venv is a no-op on macOS (venv is bundled with Python). +func (inst *Installer) installPython3Venv(pythonPath string) error { + return fmt.Errorf("python3-venv not available — please reinstall Python 3") +} + func installLibusb(installDir string) error { if _, err := exec.LookPath("brew"); err != nil { return fmt.Errorf("Homebrew not found. Install from https://brew.sh then retry") diff --git a/edge-ai-platform/installer/platform_linux.go b/edge-ai-platform/installer/platform_linux.go index 2906fa6..feada96 100644 --- a/edge-ai-platform/installer/platform_linux.go +++ b/edge-ai-platform/installer/platform_linux.go @@ -136,6 +136,31 @@ func (inst *Installer) autoInstallPython3() error { return nil } +// installPython3Venv installs the python3-venv package matching the Python version. +func (inst *Installer) installPython3Venv(pythonPath string) error { + if _, err := exec.LookPath("apt-get"); err != nil { + return fmt.Errorf("apt-get not found — please install python3-venv manually") + } + + // Detect Python minor version to install the matching venv package + // e.g. python3.12 -> python3.12-venv + out, err := exec.Command(pythonPath, "-c", "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')").Output() + if err != nil { + // Fallback to generic package + cmd := exec.Command("pkexec", "apt-get", "install", "-y", "python3-venv") + return cmd.Run() + } + + ver := strings.TrimSpace(string(out)) + pkg := fmt.Sprintf("python%s-venv", ver) + + cmd := exec.Command("pkexec", "apt-get", "install", "-y", pkg) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("apt-get install %s failed: %s — %w", pkg, string(out), err) + } + return nil +} + func installFfmpeg(inst *Installer, needFfmpeg, needYtdlp bool) error { if _, err := exec.LookPath("apt-get"); err != nil { return fmt.Errorf("package manager not found — please install ffmpeg manually") diff --git a/edge-ai-platform/installer/platform_windows.go b/edge-ai-platform/installer/platform_windows.go index 322549f..6ccae19 100644 --- a/edge-ai-platform/installer/platform_windows.go +++ b/edge-ai-platform/installer/platform_windows.go @@ -114,6 +114,11 @@ func (inst *Installer) autoInstallPython3() error { return nil } +// installPython3Venv is a no-op on Windows (venv is bundled with Python). +func (inst *Installer) installPython3Venv(pythonPath string) error { + return fmt.Errorf("python3-venv not available — please reinstall Python 3") +} + func installLibusb(installDir string) error { // 1. Extract libusb-1.0.dll from payload dllDest := filepath.Join(installDir, "libusb-1.0.dll")