diff --git a/agent/main.go b/agent/main.go index 814168a..57e5af7 100644 --- a/agent/main.go +++ b/agent/main.go @@ -231,6 +231,14 @@ func cmdRun() error { sup := engine.New(engine.Options{ Command: func(ctx context.Context) *exec.Cmd { cmd := exec.CommandContext(ctx, exe, cfg.EngineArgs...) + // Run the engine FROM a known directory rather than from whatever + // happened to launch us. A double-clicked bundle hands its child + // "/", and an engine invoked as `-m behavision` then cannot find + // itself - measured on macOS, where it retried forever. + cmd.Dir = cfg.EngineDir + if cmd.Dir == "" { + cmd.Dir = paths.InstallRoot() + } // How the engine learns where to send detections. The engine's // config already reads `events.webhook_url: ${BEHAVISION_WEBHOOK_URL}` // and python-dotenv does not override a variable the process diff --git a/agent/pkg/config/config.go b/agent/pkg/config/config.go index 52b01ee..92c0772 100644 --- a/agent/pkg/config/config.go +++ b/agent/pkg/config/config.go @@ -37,7 +37,18 @@ type Config struct { BrokerCAFile string `json:"broker_ca_file"` // Engine process. - EngineExe string `json:"engine_exe"` + EngineExe string `json:"engine_exe"` + // EngineDir is the working directory the engine is launched IN. Empty + // means the install root. + // + // It exists because nothing set it, so the engine inherited whatever + // launched the app - and for an app started by double-clicking its + // bundle that is "/", not anywhere useful. The symptom on macOS was + // `python: No module named behavision` repeating forever: the dev engine + // is `-m behavision`, which resolves against the working directory. The + // same app started from a terminal in the repo worked, which is exactly + // the shape of a bug that survives every test run by a developer. + EngineDir string `json:"engine_dir,omitempty"` EngineArgs []string `json:"engine_args"` APIBase string `json:"api_base"` APIUser string `json:"api_user"` diff --git a/desktop/app.go b/desktop/app.go index 8be79aa..8cfa1d8 100644 --- a/desktop/app.go +++ b/desktop/app.go @@ -105,6 +105,14 @@ func (a *App) startup(ctx context.Context) { a.sup = agentengine.New(agentengine.Options{ Command: func(c context.Context) *exec.Cmd { cmd := exec.CommandContext(c, exe, a.cfg.EngineArgs...) + // Run the engine FROM a known directory rather than from whatever + // happened to launch us. A double-clicked bundle hands its child + // "/", and an engine invoked as `-m behavision` then cannot find + // itself - measured on macOS, where it retried forever. + cmd.Dir = a.cfg.EngineDir + if cmd.Dir == "" { + cmd.Dir = agentpaths.InstallRoot() + } // How the engine learns where to post its detections. Its config // already reads `events.webhook_url: ${BEHAVISION_WEBHOOK_URL}`, // and python-dotenv does not override a variable the process