From b2d65ed584e5a7ed351096d250f2468b52df9fc3 Mon Sep 17 00:00:00 2001 From: harryalbert Date: Wed, 20 May 2026 15:12:39 -0400 Subject: [PATCH 1/3] Add AmbientSetupPhaseEnded variant to OrderedTerminalEventType Adds an explicit shared-session-protocol marker that the sandboxed Oz AgentDriver emits when cloud-mode setup is complete but no initial LLM turn will follow (e.g. empty-prompt local-to-cloud handoff with `--skip-initial-turn`). Viewers consume the event to tear down the Cloud Mode Setup V2 "Running setup commands..." chip and clear `BlockList::is_executing_oz_environment_startup_commands` without waiting for the first `AppendedExchange`. The variant is unit-typed (no associated data) for v1. A future struct upgrade with `task_id: Option` is fine to plan for as a struct variant later but is deliberately out of scope here. Mirrors the placement and idiom of the adjacent `AgentConversationReplayStarted` / `AgentConversationReplayEnded` variants. The session-sharing-server treats `OrderedTerminalEventType` opaquely (only `CommandExecutionFinished` is special-cased for block-id tracking), so no server code changes are required to route or persist the new variant. The server will pick it up via a protocol dep rev bump after this change merges. Includes a serde round-trip test asserting the unit-variant wire form. Stage 2c of empty-prompt local-to-cloud handoff. Co-Authored-By: Oz --- src/common/ordered_terminal_events.rs | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/common/ordered_terminal_events.rs b/src/common/ordered_terminal_events.rs index 7461391..febb2c3 100644 --- a/src/common/ordered_terminal_events.rs +++ b/src/common/ordered_terminal_events.rs @@ -60,6 +60,12 @@ pub enum OrderedTerminalEventType { AgentConversationReplayStarted, /// Marks the end of historical agent conversation replay. AgentConversationReplayEnded, + /// Emitted by the sandboxed Oz AgentDriver when the cloud-mode setup phase is complete but no + /// initial LLM turn will follow (e.g. empty-prompt local-to-cloud handoff with + /// `--skip-initial-turn`). The viewer uses this to tear down the Cloud Mode Setup V2 + /// "Running setup commands…" chip and clear `BlockList::is_executing_oz_environment_startup_commands` + /// without needing to wait for the first `AppendedExchange`. + AmbientSetupPhaseEnded, } /// Represents the size of a PTY. Mimics the winsize struct that @@ -82,6 +88,7 @@ impl std::fmt::Debug for OrderedTerminalEventType { Self::AgentResponseEvent { .. } => f.write_str("AgentResponseEvent"), Self::AgentConversationReplayStarted => f.write_str("AgentConversationReplayStarted"), Self::AgentConversationReplayEnded => f.write_str("AgentConversationReplayEnded"), + Self::AmbientSetupPhaseEnded => f.write_str("AmbientSetupPhaseEnded"), } } } @@ -97,6 +104,7 @@ impl OrderedTerminalEventType { | OrderedTerminalEventType::CommandExecutionFinished { .. } | OrderedTerminalEventType::AgentConversationReplayStarted | OrderedTerminalEventType::AgentConversationReplayEnded + | OrderedTerminalEventType::AmbientSetupPhaseEnded | OrderedTerminalEventType::Resize { .. } => Byte::from_u64(0), } } @@ -114,3 +122,31 @@ impl OrderedTerminalEvent { self.event_type.num_bytes() } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ambient_setup_phase_ended_serializes_as_unit_variant() { + let event_type = OrderedTerminalEventType::AmbientSetupPhaseEnded; + let json = serde_json::to_string(&event_type).expect("serialize"); + assert_eq!(json, "\"AmbientSetupPhaseEnded\""); + } + + #[test] + fn ambient_setup_phase_ended_round_trips() { + let event = OrderedTerminalEvent { + event_no: 42, + event_type: OrderedTerminalEventType::AmbientSetupPhaseEnded, + }; + let json = serde_json::to_string(&event).expect("serialize"); + let parsed: OrderedTerminalEvent = serde_json::from_str(&json).expect("deserialize"); + assert_eq!(parsed.event_no, 42); + assert!(matches!( + parsed.event_type, + OrderedTerminalEventType::AmbientSetupPhaseEnded + )); + assert_eq!(parsed.num_bytes(), Byte::from_u64(0)); + } +} From 0db8bbdda17fda2b7a34ec103b74e84705cd5638 Mon Sep 17 00:00:00 2001 From: harryalbert Date: Fri, 22 May 2026 13:15:52 -0400 Subject: [PATCH 2/3] REMOTE-1499: add doc comment to AmbientSetupPhaseEnded explaining the missing Started half Adjacent variants come in Started/Ended pairs; AmbientSetupPhaseEnded has no matching Started because the setup-phase start is implicit in existing SetupCommandState transitions on the viewer once scrollback arrives. Co-Authored-By: Oz --- src/common/ordered_terminal_events.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/ordered_terminal_events.rs b/src/common/ordered_terminal_events.rs index febb2c3..6f27c88 100644 --- a/src/common/ordered_terminal_events.rs +++ b/src/common/ordered_terminal_events.rs @@ -65,6 +65,11 @@ pub enum OrderedTerminalEventType { /// `--skip-initial-turn`). The viewer uses this to tear down the Cloud Mode Setup V2 /// "Running setup commands…" chip and clear `BlockList::is_executing_oz_environment_startup_commands` /// without needing to wait for the first `AppendedExchange`. + /// + /// There is no matching `AmbientSetupPhaseStarted` variant: setup-phase start is already + /// implicit in the existing `SetupCommandState` transitions on the viewer (the default + /// `running_group_id` is `Some(initial)` once scrollback arrives), so an explicit start + /// marker would be redundant. AmbientSetupPhaseEnded, } From 719436dbe1a4a8332376a272536eab6dab0d23e0 Mon Sep 17 00:00:00 2001 From: harryalbert Date: Thu, 28 May 2026 10:02:09 -0400 Subject: [PATCH 3/3] Rename AmbientSetupPhaseEnded -> CloudModeSetupPhaseEnded Co-Authored-By: Oz --- src/common/ordered_terminal_events.rs | 44 +++------------------------ 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/src/common/ordered_terminal_events.rs b/src/common/ordered_terminal_events.rs index 6f27c88..de2419e 100644 --- a/src/common/ordered_terminal_events.rs +++ b/src/common/ordered_terminal_events.rs @@ -61,16 +61,8 @@ pub enum OrderedTerminalEventType { /// Marks the end of historical agent conversation replay. AgentConversationReplayEnded, /// Emitted by the sandboxed Oz AgentDriver when the cloud-mode setup phase is complete but no - /// initial LLM turn will follow (e.g. empty-prompt local-to-cloud handoff with - /// `--skip-initial-turn`). The viewer uses this to tear down the Cloud Mode Setup V2 - /// "Running setup commands…" chip and clear `BlockList::is_executing_oz_environment_startup_commands` - /// without needing to wait for the first `AppendedExchange`. - /// - /// There is no matching `AmbientSetupPhaseStarted` variant: setup-phase start is already - /// implicit in the existing `SetupCommandState` transitions on the viewer (the default - /// `running_group_id` is `Some(initial)` once scrollback arrives), so an explicit start - /// marker would be redundant. - AmbientSetupPhaseEnded, + /// initial LLM turn will follow (e.g. empty-prompt local-to-cloud handoff with `--skip-initial-turn`). + CloudModeSetupPhaseEnded, } /// Represents the size of a PTY. Mimics the winsize struct that @@ -93,7 +85,7 @@ impl std::fmt::Debug for OrderedTerminalEventType { Self::AgentResponseEvent { .. } => f.write_str("AgentResponseEvent"), Self::AgentConversationReplayStarted => f.write_str("AgentConversationReplayStarted"), Self::AgentConversationReplayEnded => f.write_str("AgentConversationReplayEnded"), - Self::AmbientSetupPhaseEnded => f.write_str("AmbientSetupPhaseEnded"), + Self::CloudModeSetupPhaseEnded => f.write_str("CloudModeSetupPhaseEnded"), } } } @@ -109,7 +101,7 @@ impl OrderedTerminalEventType { | OrderedTerminalEventType::CommandExecutionFinished { .. } | OrderedTerminalEventType::AgentConversationReplayStarted | OrderedTerminalEventType::AgentConversationReplayEnded - | OrderedTerminalEventType::AmbientSetupPhaseEnded + | OrderedTerminalEventType::CloudModeSetupPhaseEnded | OrderedTerminalEventType::Resize { .. } => Byte::from_u64(0), } } @@ -127,31 +119,3 @@ impl OrderedTerminalEvent { self.event_type.num_bytes() } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn ambient_setup_phase_ended_serializes_as_unit_variant() { - let event_type = OrderedTerminalEventType::AmbientSetupPhaseEnded; - let json = serde_json::to_string(&event_type).expect("serialize"); - assert_eq!(json, "\"AmbientSetupPhaseEnded\""); - } - - #[test] - fn ambient_setup_phase_ended_round_trips() { - let event = OrderedTerminalEvent { - event_no: 42, - event_type: OrderedTerminalEventType::AmbientSetupPhaseEnded, - }; - let json = serde_json::to_string(&event).expect("serialize"); - let parsed: OrderedTerminalEvent = serde_json::from_str(&json).expect("deserialize"); - assert_eq!(parsed.event_no, 42); - assert!(matches!( - parsed.event_type, - OrderedTerminalEventType::AmbientSetupPhaseEnded - )); - assert_eq!(parsed.num_bytes(), Byte::from_u64(0)); - } -}