agent: avoid canceling foreground launches · Entire
agent: avoid canceling foreground launches
8d88ad6→main· peyton-alt·3w ago·2 files·+41 added/-2 removed
Sessions
1b6b555d42cdView transcript
?\ Add Trail Resume SubcommandCodex·GPT-5.5·1 step
Changes
2
cmd/entire/cli/agent
Mforeground.go+6/-2
Aforeground_test.go+35
8 unmodified lines
9
10
11
12
12
13
14
15
16
17
17
18
19
20
21
22
23
24
8 unmodified lines
// NewForegroundCommand builds an exec.Cmd wired to the caller's terminal.
// Agent launchers use this for commands the user should interact with directly.
func NewForegroundCommand(ctx context.Context, binary string, args ...string) (*exec.Cmd, error) {
func NewForegroundCommand(_ context.Context, binary string, args ...string) (*exec.Cmd, error) {
bin, err := exec.LookPath(binary)
if err != nil {
return nil, fmt.Errorf("%s binary not on PATH: %w", binary, err)
}
cmd := exec.CommandContext(ctx, bin, args...)
// Foreground agents are interactive terminal processes that handle SIGINT
// themselves. Binding them to the root command context would let
// exec.CommandContext SIGKILL them on Ctrl+C before they restore terminal
// state or persist session data.
cmd := exec.CommandContext(context.Background(), bin, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Mcmd/entire/cli/agent/foreground.go+6/-2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package agent
import (
"context"
"os"
"testing"
)
func TestNewForegroundCommandDoesNotBindToCallerCancellation(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithCancel(context.Background())
exe, err := os.Executable()
if err != nil {
t.Fatalf("os.Executable() error = %v", err)
}
cmd, err := NewForegroundCommand(ctx, exe, "-test.run=TestForegroundCommandHelperProcess", "--")
if err != nil {
t.Fatalf("NewForegroundCommand() error = %v", err)
}
cmd.Env = append(cmd.Env, "ENTIRE_FOREGROUND_HELPER_PROCESS=1")
cancel()
if err := cmd.Run(); err != nil {
t.Fatalf("foreground command should ignore caller cancellation and let the child run: %v", err)
}
}
func TestForegroundCommandHelperProcess(_ *testing.T) {
if os.Getenv("ENTIRE_FOREGROUND_HELPER_PROCESS") != "1" {
return
}
os.Exit(0)
}
Acmd/entire/cli/agent/foreground_test.go+35