Skip to content

Commit 3d3269a

Browse files
committed
add agent_message_clear
impls agentclientprotocol/agent-client-protocol#465
1 parent d0bb665 commit 3d3269a

4 files changed

Lines changed: 91 additions & 6 deletions

File tree

examples/client.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ impl acp::Client for ExampleClient {
9090
};
9191
println!("| Agent: {text}");
9292
}
93-
_ => {} // Handle future variants gracefully
93+
acp::SessionUpdate::AgentMessageClear => {
94+
// Clear accumulated streamed content for the current agent message.
95+
// Subsequent agent_message_chunk will append from empty.
96+
println!("| Agent: (message cleared)");
97+
}
98+
_ => {} // Handle other variants gracefully
9499
}
95100
Ok(())
96101
}

src/agent-client-protocol/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [Unreleased]
4+
5+
### Added
6+
7+
- Support for `agent_message_clear` session update (RFD [agent_message_clear](https://github.com/agentclientprotocol/agent-client-protocol/blob/main/docs/rfds/agent_message_clear.md)): clients can clear accumulated streamed content for the current agent message; example client and tests updated.
8+
39
## [0.9.4](https://github.com/agentclientprotocol/rust-sdk/compare/v0.9.3...v0.9.4) - 2026-02-04
410

511
### Added

src/agent-client-protocol/src/rpc_tests.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,9 @@ async fn test_full_conversation_flow() {
627627
found_final_message = true;
628628
}
629629
}
630+
SessionUpdate::AgentMessageClear => {
631+
// Client would clear accumulated message; test just verifies we receive it.
632+
}
630633
SessionUpdate::ToolCall(_) => {
631634
found_tool_call = true;
632635
}
@@ -647,6 +650,71 @@ async fn test_full_conversation_flow() {
647650
.await;
648651
}
649652

653+
#[tokio::test]
654+
async fn test_agent_message_clear_sequence() {
655+
let local_set = tokio::task::LocalSet::new();
656+
local_set
657+
.run_until(async {
658+
let client = TestClient::new();
659+
let agent = TestAgent::new();
660+
let (agent_conn, client_conn) = create_connection_pair(&client, &agent);
661+
662+
let session_id = SessionId::new("clear-test-session");
663+
agent_conn
664+
.prompt(PromptRequest::new(
665+
session_id.clone(),
666+
vec!["Say hello then replace with goodbye".into()],
667+
))
668+
.await
669+
.expect("prompt failed");
670+
671+
// Agent sends draft, then clear, then final (RFD agent_message_clear usage pattern)
672+
client_conn
673+
.session_notification(SessionNotification::new(
674+
session_id.clone(),
675+
SessionUpdate::AgentMessageChunk(ContentChunk::new("Drafting...".into())),
676+
))
677+
.await
678+
.expect("session_notification failed");
679+
client_conn
680+
.session_notification(SessionNotification::new(
681+
session_id.clone(),
682+
SessionUpdate::AgentMessageClear,
683+
))
684+
.await
685+
.expect("session_notification failed");
686+
client_conn
687+
.session_notification(SessionNotification::new(
688+
session_id.clone(),
689+
SessionUpdate::AgentMessageChunk(ContentChunk::new("Here is the final result.".into())),
690+
))
691+
.await
692+
.expect("session_notification failed");
693+
694+
for _ in 0..10 {
695+
tokio::task::yield_now().await;
696+
}
697+
698+
let updates = client.session_notifications.lock().unwrap();
699+
let mut clear_seen = false;
700+
let mut final_chunk_seen = false;
701+
for n in updates.iter() {
702+
match &n.update {
703+
SessionUpdate::AgentMessageClear => clear_seen = true,
704+
SessionUpdate::AgentMessageChunk(ContentChunk { content: ContentBlock::Text(t), .. }) => {
705+
if t.text.contains("final result") {
706+
final_chunk_seen = true;
707+
}
708+
}
709+
_ => {}
710+
}
711+
}
712+
assert!(clear_seen, "Client should receive agent_message_clear");
713+
assert!(final_chunk_seen, "Client should receive final chunk after clear");
714+
})
715+
.await;
716+
}
717+
650718
#[tokio::test]
651719
async fn test_extension_methods_and_notifications() {
652720
let local_set = tokio::task::LocalSet::new();

src/sacp-test/src/test_client.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,17 @@ where
4242
JrHandlerChain::new()
4343
.name("test-client")
4444
.on_receive_notification(async |notif: SessionNotification, _cx| {
45-
// Collect text from AgentMessageChunk updates
46-
if let SessionUpdate::AgentMessageChunk(chunk) = &notif.update
47-
&& let ContentBlock::Text(text_content) = &chunk.content
48-
{
49-
collected_text.push_str(&text_content.text);
45+
// Collect text from AgentMessageChunk updates; clear on AgentMessageClear
46+
match &notif.update {
47+
SessionUpdate::AgentMessageChunk(chunk) => {
48+
if let ContentBlock::Text(text_content) = &chunk.content {
49+
collected_text.push_str(&text_content.text);
50+
}
51+
}
52+
SessionUpdate::AgentMessageClear => {
53+
collected_text.clear();
54+
}
55+
_ => {}
5056
}
5157
Ok(())
5258
})

0 commit comments

Comments
 (0)