From d98508dafa7bcc7da03f5e975ec62c1b754c1cdc Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 21 May 2026 14:48:07 +0400 Subject: [PATCH] v3.2.1: Hermes install diagnostics and internal venv fixes --- .../main/java/ai/z/chat/BootstrapPlugin.java | 150 ++++++------------ 1 file changed, 51 insertions(+), 99 deletions(-) diff --git a/android/app/src/main/java/ai/z/chat/BootstrapPlugin.java b/android/app/src/main/java/ai/z/chat/BootstrapPlugin.java index 74b3675..d11b60c 100644 --- a/android/app/src/main/java/ai/z/chat/BootstrapPlugin.java +++ b/android/app/src/main/java/ai/z/chat/BootstrapPlugin.java @@ -593,78 +593,19 @@ public class BootstrapPlugin extends Plugin { return; } - String pythonBin = prefix + "/bin/python3"; - String pythonBinAlt = prefix + "/bin/python"; - - if (!new File(pythonBin).exists() && !new File(pythonBinAlt).exists()) { - Log.i(TAG, "Python not found, installing via pkg..."); - String pkgBin = prefix + "/bin/pkg"; - String aptBin = prefix + "/bin/apt"; - String installBin = new File(pkgBin).exists() ? pkgBin : aptBin; - - if (!new File(installBin).exists()) { - call.reject("Bootstrap not installed. Install dev tools first."); - return; - } - - ProcessBuilder pb = new ProcessBuilder("/system/bin/sh", "-c", - "export PREFIX=\"" + prefix + "\" LD_LIBRARY_PATH=\"" + prefix + "/lib\" PATH=\"" + prefix + "/bin:/system/bin:$PATH\" HOME=\"" + home + "\" ANDROID_API_LEVEL=\"" + android.os.Build.VERSION.SDK_INT + "\" && " + - "sh \"" + installBin + "\" install -y python clang rust make pkg-config libffi openssl 2>&1"); - pb.redirectErrorStream(true); - Process p = pb.start(); - String installOutput = drainProcess(p); - p.waitFor(300, java.util.concurrent.TimeUnit.SECONDS); - Log.i(TAG, "Python install output: " + installOutput.substring(0, Math.min(500, installOutput.length()))); - } - - if (!new File(pythonBin).exists() && !new File(pythonBinAlt).exists()) { - call.reject("Python installation failed. Try: pkg install python"); + JSObject setup = setupVirtualEnvInternal(prefix, home, venvDir); + String pipBin = setup.getString("pip"); + if (pipBin == null || !new File(pipBin).exists()) { + call.reject("Failed to prepare internal virtual environment"); return; } - String usePython = new File(pythonBin).exists() ? pythonBin : pythonBinAlt; + String pipOutput = runBootstrapCommand(prefix, home, + "\"" + pipBin + "\" install --upgrade pip setuptools wheel && " + + "\"" + pipBin + "\" install --prefer-binary hermes-agent"); - Log.i(TAG, "Creating Hermes Python venv..."); - ProcessBuilder pb = new ProcessBuilder(usePython, "-m", "venv", venvDir); - pb.environment().put("ANDROID_API_LEVEL", String.valueOf(android.os.Build.VERSION.SDK_INT)); - pb.environment().put("HOME", home); - pb.environment().put("LD_LIBRARY_PATH", prefix + "/lib"); - pb.environment().put("PREFIX", prefix); - pb.redirectErrorStream(true); - Process p = pb.start(); - String venvOutput = drainProcess(p); - p.waitFor(60, java.util.concurrent.TimeUnit.SECONDS); - Log.i(TAG, "venv output: " + venvOutput.substring(0, Math.min(300, venvOutput.length()))); - - String pipBin = venvDir + "/bin/pip"; - if (!new File(pipBin).exists()) { - call.reject("Failed to create Python venv: " + venvOutput.substring(0, Math.min(200, venvOutput.length()))); - return; - } - - Log.i(TAG, "Upgrading pip..."); - pb = new ProcessBuilder(pipBin, "install", "--upgrade", "pip", "setuptools", "wheel"); - pb.environment().put("ANDROID_API_LEVEL", String.valueOf(android.os.Build.VERSION.SDK_INT)); - pb.environment().put("HOME", home); - pb.environment().put("LD_LIBRARY_PATH", prefix + "/lib"); - pb.redirectErrorStream(true); - p = pb.start(); - drainProcess(p); - p.waitFor(120, java.util.concurrent.TimeUnit.SECONDS); - - Log.i(TAG, "Installing hermes-agent..."); - pb = new ProcessBuilder(pipBin, "install", "hermes-agent"); - pb.environment().put("ANDROID_API_LEVEL", String.valueOf(android.os.Build.VERSION.SDK_INT)); - pb.environment().put("HOME", home); - pb.environment().put("LD_LIBRARY_PATH", prefix + "/lib"); - pb.environment().put("PREFIX", prefix); - pb.redirectErrorStream(true); - p = pb.start(); - String pipOutput = drainProcess(p); - boolean pipOk = p.waitFor(600, java.util.concurrent.TimeUnit.SECONDS); - - if (!new File(venvDir + "/bin/hermes").exists()) { - call.reject("hermes-agent installation failed: " + pipOutput.substring(0, Math.min(500, pipOutput.length()))); + if (!new File(hermesLink).exists()) { + call.reject("hermes-agent installation failed: " + pipOutput.substring(0, Math.min(800, pipOutput.length()))); return; } @@ -731,36 +672,7 @@ public class BootstrapPlugin extends Plugin { String home = call.getString("home", homeDir + "/home"); String venvDir = call.getString("venv", filesDir + "/venv/default"); - new File(venvDir).getParentFile().mkdirs(); - String pkgBin = prefix + "/bin/pkg"; - String aptBin = prefix + "/bin/apt"; - String python3 = prefix + "/bin/python3"; - - if (!new File(pkgBin).exists() && !new File(aptBin).exists()) { - call.reject("Bootstrap tools missing. Install internal dev environment first."); - return; - } - - if (!new File(python3).exists()) { - String installer = new File(pkgBin).exists() ? pkgBin : aptBin; - runBootstrapCommand(prefix, home, - "sh \"" + installer + "\" install -y python clang rust make pkg-config libffi openssl"); - } - - if (!new File(python3).exists()) { - call.reject("python3 unavailable after install"); - return; - } - - runBootstrapCommand(prefix, home, - "\"" + python3 + "\" -m venv \"" + venvDir + "\" && " + - "\"" + venvDir + "/bin/pip\" install --upgrade pip setuptools wheel"); - - call.resolve(new JSObject() - .put("ok", true) - .put("venv", venvDir) - .put("python", venvDir + "/bin/python") - .put("pip", venvDir + "/bin/pip")); + call.resolve(setupVirtualEnvInternal(prefix, home, venvDir)); } catch (Exception e) { try { call.reject("setupVirtualEnv failed: " + e.getMessage()); } catch (Exception ignored) {} } @@ -788,7 +700,7 @@ public class BootstrapPlugin extends Plugin { } String output = runBootstrapCommand(prefix, home, - "\"" + pip + "\" install " + packages); + "\"" + pip + "\" install --prefer-binary " + packages); call.resolve(new JSObject().put("ok", true).put("output", output)); } catch (Exception e) { try { call.reject("venvPipInstall failed: " + e.getMessage()); } catch (Exception ignored) {} @@ -796,6 +708,46 @@ public class BootstrapPlugin extends Plugin { }).start(); } + private JSObject setupVirtualEnvInternal(String prefix, String home, String venvDir) throws Exception { + new File(venvDir).getParentFile().mkdirs(); + String pkgBin = prefix + "/bin/pkg"; + String aptBin = prefix + "/bin/apt"; + String python3 = prefix + "/bin/python3"; + + if (!new File(pkgBin).exists() && !new File(aptBin).exists()) { + throw new RuntimeException("Bootstrap tools missing. Install internal dev environment first."); + } + + if (!new File(python3).exists()) { + String installer = new File(pkgBin).exists() ? pkgBin : aptBin; + runBootstrapCommand(prefix, home, + "sh \"" + installer + "\" install -y python clang rust make pkg-config libffi openssl"); + } + + if (!new File(python3).exists()) { + throw new RuntimeException("python3 unavailable after install"); + } + + String venvPython = venvDir + "/bin/python"; + String venvPip = venvDir + "/bin/pip"; + if (!new File(venvPip).exists()) { + runBootstrapCommand(prefix, home, + "\"" + python3 + "\" -m venv \"" + venvDir + "\""); + } + if (!new File(venvPip).exists()) { + throw new RuntimeException("Failed to create Python venv"); + } + + runBootstrapCommand(prefix, home, + "\"" + venvPip + "\" install --upgrade pip setuptools wheel"); + + return new JSObject() + .put("ok", true) + .put("venv", venvDir) + .put("python", venvPython) + .put("pip", venvPip); + } + private String runBootstrapCommand(String prefix, String home, String command) throws Exception { ProcessBuilder pb = new ProcessBuilder("/system/bin/sh", "-c", "export PREFIX=\"" + prefix + "\" HOME=\"" + home + "\" " +