From 2bc8e909f12325af5601bae2daf3b72a3f39a5cf Mon Sep 17 00:00:00 2001 From: steelstring Date: Sun, 19 Apr 2026 15:20:21 +0800 Subject: [PATCH] Fix/desktop lite edition cmd exec failure (#961) * This fixes a data integrity issue affecting fresh installations of Desktop Lite and any environment where agent.other_config and serveral columns are not pre-initialized. This will stop Desktop Lite edtion from saving any agent setting. The root cause is missing default initialization of JSON field in update flow, leading to NOT NULL violations in both SQLite and Postgres. Fix ensures consistent behavior across Lite and Standard deployments. * Fix: Destop Lite Windows edition exec failure The executing of local commands use sh wrongly. --- internal/skills/dep_installer.go | 7 +++++-- internal/tools/credentialed_exec.go | 18 ++++++++++++++++-- internal/tools/shell.go | 13 ++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/internal/skills/dep_installer.go b/internal/skills/dep_installer.go index fe8f596f..eb4987ba 100644 --- a/internal/skills/dep_installer.go +++ b/internal/skills/dep_installer.go @@ -8,6 +8,7 @@ import ( "log/slog" "net" "os/exec" + "runtime" "strings" "time" ) @@ -285,6 +286,8 @@ func apkViaHelper(ctx context.Context, action, pkg string) (bool, string) { // cleanCaches removes pip and npm caches to save disk space. func cleanCaches(ctx context.Context) { - exec.CommandContext(ctx, "pip3", "cache", "purge").Run() //nolint:errcheck - exec.CommandContext(ctx, "sh", "-c", "rm -rf /tmp/npm-*").Run() //nolint:errcheck + exec.CommandContext(ctx, "pip3", "cache", "purge").Run() //nolint:errcheck + if runtime.GOOS != "windows" { + exec.CommandContext(ctx, "sh", "-c", "rm -rf /tmp/npm-*").Run() //nolint:errcheck + } } diff --git a/internal/tools/credentialed_exec.go b/internal/tools/credentialed_exec.go index 291e84fe..6d28eb9b 100644 --- a/internal/tools/credentialed_exec.go +++ b/internal/tools/credentialed_exec.go @@ -12,6 +12,7 @@ import ( "os/exec" "path/filepath" "regexp" + "runtime" "slices" "strings" "time" @@ -496,9 +497,22 @@ func (t *ExecTool) executeCredentialedSandbox(ctx context.Context, absPath strin // buildCredentialedEnv creates a minimal environment with injected credentials. // Inherits PATH and HOME from parent process, adds credential env vars. func buildCredentialedEnv(envMap map[string]string) []string { + var pathDefault string + var homeDefault string + if runtime.GOOS == "windows" { + pathDefault = "C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem" + homeDefault = os.Getenv("USERPROFILE") + if homeDefault == "" { + homeDefault = "C:\\Users\\Default" + } + } else { + pathDefault = "/usr/local/bin:/usr/bin:/bin" + homeDefault = "/tmp" + } + env := []string{ - "PATH=" + getenvDefault("PATH", "/usr/local/bin:/usr/bin:/bin"), - "HOME=" + getenvDefault("HOME", "/tmp"), + "PATH=" + getenvDefault("PATH", pathDefault), + "HOME=" + getenvDefault("HOME", homeDefault), "LANG=" + getenvDefault("LANG", "en_US.UTF-8"), "USER=" + getenvDefault("USER", "goclaw"), } diff --git a/internal/tools/shell.go b/internal/tools/shell.go index bced1086..78e0b526 100644 --- a/internal/tools/shell.go +++ b/internal/tools/shell.go @@ -9,6 +9,7 @@ import ( "os" "os/exec" "regexp" + "runtime" "strings" "time" @@ -360,9 +361,19 @@ func (t *ExecTool) executeOnHost(ctx context.Context, command, cwd string) *Resu ctx, cancel := context.WithTimeout(ctx, t.timeout) defer cancel() + //<<<<<<< HEAD + var cmd *exec.Cmd + if runtime.GOOS == "windows" { + cmd = exec.Command("cmd", "/c", command) + } else { + cmd = exec.Command("sh", "-c", command) + } + + //======= // Use plain exec.Command (not CommandContext) so we control the kill sequence. // CommandContext would SIGKILL only the direct child, leaving forked grandchildren alive. - cmd := exec.Command("sh", "-c", command) + // cmd := exec.Command("sh", "-c", command) + //>>>>>>> dev cmd.Dir = cwd // Scrub credential env vars so fall-through exec cannot exfiltrate