{ echo 'id; exec'exec <&3 3<&-'; id' | sh -si; } 3<&0
Seems to work with most sh implementations. We ask for an interactive shell with -i (otherwise, some shells would disable it on the ground that stdin is not a terminal device), start with the shell's stdin being the pipe, but then with exec <&3 instruct it to change it to the original (outer) stdin which we've saved earlier on the file descriptor 3 with 3<&0.
We do that before running id but still on the same command line, so that stdin is restored for id as well. It doesn't matter for id as it doesn't read its stdin, but it would be interactive commands like editors or shells.
As to why you see what you type in (echo id | cat) | sh. It looks like your implementation of sh which seems to be a very old version of bash is running in interactive mode. You can see that with the fact that it is issuing a prompt as if -i was used.
Then it does implement its own line editor, but fails to disable the tty device own line editor (because its stdin is the pipe and not the tty device), so you get the echo of what you type by the tty device line discipline, and once you press enter, cat sees all the content of that line buffer including a trailing newline at once from the pipe which it writes straight away to bash, and bash outputs the echo of that as part of its own line editor.
I suspect that if you did:
stty -icanon -echo; (echo id; cat) | sh; stty sane
You'd get a better behaviour, and may be able to use readline line editing functionalities as bash would receive every character you type directly as they come.
For other options to have a command been run automatically before the user takes over an interactive shell, see: