fix(maestro): parse reported activity states strictly
This commit is contained in:
@@ -163,6 +163,13 @@ impl<'de> Deserialize<'de> for ActivityState {
|
||||
/// for a fixed TTL, then resumes inference.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ReportActivityRequest {
|
||||
/// Parsed strictly, unlike [`ActivityState`]'s own lenient `Deserialize`
|
||||
/// (#110). Leniency exists so a client reading a *newer* daemon's snapshot
|
||||
/// degrades an unrecognised state to `Idle` instead of dropping the whole
|
||||
/// session. A report travelling the other way has no such excuse: an agent
|
||||
/// posting a state this daemon does not know is a bug in the agent, and
|
||||
/// silently recording it as `Idle` would hide that behind a 204.
|
||||
#[serde(deserialize_with = "strict_activity_state")]
|
||||
pub state: ActivityState,
|
||||
/// Short human string shown next to the state (e.g. an error message).
|
||||
/// The daemon caps its length server-side.
|
||||
@@ -170,6 +177,26 @@ pub struct ReportActivityRequest {
|
||||
pub detail: Option<String>,
|
||||
}
|
||||
|
||||
/// Reject an unknown [`ActivityState`] spelling instead of degrading it to
|
||||
/// `Idle`. Used only by [`ReportActivityRequest`]; see the note there.
|
||||
fn strict_activity_state<'de, D>(deserializer: D) -> Result<ActivityState, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
use serde::de::Error as _;
|
||||
let s = String::deserialize(deserializer)?;
|
||||
match s.as_str() {
|
||||
"Active" => Ok(ActivityState::Active),
|
||||
"Idle" => Ok(ActivityState::Idle),
|
||||
"AwaitingInput" => Ok(ActivityState::AwaitingInput),
|
||||
"Error" => Ok(ActivityState::Error),
|
||||
other => Err(D::Error::unknown_variant(
|
||||
other,
|
||||
&["Active", "Idle", "AwaitingInput", "Error"],
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Optional worktree request attached to a `CreateSessionRequest`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct WorktreeSpec {
|
||||
|
||||
@@ -108,3 +108,9 @@ If a client receives an `ActivityState` variant it does not know, it must not
|
||||
fail rendering: treat it as `Idle` (neutral/dim, line-2 rules apply as usual)
|
||||
until the daemon sends a variant it does know. Rust clients deserialize
|
||||
activity leniently for the same reason.
|
||||
|
||||
Leniency runs one way only. It covers a client *reading* a newer daemon, where
|
||||
dropping the whole session would be worse than dimming one card. A report
|
||||
arriving at `POST /api/sessions/:id/activity` is parsed strictly and an unknown
|
||||
state is a 4xx: an agent posting a state the daemon does not know is a bug in
|
||||
the agent, and answering 204 would hide it.
|
||||
|
||||
Reference in New Issue
Block a user