feat(runtime): add shell detach and reattach - #2199
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## aidandaly/runtime-shell #2199 +/- ##
==========================================================
Coverage ? 97.02%
==========================================================
Files ? 551
Lines ? 38370
Branches ? 0
==========================================================
Hits ? 37227
Misses ? 1143
Partials ? 0 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
AgentCore Harness Review
Verdict: Changes requested
Ctrl+] does not actually detach — it kills the shell
RuntimeShellSessionAdapter.detach() (in src/core/runtimeShell.ts, line 146‑148) is implemented as:
detach(): Promise<void> {
return this.session.close();
}But per the published bedrock-agentcore 0.4.3 SDK (ShellSession.close(), runtime/shell/session.d.ts line 159‑162):
Send a CLOSE frame (0xFF) to permanently kill the shell, then close the WebSocket. The server kills the shell process (SIGHUP → SIGKILL) and responds with its own [0xFF]. Unlike dropping the WebSocket (which detaches and allows reconnection), this is permanent.
So the new "detach" path — Ctrl+] in InteractiveTerminal.onData → peer.detach() → adapter → ShellSession.close() → 0xFF CLOSE — actually terminates the remote shell. The follow-up message emitted in src/handlers/runtime/shell/operation.ts (lines 55‑61):
Detached.
To reattach:
agentcore runtime shell --id ... --session-id ... --shell-id ...
will be a lie: by the time it prints, the server has already SIGKILL'd the shell, and re-running with the printed --shell-id won't reattach. The user-facing README change also promises "Ctrl+] detaches the client while leaving the shell available for reattachment," which is not what actually happens.
The existing tests don't catch this because they mock at the RuntimeShellSdkSession/FakePeer level and only assert that detach() was called, not that the underlying wire behavior is a detach rather than a close.
Possible fixes:
- Wait for a real SDK detach method.
bedrock-agentcore@0.4.3doesn't expose a public detach — the only comparable capability is_terminateConnection(), which is marked@internal. If AWS is planning to ship one (e.g. adetach()onShellSessionthat drops the socket without sending 0xFF), gate this PR on that release and switch the adapter to call it. - Use the currently-internal
_terminateConnection()as a stopgap, with a comment/TODO — it does exactly what's needed (drops the socket without CLOSE). Not ideal since it's@internal, but at least it matches the advertised behavior. - Drop the socket manually — e.g. call the internal WebSocket's
terminate()/close()without going throughShellSession.close(). Also fragile. - Remove Ctrl+] detach and the reattach messaging from this PR and land only the
--session-id/--shell-idreattach inputs plus theshellIdecho, so the reattach UX doesn't ship broken.Ctrl+]can be re-added once the SDK supports a real detach.
Also worth adding, once the semantics are fixed: an integration/handler-level test that exercises the full detach path (Ctrl+] → terminal.run returns {detached: true} → operation prints reattach hint) against something more faithful than a peer/session that just increments counters, so this class of regression is caught next time.
Minor
- The
finallyinoperation.tsunconditionally callssession.detach()even after a clean shell exit. Today that's benign because the SDK'sclose()is idempotent, but once (1) above is fixed, double-check the natural-exit branch still tears the socket down cleanly.
75c462d to
cdcd304
Compare
cdcd304 to
4670d78
Compare
4670d78 to
ce13f83
Compare
ce13f83 to
f81db77
Compare
f81db77 to
4a4289a
Compare
Summary
Stacked on #2198.
Adds explicit detach and reattach behavior to Runtime Shell:
Ctrl+]detaches the local client while preserving the remote shell.--session-idwith--shell-idreattaches to an existing shell.--session-idwhenever--shell-idis supplied.The same ownership boundaries remain in place:
Command
Validation
CI=true bun test --coverage --coverage-reporter=lcovbun run typecheckbun run lint:checkbun run format:checkbun run secrets:checkbun run buildLive detach/reattach validation used the TypeScript SDK PR #249 implementation
and covered:
Ctrl+]detachMerge blocker
Keep this PR in draft until the corrected TypeScript SDK shell lifecycle is
published and this branch is updated to that release.
The current npm release (
bedrock-agentcore0.4.3) exposes the API required tocompile this branch, but
ShellSession.close()terminates the remote PTY. ThisPR's CLI
detach()adapter currently delegates to that method, so shipping iton
0.4.3would present detach as successful while destroying the shell thatthe user expects to reattach to.
The required SDK behavior is tracked by
aws/bedrock-agentcore-sdk-typescript#249.