Start a stopped session's process for a command too
Same reasoning as the message path a commit ago, and the same objection
to leaving it out: a command is something somebody asked the session to
do, and answering "its process has exited" hands back the work of
starting one. `/compact` on a stopped session is the case that shows it
-- what is being asked for is exactly what a stopped session needs
before it is useful again.
`POST /sessions/{id}/command` and `/compact` now go through
`SessionManager::run_command`. A rename is deliberately not one of them:
it is persisted and listed whether or not a process ever hears about it,
so starting a CLI to tell it a name would be spending a resume on
nothing. It stays a forward to a process that happens to be there.
A command needs one thing a message did not. `Commands::submit` refuses
on `Exited`, and a driver that has just started a process announces
`Idle` through the sink rather than writing it -- so a command judged
against the session's own status would be refused by the word the start
had just replaced, in a window narrow enough that only a test reliably
hits it. `start_if_exited` returning `Exited` is what says a process was
started, so the status the command is judged against comes from there
rather than from a re-read the pump may not have caught up with. The
test fails without it.
`LiveSession::compact` went with this: `/compact` the route and
"/compact" the typed command were two ways to the same command, and now
there is one.
Verified over the API against a stand-in CLI: with the session reporting
`exited`, both `/clear` and `POST /compact` started the process and were
delivered -- transcript order `idle`, `commandSent`, `running`, `idle`,
with no "this session's process has exited" anywhere.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4a122f7b25
commit
1a132b4de3
4 files changed
+115
-36
No files matched your search
+20
-9
@@ -24,6 +24,7 @@
|
||||
//! POST /sessions/{id}/title {title}
|
||||
//! POST /sessions/{id}/model {model}
|
||||
//! POST /sessions/{id}/command {text} -- /compact, /clear, /rename x, or the dialect's own
|
||||
//! (starts the process first if it has exited)
|
||||
//! POST /sessions/{id}/compact
|
||||
//! POST /sessions/{id}/attachments multipart image upload -> {id}, referenced by /message
|
||||
//! GET /sessions/{id}/files/{name} images the session produced or was sent
|
||||
@@ -840,15 +841,22 @@ async fn command(
|
||||
Some((name, rest)) => (name, rest.trim()),
|
||||
None => (text, ""),
|
||||
};
|
||||
match (name, rest) {
|
||||
("/compact", _) => lookup(&manager, &id)?.run_command(SessionCommand::Compact),
|
||||
("/clear", _) => lookup(&manager, &id)?.run_command(SessionCommand::Clear),
|
||||
// Through the manager, not the session: a name is persisted and
|
||||
// listed as well as forwarded, and that is one operation.
|
||||
// Everything but a rename goes through the manager, which starts the
|
||||
// session's process first if it has exited. A rename is persisted and
|
||||
// listed whether or not a process hears about it, so it neither needs
|
||||
// one nor is worth starting one for.
|
||||
let command = match (name, rest) {
|
||||
("/compact", _) => SessionCommand::Compact,
|
||||
("/clear", _) => SessionCommand::Clear,
|
||||
("/rename", "") => return Err(bad_request(anyhow::anyhow!("a session needs a name"))),
|
||||
("/rename", title) => manager.rename_session(&id, title).map_err(bad_request)?,
|
||||
_ => lookup(&manager, &id)?.run_command(SessionCommand::Raw(text.to_string())),
|
||||
}
|
||||
("/rename", title) => {
|
||||
manager.rename_session(&id, title).map_err(bad_request)?;
|
||||
return Ok(StatusCode::NO_CONTENT);
|
||||
}
|
||||
_ => SessionCommand::Raw(text.to_string()),
|
||||
};
|
||||
lookup(&manager, &id)?;
|
||||
manager.run_command(&id, command).map_err(bad_request)?;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
@@ -856,7 +864,10 @@ async fn compact(
|
||||
State(manager): State<Arc<SessionManager>>,
|
||||
UrlPath(id): UrlPath<String>,
|
||||
) -> Result<StatusCode, ApiError> {
|
||||
lookup(&manager, &id)?.compact();
|
||||
lookup(&manager, &id)?;
|
||||
manager
|
||||
.run_command(&id, SessionCommand::Compact)
|
||||
.map_err(bad_request)?;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user