From 1d9537bc33c33e7252e65646e80cb88360c30511 Mon Sep 17 00:00:00 2001 From: Eva H <63033505+hoyyeva@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:57:35 -0700 Subject: [PATCH] launch/openclaw: fix --yes flag behaviour to skip channels configuration (#15589) --- cmd/launch/openclaw.go | 5 +++++ cmd/launch/openclaw_test.go | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/cmd/launch/openclaw.go b/cmd/launch/openclaw.go index f1279e054..d5980a532 100644 --- a/cmd/launch/openclaw.go +++ b/cmd/launch/openclaw.go @@ -186,6 +186,11 @@ func (c *Openclaw) runChannelSetupPreflight(bin string) error { if !isInteractiveSession() { return nil } + // --yes is headless; channel setup spawns an interactive picker we can't + // auto-answer, so skip it. Users can run `openclaw channels add` later. + if currentLaunchConfirmPolicy.yes { + return nil + } for { if c.channelsConfigured() { diff --git a/cmd/launch/openclaw_test.go b/cmd/launch/openclaw_test.go index 88593cdbc..434496bae 100644 --- a/cmd/launch/openclaw_test.go +++ b/cmd/launch/openclaw_test.go @@ -1304,6 +1304,46 @@ func TestOpenclawChannelSetupPreflight(t *testing.T) { } }) + t.Run("--yes skips preflight without channels configured", func(t *testing.T) { + tmpDir := t.TempDir() + setTestHome(t, tmpDir) + t.Setenv("PATH", tmpDir) + configDir := filepath.Join(tmpDir, ".openclaw") + if err := os.MkdirAll(configDir, 0o755); err != nil { + t.Fatal(err) + } + // Empty config = no channels configured. Without the --yes skip, the + // preflight would prompt and (on confirm) spawn `openclaw channels add`. + if err := os.WriteFile(filepath.Join(configDir, "openclaw.json"), []byte(`{}`), 0o644); err != nil { + t.Fatal(err) + } + bin := filepath.Join(tmpDir, "openclaw") + if err := os.WriteFile(bin, []byte("#!/bin/sh\nprintf '%s\\n' \"$*\" >> \"$HOME/invocations.log\"\n"), 0o755); err != nil { + t.Fatal(err) + } + + oldInteractive := isInteractiveSession + isInteractiveSession = func() bool { return true } + defer func() { isInteractiveSession = oldInteractive }() + + restore := withLaunchConfirmPolicy(launchConfirmPolicy{yes: true}) + defer restore() + + oldConfirmPrompt := DefaultConfirmPrompt + DefaultConfirmPrompt = func(prompt string, options ConfirmOptions) (bool, error) { + t.Fatalf("did not expect prompt in --yes mode: %s", prompt) + return false, nil + } + defer func() { DefaultConfirmPrompt = oldConfirmPrompt }() + + if err := c.runChannelSetupPreflight("openclaw"); err != nil { + t.Fatalf("runChannelSetupPreflight() error = %v", err) + } + if _, err := os.Stat(filepath.Join(tmpDir, "invocations.log")); !os.IsNotExist(err) { + t.Fatalf("expected no channels add invocation in --yes mode, got err=%v", err) + } + }) + t.Run("set up later prompts once and exits", func(t *testing.T) { tmpDir := t.TempDir() setTestHome(t, tmpDir)