Condense the documentation and thin the server's comments

The markdown had accumulated a lot that was stale rather than wrong.
PLAN.md still described pi as the llama.cpp harness, a refcounted
LlamaServerManager, and a providers-by-hosts cross-product, all of which
were superseded or never built; it also carried a second copy of the HTTP
table that routes.rs owns. EXPLORER.md and TRANSCRIPT_CACHE.md held
implementation checklists for work that has since landed. AGENTS.md
restated most of PLAN.md's design instead of being the working-notes
layer it says it is. 3225 lines of markdown to 2180, with the stale
sections gone rather than reworded.

On the server, comments explaining what the code already says are out and
the ones recording a constraint, a measurement or an incident are kept but
cut to a few lines each: 5504 comment lines to 4586.

Four doc comments in session/mod.rs, and one each in process.rs and
usage.rs, had drifted onto the item above the one they describe --
functions were reordered without them, so `stop_session`'s doc sat on
`set_session_cwd`, `stat_of`'s on `struct Stat`, and `UsageMonitor`'s on
`type Cached`. Each is back on its own item.

routes.rs's module table also claimed later phases would add `/hosts`,
which setups replaced.

cargo test (127 passed), clippy --all-targets and fmt are clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-09-04 15:45:43 -04:00
1 parent e3e02d55f7
commit 79682f03a7
24 files changed
+4572 -6821

No files matched your search

+59 -80
View File
@@ -1,23 +1,19 @@
//! Where a session's process runs, and the only place that knows how.
//!
//! A driver says *what* to run -- a [`Launch`] -- and hands it here.
//! Whether that becomes a child of this process or an `ssh host …`
//! invocation is settled in this module, so a driver carries no transport
//! knowledge and a second one cannot forget to handle the remote case. It
//! also means the wrapping is honest about drivers that run nothing at
//! all: `EchoDriver` builds no [`Launch`], so there is nothing to wrap and
//! no host for it to appear to honour.
//! A driver says *what* to run -- a [`Launch`] -- and hands it here. Whether
//! that becomes a child of this process or an `ssh host …` invocation is
//! settled in this module, so a driver carries no transport knowledge and a
//! second one cannot forget to handle the remote case. It also means the
//! wrapping is honest about drivers that run nothing at all: `EchoDriver`
//! builds no [`Launch`], so there is no host for it to appear to honour.
//!
//! The quoting, the forced ssh options and the remote script are
//! `crate::ssh`'s, which this dispatches to. That split is deliberate:
//! this module decides *which* transport, that one knows what a correct
//! ssh invocation is.
//! `crate::ssh`'s: this module decides *which* transport, that one knows what a
//! correct ssh invocation is.
//!
//! Known second operation, not built because nothing needs it yet: a
//! managed `llama-server` is spawned as a process but then spoken to over
//! HTTP, so a remote one needs a forwarded port (`ssh -L`) as well. A
//! transport is eventually "run this" plus "reach this port", where the
//! second is a no-op locally. See PLAN.md's SSH section.
//! Known second operation, not built because nothing needs it yet: a managed
//! `llama-server` is spawned as a process but then spoken to over HTTP, so a
//! remote one needs a forwarded port (`ssh -L`) as well.
use std::path::{Path, PathBuf};
use std::process::Stdio;
@@ -27,11 +23,9 @@ use tokio::process::Child;
use crate::config::SshConfig;
/// What a driver needs run in order to exist as a process.
///
/// Deliberately just the three things every transport can carry. Anything
/// a particular machine needs -- a port, a key, extra ssh options -- is
/// the transport's own configuration, not something a driver states.
/// What a driver needs run in order to exist as a process. Deliberately just
/// the three things every transport can carry; anything a particular machine
/// needs is the transport's own configuration, not something a driver states.
pub struct Launch {
pub program: String,
pub args: Vec<String>,
@@ -51,22 +45,20 @@ impl Launch {
/// How a launched process's standard streams are connected.
///
/// The choice is not the transport's and not the driver's dialect: it is
/// whether the process is expected to outlive this server. A probe is
/// asked a question and answers within one call, so pipes this server
/// drains are right and dying with it is right. A session is a
/// whether the process is expected to outlive this server. A probe answers
/// within one call, so pipes this server drains are right. A session is a
/// conversation somebody is having, so its streams live in the session
/// directory where a later run of this server can pick them up again --
/// see `session::process`.
/// directory where a later run of this server can pick them up.
pub enum Streams {
/// Pipes owned by this server; the child is killed when they drop.
Piped,
/// The same, except that stdin is already open on something this
/// server holds -- the file being copied to another machine. Bytes
/// this process has in memory do not need this: [`Streams::Piped`]
/// gives a pipe to write them into as the child reads.
/// The same, except that stdin is already open on something this server
/// holds -- the file being copied to another machine. Bytes this process has
/// in memory do not need this: [`Streams::Piped`] gives a pipe to write them
/// into as the child reads.
PipedFrom(Stdio),
/// Files -- and, for stdin, a fifo the child itself holds open so it
/// never reads EOF -- that outlast this process.
/// Files -- and, for stdin, a fifo the child itself holds open so it never
/// reads EOF -- that outlast this process.
Detached {
stdin: Stdio,
stdout: Stdio,
@@ -80,8 +72,7 @@ pub enum Transport {
Here,
/// Reached with the system `ssh` client. Owns its entry rather than
/// borrowing it, so a session keeps working against the config it was
/// spawned with even if the setup is edited afterwards. Carries the
/// setup's name only to say where things are running.
/// spawned with even if the setup is edited afterwards.
Ssh { name: String, ssh: SshConfig },
}
@@ -97,12 +88,10 @@ impl Transport {
}
}
/// Starts `launch` with its streams connected as `streams` says.
///
/// The failure names what to check, and the two transports fail for
/// genuinely different reasons -- a missing ssh client here versus a
/// program that is not on the remote PATH -- so each says its own
/// thing rather than one message hedging between them.
/// Starts `launch` with its streams connected as `streams` says. The failure
/// names what to check, and the two transports fail for genuinely different
/// reasons -- a missing ssh client here versus a program not on the remote
/// PATH -- so each says its own thing.
pub fn spawn(&self, launch: &Launch, streams: Streams) -> Result<Child> {
let host = match self {
Self::Here => None,
@@ -135,11 +124,9 @@ impl Transport {
stderr,
} => {
command.stdin(stdin).stdout(stdout).stderr(stderr);
// No `kill_on_drop`: outliving this server is the point.
// Its own process group as well, so a signal sent to the
// server's group -- which is how a terminal or a
// supervisor stops it -- does not travel to a session that
// is meant to survive being stopped.
// No `kill_on_drop`: outliving this server is the point. Its own
// process group as well, so a signal sent to the server's group
// does not travel to a session meant to survive being stopped.
command.process_group(0);
}
}
@@ -157,13 +144,10 @@ impl Transport {
})
}
/// Runs `launch` to completion and returns its stdout, blocking.
///
/// The synchronous twin of `capture`, for callers that are already on a
/// blocking task and would otherwise need a runtime to ask a machine a
/// question. Both build the invocation the same way -- see
/// `crate::ssh::command` -- so there is still only one description of
/// what running something on another machine means.
/// Runs `launch` to completion and returns its stdout, blocking. The
/// synchronous twin of `capture`, for callers already on a blocking task that
/// would otherwise need a runtime to ask a machine a question. Both build the
/// invocation the same way.
pub fn capture_blocking(&self, launch: &Launch) -> Result<String> {
let host = match self {
Self::Here => None,
@@ -189,21 +173,19 @@ impl Transport {
/// Runs `launch` with `input` on its stdin and reports everything it
/// produced -- stdout as bytes, stderr as text, and the exit status.
///
/// The one description of "run this there, with this on stdin", so
/// that shipping an attachment and writing a file through the explorer
/// are the same operation rather than two. It is also the only capture
/// that hands back the **status**: a script can then answer with an
/// exit code the caller distinguishes (the explorer's write says
/// `exit 3` for "this file is not the one you read"), which
/// [`Transport::capture`] cannot express because it turns every
/// failure into one error.
/// The one description of "run this there, with this on stdin", so that
/// shipping an attachment and writing a file through the explorer are the
/// same operation rather than two. It is also the only capture that hands
/// back the **status**: a script can answer with an exit code the caller
/// distinguishes (the explorer's write says `exit 3` for "this file is not
/// the one you read"), which [`Transport::capture`] cannot express.
///
/// Bytes rather than a `String`, because a file's contents are not
/// text until something has checked, and lossy decoding would replace
/// the evidence that they are not.
/// Bytes rather than a `String`, because a file's contents are not text
/// until something has checked, and lossy decoding would replace the
/// evidence that they are not.
///
/// `Err` means the process could not be started at all; a process that
/// ran and failed is a [`Captured`] with a status saying so.
/// `Err` means the process could not be started at all; a process that ran
/// and failed is a [`Captured`] with a status saying so.
pub async fn capture_with_input(&self, launch: &Launch, input: Input) -> Result<Captured> {
let (streams, to_write) = match input {
Input::None => (Streams::Piped, None),
@@ -212,13 +194,11 @@ impl Transport {
};
let mut child = self.spawn(launch, streams)?;
if let Some(bytes) = to_write {
// Written from a task rather than before the wait, because the
// child may not read all of it -- the write script exits
// without reading when the file has changed underneath -- and
// a caller blocked on filling a pipe nobody is draining would
// deadlock instead of getting that answer. The broken pipe is
// the expected end of this write, so it is dropped: what
// happened is the exit status below.
// Written from a task rather than before the wait, because the child
// may not read all of it -- the write script exits without reading
// when the file has changed underneath -- and a caller blocked on
// filling a pipe nobody is draining would deadlock instead of getting
// that answer. The broken pipe is the expected end of this write.
let mut stdin = child.stdin.take().context("the child has no stdin")?;
tokio::spawn(async move {
use tokio::io::AsyncWriteExt;
@@ -248,11 +228,11 @@ impl Transport {
/// What a command is given on its standard input.
///
/// Three cases rather than an `Option<Stdio>` because they are three
/// genuinely different arrangements and only this knows which: nothing to
/// say, bytes this process is holding, or a file it has open. The last one
/// is how a several-hundred-megabyte attachment reaches another machine
/// without passing through this server's memory.
/// Three cases rather than an `Option<Stdio>` because they are three genuinely
/// different arrangements and only this knows which: nothing to say, bytes this
/// process is holding, or a file it has open. The last is how a
/// several-hundred-megabyte attachment reaches another machine without passing
/// through this server's memory.
pub enum Input {
None,
Bytes(Vec<u8>),
@@ -263,10 +243,9 @@ pub enum Input {
pub struct Captured {
pub status: std::process::ExitStatus,
pub stdout: Vec<u8>,
/// Trimmed, and what a failure is reported as: ssh's own refusals and
/// a tool's own message about the file it could not open are both the
/// useful half of why something did not work, and both are written to
/// name the thing.
/// Trimmed, and what a failure is reported as: ssh's own refusals and a
/// tool's own message about the file it could not open are both the useful
/// half of why something did not work.
pub stderr: String,
}