diff options
Diffstat (limited to 'src/protocol/endpoint.rs')
| -rw-r--r-- | src/protocol/endpoint.rs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/protocol/endpoint.rs b/src/protocol/endpoint.rs index a70ef568..640e594e 100644 --- a/src/protocol/endpoint.rs +++ b/src/protocol/endpoint.rs @@ -27,6 +27,8 @@ pub const PRESENTATION_EFFECTS_READY_KIND: &str = "endpoint.presentation.ready.v pub const HEALTH_CHECK_CAPABILITY: &str = "health_check"; pub const HEALTH_PING_KIND: &str = "endpoint.health.ping.v1"; pub const HEALTH_PONG_KIND: &str = "endpoint.health.pong.v1"; +pub const AGENT_VIEW_PROJECTION_CAPABILITY: &str = "agent_view_projection"; +pub const AGENT_VIEW_PROJECTION_KIND: &str = "endpoint.agent-view.v1"; fn default_true() -> bool { true @@ -60,6 +62,16 @@ pub struct EndpointHandshakeError { pub message: String, } +/// Optional companion to a V1 snapshot. The view payload is intentionally opaque to this +/// stable envelope so clients can ignore view language additions they do not understand. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct EndpointAgentViewProjection { + pub boot_id: String, + pub revision: u64, + #[serde(default)] + pub view: Option<serde_json::Value>, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct EndpointServerWelcome { pub generation: u32, @@ -83,6 +95,22 @@ pub fn snapshot_message(snapshot: &ClientShellSnapshot) -> serde_json::Result<Se }) } +pub fn agent_view_projection_message( + boot_id: &str, + revision: u64, + view: Option<&crate::api::schema::AgentViewSetParams>, +) -> serde_json::Result<ServerMessage> { + let projection = EndpointAgentViewProjection { + boot_id: boot_id.to_owned(), + revision, + view: view.map(serde_json::to_value).transpose()?, + }; + Ok(ServerMessage::EndpointControl { + kind: AGENT_VIEW_PROJECTION_KIND.into(), + data: serde_json::to_string(&projection)?, + }) +} + impl EndpointClientHello { pub fn supports_required_codecs(&self) -> bool { self.snapshot_codecs @@ -114,6 +142,7 @@ impl EndpointServerWelcome { SURFACE_INTEREST_CAPABILITY.into(), PRESENTATION_EFFECTS_FENCE_CAPABILITY.into(), HEALTH_CHECK_CAPABILITY.into(), + AGENT_VIEW_PROJECTION_CAPABILITY.into(), ], error: None, } @@ -244,6 +273,33 @@ mod tests { } #[test] + fn agent_view_projection_is_an_optional_revision_bound_control() { + let view = crate::api::schema::AgentViewSetParams { + source: "example.views".into(), + label: Some("focus".into()), + filter: None, + sort: Vec::new(), + }; + let ServerMessage::EndpointControl { kind, data } = + agent_view_projection_message("boot", 7, Some(&view)).unwrap() + else { + panic!("projection should use endpoint control"); + }; + assert_eq!(kind, AGENT_VIEW_PROJECTION_KIND); + let projection: EndpointAgentViewProjection = serde_json::from_str(&data).unwrap(); + assert_eq!(projection.boot_id, "boot"); + assert_eq!(projection.revision, 7); + assert_eq!( + projection + .view + .map(serde_json::from_value) + .transpose() + .unwrap(), + Some(view) + ); + } + + #[test] fn snapshot_json_tolerates_future_fields_and_command_actions() { let mut snapshot = match snapshot_message(&snapshot()).unwrap() { ServerMessage::EndpointControl { data, .. } => { @@ -284,6 +340,7 @@ mod tests { SURFACE_INTEREST_CAPABILITY.to_string(), PRESENTATION_EFFECTS_FENCE_CAPABILITY.to_string(), HEALTH_CHECK_CAPABILITY.to_string(), + AGENT_VIEW_PROJECTION_CAPABILITY.to_string(), ] ); } |
