Session Lifecycle — Terminal Runtime Layer
How terminal sessions are created, used, and destroyed within the runtime layer.
Session States
session.create
│
▼
┌──────────┐
│ CREATING │ Setting up shell, env, cwd
└────┬─────┘
│ success
▼
┌─────────────────────┐
┌───>│ IDLE │<────────────┐
│ │ Ready for commands │ │
│ └─────────┬───────────┘ │
│ │ exec.run / exec.stream │
│ ▼ │
│ ┌──────────────────┐ │
│ │ RUNNING │ Command active │
│ │ stdout/stderr │ │
│ │ flowing │ │
│ └────────┬─────────┘ │
│ │ │
│ ┌───────┴────────┐ │
│ │ │ │
│ exit/timeout cancel │
│ │ │ │
│ ▼ ▼ │
│ result returned cancelled │
└────────────────────┴────────────────────┘
│
session.destroy
│
▼
┌──────────────┐
│ TERMINATED │ Cleaned up
└──────────────┘
State Descriptions
| State | Description | Allowed Actions |
|---|---|---|
| CREATING | Shell process is starting | Wait (internal only) |
| IDLE | Session is alive, no command running | exec.run, exec.stream, session.destroy, session.info |
| RUNNING | A command is actively executing | exec.cancel, session.info, session.destroy |
| TERMINATED | Session is dead, cleaned up | session.info (read-only) |
Session Creation
When session.create is called, the runtime:
- Generates a session ID (e.g.,
s-a1b2c3) - Resolves the shell (provided or
/bin/sh) - Prepares environment (runtime base + session-specific)
- Sets working directory
- Starts the shell process
- Registers in session pool
- Returns session metadata
Failure Modes
| Failure | Handling |
|---|---|
| Shell binary not found | Return error, no session created |
| Too many active sessions | Return MAX_SESSIONS_REACHED |
| Shell crashes immediately | Return error, clean up |
Command Execution Within a Session
Buffered Mode (exec.run)
- Agent sends
exec.runwith session ID and command - TRL checks session state is
IDLE - TRL writes command to session’s shell stdin
- TRL reads stdout/stderr until command completes (or timeout)
- TRL captures exit code, session returns to
IDLE - TRL returns
{stdout, stderr, exit_code, duration_ms}to agent
Streaming Mode (exec.stream)
- Agent sends
exec.stream; TRL returnsstream_id - TRL writes command to shell stdin
- As output arrives, TRL pushes chunks to agent
- On completion, TRL pushes final
exitchunk; session returns toIDLE
Timeout Handling
When a timeout fires:
- Send
SIGTERMto the command’s process group - Wait 5 seconds
- If still alive, send
SIGKILL - Return result with
timed_out: true - Session returns to
IDLE(session survives timeouts)
Session Destruction
When session.destroy is called:
- If a command is running, cancel it first (SIGTERM → SIGKILL)
- Send SIGTERM to the session’s shell process
- Wait up to 5 seconds for graceful exit
- If
force: trueor grace period exceeded, send SIGKILL - Close all pipes, remove from session pool
Zombie Prevention
- Use async process handling that automatically reaps
- Periodically scan for orphaned PIDs
- On runtime shutdown, destroy all active sessions
Session Pool Management
- max_sessions — configurable limit
- Housekeeping — periodic cleanup of stale/idle sessions, dead sessions
- Concurrency — multiple sessions can be IDLE or RUNNING; commands within a single session are sequential in buffered mode