diff --git a/cmd/toolsrv/internal/exec/exec.go b/cmd/toolsrv/internal/exec/exec.go index 00b79b0..aaf7d90 100644 --- a/cmd/toolsrv/internal/exec/exec.go +++ b/cmd/toolsrv/internal/exec/exec.go @@ -87,7 +87,7 @@ func ExecuteTool(ctx context.Context, info protocol.ToolInfo, args json.RawMessa var result string if bypassed { bypassCode := fmt.Sprintf("cat <<'OLLIE_EOF' | %s\n%s\nOLLIE_EOF", toolPath, stdinData) - result, err = executeBypassDirect(ctx, bypassCode, cwd, cfg.Env, timeout, cfg.Started) + result, err = executeBypassDirect(ctx, bypassCode, cwd, cfg.Env, timeout, cfg.Output, cfg.Started) } else { result, err = executeSandboxed(ctx, toolPath, stdinData, cwd, cfg.Env, timeout, cfg.Yolo, cfg.Output, cfg.Started) } @@ -243,7 +243,7 @@ func executeSandboxed(ctx context.Context, toolPath, stdinData, cwd string, envE // executeBypassDirect requests bypass approval and executes the command directly. // The approval comes from olliesrv via the 9P bypass/pending and bypass/resolve files. -func executeBypassDirect(ctx context.Context, cmd, cwd string, envExtra map[string]string, timeout int, started chan StartResult) (string, error) { +func executeBypassDirect(ctx context.Context, cmd, cwd string, envExtra map[string]string, timeout int, streamOut io.Writer, started chan StartResult) (string, error) { // Build environment map envMap := make(map[string]string) for _, kv := range os.Environ() { @@ -277,11 +277,11 @@ func executeBypassDirect(ctx context.Context, cmd, cwd string, envExtra map[stri defer cancel() } - return executeDirectUnsandboxed(ctx, cmd, cwd, envMap, started) + return executeDirectUnsandboxed(ctx, cmd, cwd, envMap, streamOut, started) } // executeDirectUnsandboxed runs a command without any sandbox. -func executeDirectUnsandboxed(ctx context.Context, cmd, cwd string, env map[string]string, started chan StartResult) (string, error) { +func executeDirectUnsandboxed(ctx context.Context, cmd, cwd string, env map[string]string, streamOut io.Writer, started chan StartResult) (string, error) { execCmd := osExec.CommandContext(ctx, "bash", "-c", cmd) execCmd.Dir = cwd if len(env) > 0 { @@ -292,8 +292,14 @@ func executeDirectUnsandboxed(ctx context.Context, cmd, cwd string, env map[stri } var stdout, stderr bytes.Buffer - execCmd.Stdout = &stdout - execCmd.Stderr = &stderr + if streamOut != nil { + // Streaming mode: tee to both the stream and local buffer + execCmd.Stdout = io.MultiWriter(&stdout, streamOut) + execCmd.Stderr = io.MultiWriter(&stderr, streamOut) + } else { + execCmd.Stdout = &stdout + execCmd.Stderr = &stderr + } if err := execCmd.Start(); err != nil { if started != nil {