Skip to content

Commit 6e55eb4

Browse files
committed
add agent_message_clear
impls agentclientprotocol/agent-client-protocol#465
1 parent 0133bc4 commit 6e55eb4

File tree

9 files changed

+83
-0
lines changed

9 files changed

+83
-0
lines changed

schema/schema.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,20 @@
531531
],
532532
"description": "The input specification for a command."
533533
},
534+
"AgentMessageClear": {
535+
"description": "Clear the accumulated streamed content for the current agent message. Subsequent agent_message_chunk updates start appending from empty.",
536+
"properties": {
537+
"_meta": {
538+
"additionalProperties": true,
539+
"description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)",
540+
"type": [
541+
"object",
542+
"null"
543+
]
544+
}
545+
},
546+
"type": "object"
547+
},
534548
"AvailableCommandsUpdate": {
535549
"description": "Available commands are ready or have changed",
536550
"properties": {
@@ -3767,6 +3781,24 @@
37673781
"sessionUpdate"
37683782
],
37693783
"type": "object"
3784+
},
3785+
{
3786+
"allOf": [
3787+
{
3788+
"$ref": "#/$defs/AgentMessageClear"
3789+
}
3790+
],
3791+
"description": "Clear the accumulated streamed content for the current agent message. Subsequent agent_message_chunk updates start appending from empty.",
3792+
"properties": {
3793+
"sessionUpdate": {
3794+
"const": "agent_message_clear",
3795+
"type": "string"
3796+
}
3797+
},
3798+
"required": [
3799+
"sessionUpdate"
3800+
],
3801+
"type": "object"
37703802
}
37713803
]
37723804
},

scripts/gen_schema.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"SessionUpdate9": "ConfigOptionUpdate",
6464
"SessionUpdate10": "SessionInfoUpdate",
6565
"SessionUpdate11": "UsageUpdate",
66+
"SessionUpdate12": "AgentMessageClear",
6667
"ToolCallContent1": "ContentToolCallContent",
6768
"ToolCallContent2": "FileEditToolCallContent",
6869
"ToolCallContent3": "TerminalToolCallContent",

src/acp/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
)
1010
from .helpers import (
1111
audio_block,
12+
clear_agent_message,
1213
embedded_blob_resource,
1314
embedded_text_resource,
1415
image_block,

src/acp/contrib/session_state.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from ..schema import (
1010
AgentMessageChunk,
11+
AgentMessageClear,
1112
AgentPlanUpdate,
1213
AgentThoughtChunk,
1314
AvailableCommand,
@@ -238,6 +239,10 @@ def _apply_update(self, update: Any) -> None:
238239
self._agent_messages.append(update.model_copy(deep=True))
239240
return
240241

242+
if isinstance(update, AgentMessageClear):
243+
self._agent_messages.clear()
244+
return
245+
241246
if isinstance(update, AgentThoughtChunk):
242247
self._agent_thoughts.append(update.model_copy(deep=True))
243248

src/acp/helpers.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from .schema import (
77
AgentMessageChunk,
8+
AgentMessageClear,
89
AgentPlanUpdate,
910
AgentThoughtChunk,
1011
AudioContentBlock,
@@ -39,6 +40,7 @@
3940

4041
SessionUpdate = (
4142
AgentMessageChunk
43+
| AgentMessageClear
4244
| AgentPlanUpdate
4345
| AgentThoughtChunk
4446
| AvailableCommandsUpdate
@@ -53,6 +55,7 @@
5355

5456
__all__ = [
5557
"audio_block",
58+
"clear_agent_message",
5659
"embedded_blob_resource",
5760
"embedded_text_resource",
5861
"image_block",
@@ -167,6 +170,14 @@ def update_agent_message_text(text: str) -> AgentMessageChunk:
167170
return update_agent_message(text_block(text))
168171

169172

173+
def clear_agent_message() -> AgentMessageClear:
174+
"""Clear the accumulated streamed content for the current agent message.
175+
176+
Subsequent agent_message_chunk updates will start appending from empty.
177+
"""
178+
return AgentMessageClear(session_update="agent_message_clear")
179+
180+
170181
def update_agent_thought(content: ContentBlock) -> AgentThoughtChunk:
171182
return AgentThoughtChunk(session_update="agent_thought_chunk", content=content)
172183

src/acp/schema.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2238,6 +2238,19 @@ class AgentThoughtChunk(ContentChunk):
22382238
session_update: Annotated[Literal["agent_thought_chunk"], Field(alias="sessionUpdate")]
22392239

22402240

2241+
class AgentMessageClear(BaseModel):
2242+
# Clear the accumulated streamed content for the current agent message.
2243+
# Subsequent agent_message_chunk updates start appending from empty.
2244+
field_meta: Annotated[
2245+
Optional[Dict[str, Any]],
2246+
Field(
2247+
alias="_meta",
2248+
description="The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)",
2249+
),
2250+
] = None
2251+
session_update: Annotated[Literal["agent_message_clear"], Field(alias="sessionUpdate")]
2252+
2253+
22412254
class ClientRequest(BaseModel):
22422255
# JSON RPC Request Id
22432256
#
@@ -2831,6 +2844,7 @@ class SessionNotification(BaseModel):
28312844
ConfigOptionUpdate,
28322845
SessionInfoUpdate,
28332846
UsageUpdate,
2847+
AgentMessageClear,
28342848
],
28352849
Field(description="The actual update content.", discriminator="session_update"),
28362850
]

tests/contrib/test_contrib_session_state.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44

5+
from acp import clear_agent_message
56
from acp.contrib.session_state import SessionAccumulator
67
from acp.schema import (
78
AgentMessageChunk,
@@ -107,6 +108,19 @@ def test_session_accumulator_tracks_messages_and_commands():
107108
assert agent_content.text == "Hi!"
108109

109110

111+
def test_session_accumulator_agent_message_clear_clears_accumulated_chunks():
112+
acc = SessionAccumulator()
113+
acc.apply(notification("s", AgentMessageChunk(session_update="agent_message_chunk", content=TextContentBlock(type="text", text="Thinking..."))))
114+
acc.apply(notification("s", AgentMessageChunk(session_update="agent_message_chunk", content=TextContentBlock(type="text", text=" draft"))))
115+
assert len(acc.snapshot().agent_messages) == 2
116+
acc.apply(notification("s", clear_agent_message()))
117+
assert len(acc.snapshot().agent_messages) == 0
118+
acc.apply(notification("s", AgentMessageChunk(session_update="agent_message_chunk", content=TextContentBlock(type="text", text="Final result."))))
119+
snapshot = acc.snapshot()
120+
assert len(snapshot.agent_messages) == 1
121+
assert snapshot.agent_messages[0].content.text == "Final result."
122+
123+
110124
def test_session_accumulator_auto_resets_on_new_session():
111125
acc = SessionAccumulator()
112126
acc.apply(
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"sessionUpdate":"agent_message_clear"}

tests/test_golden.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from acp import (
1111
audio_block,
12+
clear_agent_message,
1213
embedded_blob_resource,
1314
embedded_text_resource,
1415
image_block,
@@ -30,6 +31,7 @@
3031
)
3132
from acp.schema import (
3233
AgentMessageChunk,
34+
AgentMessageClear,
3335
AgentPlanUpdate,
3436
AgentThoughtChunk,
3537
AllowedOutcome,
@@ -86,6 +88,7 @@
8688
"request_permission_request": RequestPermissionRequest,
8789
"request_permission_response_selected": RequestPermissionResponse,
8890
"session_update_agent_message_chunk": AgentMessageChunk,
91+
"session_update_agent_message_clear": AgentMessageClear,
8992
"session_update_agent_thought_chunk": AgentThoughtChunk,
9093
"session_update_config_option_update": ConfigOptionUpdate,
9194
"session_update_plan": AgentPlanUpdate,
@@ -144,6 +147,7 @@
144147
"tool_content_terminal": lambda: tool_terminal_ref("term_001"),
145148
"session_update_user_message_chunk": lambda: update_user_message_text("What's the capital of France?"),
146149
"session_update_agent_message_chunk": lambda: update_agent_message_text("The capital of France is Paris."),
150+
"session_update_agent_message_clear": lambda: clear_agent_message(),
147151
"session_update_agent_thought_chunk": lambda: update_agent_thought_text("Thinking about best approach..."),
148152
"session_update_plan": lambda: update_plan([
149153
plan_entry(

0 commit comments

Comments
 (0)