Skip to main content

Module exec

Module exec 

Source
Expand description

Headless session backend: run the role’s [client.runtime] command as a child of the client.

The other two backends own a terminal — zellij a pane, Orca a tab — and the fake backend owns nothing at all, so none of them can serve a coding agent that must be run headlessly and reached over a socket (an e2e case with no window manager, a CI host, a supervisor that only needs the process). This backend is that path, and it is the one place in the tree that spawns a session command directly.

Process semantics, which is what makes it different from a naive Command::spawn:

  • stdin is a pipe the client holds open. An agent in RPC mode treats EOF on stdin as “the operator left” and exits, so Stdio::null() (immediate EOF) or a dropped ChildStdin would end it the moment it starts. The child’s stdin stays owned by the Child this backend keeps, so the write end lives until SessionBackend::close takes the child out.
  • stdout and stderr go to <workspace>/.onlyne/logs/session-<task>.log (both streams into one append handle, the shape an operator gives onlyne-client run for its own log). The agent’s own diagnostics are what an operator reads when a session misbehaves, so they must not disappear into the client’s stdio.
  • the child gets its own process group (unix), so a signal aimed at the client’s group — the operator’s terminal, a supervisor’s kill — does not reach the agent behind the drain: only SessionBackend::close ends a session, which is the contract a tab or a pane has too.
  • close is graceful before it is lethal: SIGTERM, then SIGKILL after the grace window, and force skips the grace. The child is reaped either way, so no zombie outlives its session. The group signal is kill(2) on the recorded pgid only (backend_ref.pgid, equal to the leader pid after process_group(0)). Close never matches cmdline text and refuses pid 0/-1.

Structs§

ExecBackend