Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion crates/freshell-protocol/src/client_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub enum ClientMessage {
TerminalCodexCandidatePersisted(TerminalCodexCandidatePersisted),
#[serde(rename = "terminal.attach")]
TerminalAttach(TerminalAttach),
#[serde(rename = "terminal.interest")]
TerminalInterest(TerminalInterest),
#[serde(rename = "terminal.autoResumeCancel")]
TerminalAutoResumeCancel(TerminalAutoResumeCancel),
#[serde(rename = "terminal.detach")]
Expand Down Expand Up @@ -95,7 +97,7 @@ pub enum ClientMessage {

/// The exact `type` discriminants of every client→server message, in the frozen
/// inventory's order. This is the T0 conformance checklist.
pub const CLIENT_MESSAGE_TYPES: [&str; 36] = [
pub const CLIENT_MESSAGE_TYPES: [&str; 37] = [
"amplifier.activity.list",
"claude.activity.list",
"client.diagnostic",
Expand Down Expand Up @@ -128,6 +130,7 @@ pub const CLIENT_MESSAGE_TYPES: [&str; 36] = [
"terminal.create",
"terminal.detach",
"terminal.input",
"terminal.interest",
"terminal.kill",
"terminal.resize",
"ui.layout.sync",
Expand All @@ -148,6 +151,8 @@ pub struct HelloCapabilities {
#[serde(skip_serializing_if = "Option::is_none")]
pub terminal_output_batch_v1: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub terminal_interest_v1: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ui_screenshot_v1: Option<bool>,
/// Reconciliation handshake opt-in (design §4.1). A client that sets this
/// MAY send `pane.reconcile.request` once the `ready` it receives
Expand Down Expand Up @@ -189,6 +194,16 @@ pub struct Hello {
pub sidebar_open_sessions: Option<Vec<SessionLocator>>,
}

/// Full presentation-interest snapshot for this connection. Validation of
/// cardinality, safe revision range and focused-in-visible runs at dispatch.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TerminalInterest {
pub revision: u64,
pub focused_terminal_id: Option<String>,
pub visible_terminal_ids: Vec<String>,
}

// --- client.diagnostic ------------------------------------------------------

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
Expand Down
2 changes: 2 additions & 0 deletions crates/freshell-protocol/src/server_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,8 @@ pub struct ReadyCapabilities {
/// omitted from the wire entirely otherwise (frozen-client inertness).
#[serde(skip_serializing_if = "Option::is_none")]
pub pane_reconcile_fresh_agent_v1: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub terminal_interest_v1: Option<bool>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
Expand Down
12 changes: 6 additions & 6 deletions crates/freshell-protocol/tests/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ fn client_types_match_inventory_exactly() {
let inv = inventory();
assert_eq!(
inv["clientToServer"]["count"].as_u64(),
Some(36),
"inventory declares 36 client→server types"
Some(37),
"inventory declares 37 client→server types"
);
let expected = json_type_set(&inv["clientToServer"]["types"]);
let actual: BTreeSet<String> = CLIENT_MESSAGE_TYPES.iter().map(|s| s.to_string()).collect();
assert_eq!(actual.len(), 36, "crate declares 36 client types (no dups)");
assert_eq!(actual.len(), 37, "crate declares 37 client types (no dups)");
assert_eq!(
actual, expected,
"CLIENT_MESSAGE_TYPES must equal the frozen inventory (no missing/extra)"
Expand All @@ -61,14 +61,14 @@ fn server_types_match_inventory_exactly() {
}

#[test]
fn combined_surface_is_96() {
fn combined_surface_is_97() {
let all = all_message_types();
assert_eq!(all.len(), 96, "36 client + 60 server = 96 discriminants");
assert_eq!(all.len(), 97, "37 client + 60 server = 97 discriminants");
// sorted + unique
let unique: BTreeSet<&str> = all.iter().copied().collect();
assert_eq!(
unique.len(),
96,
97,
"no discriminant collides across directions"
);
}
Expand Down
1 change: 1 addition & 0 deletions crates/freshell-protocol/tests/pane_reconcile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ fn ready_capabilities_advertise_pane_reconcile_v1_when_negotiated() {
capabilities: Some(ReadyCapabilities {
pane_reconcile_v1: Some(true),
pane_reconcile_fresh_agent_v1: None,
terminal_interest_v1: None,
}),
};
let wire = serde_json::to_value(ServerMessage::Ready(ready)).expect("serializes");
Expand Down
Loading
Loading