Skip to content

Commit 540e58c

Browse files
author
Mark Pollack
committed
Add messageId overloads to prompt context send methods
Add sendMessage(text, messageId) and sendThought(text, messageId) as default methods on PromptContext and SyncPromptContext. They delegate to the existing sendUpdate with the three-argument chunk constructor, so no implementation changes are needed and external implementors are unaffected. Lets agents group or identify streamed chunks via the per-chunk messageId field without dropping to the low-level sendUpdate API.
1 parent 55bfcdd commit 540e58c

4 files changed

Lines changed: 93 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ Protocol currency: catching up to ACP spec v0.13.6 (June 2026).
1717
stored session; gated on the `sessionCapabilities.delete` capability.
1818
- `additionalDirectories` on `session/new`, `session/load`, `session/resume`, `session/fork` requests
1919
and on `SessionInfo` — extra workspace roots beyond `cwd`.
20-
- Per-chunk `messageId` on `AgentMessageChunk`, `AgentThoughtChunk`, `UserMessageChunk`.
20+
- Per-chunk `messageId` on `AgentMessageChunk`, `AgentThoughtChunk`, `UserMessageChunk`, plus
21+
`sendMessage(text, messageId)` / `sendThought(text, messageId)` convenience overloads on
22+
`PromptContext` and `SyncPromptContext`.
2123
- `sessionCapabilities.delete` and `sessionCapabilities.additionalDirectories`, surfaced via
2224
`NegotiatedCapabilities` (`supports*`/`require*`).
2325

acp-core/src/main/java/com/agentclientprotocol/sdk/agent/PromptContext.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,19 @@ public interface PromptContext {
188188
*/
189189
Mono<Void> sendMessage(String text);
190190

191+
/**
192+
* Sends a message to the client as an agent message chunk, tagged with a message ID.
193+
* Chunks sharing the same {@code messageId} belong to the same logical message; a change
194+
* in {@code messageId} signals a new message.
195+
* @param text The message text to send
196+
* @param messageId The message identifier, or {@code null} for none
197+
* @return A Mono that completes when the message is sent
198+
*/
199+
default Mono<Void> sendMessage(String text, String messageId) {
200+
return sendUpdate(getSessionId(),
201+
new AcpSchema.AgentMessageChunk("agent_message_chunk", new AcpSchema.TextContent(text), messageId));
202+
}
203+
191204
/**
192205
* Sends a thought to the client as an agent thought chunk.
193206
* Thoughts are typically displayed differently than messages,
@@ -197,6 +210,18 @@ public interface PromptContext {
197210
*/
198211
Mono<Void> sendThought(String text);
199212

213+
/**
214+
* Sends a thought to the client as an agent thought chunk, tagged with a message ID.
215+
* Chunks sharing the same {@code messageId} belong to the same logical message.
216+
* @param text The thought text to send
217+
* @param messageId The message identifier, or {@code null} for none
218+
* @return A Mono that completes when the thought is sent
219+
*/
220+
default Mono<Void> sendThought(String text, String messageId) {
221+
return sendUpdate(getSessionId(),
222+
new AcpSchema.AgentThoughtChunk("agent_thought_chunk", new AcpSchema.TextContent(text), messageId));
223+
}
224+
200225
/**
201226
* Reads a text file from the client's file system.
202227
* @param path The path to the file

acp-core/src/main/java/com/agentclientprotocol/sdk/agent/SyncPromptContext.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,18 @@ public interface SyncPromptContext {
184184
*/
185185
void sendMessage(String text);
186186

187+
/**
188+
* Sends a message to the client as an agent message chunk, tagged with a message ID.
189+
* Chunks sharing the same {@code messageId} belong to the same logical message; a change
190+
* in {@code messageId} signals a new message.
191+
* @param text The message text to send
192+
* @param messageId The message identifier, or {@code null} for none
193+
*/
194+
default void sendMessage(String text, String messageId) {
195+
sendUpdate(getSessionId(),
196+
new AcpSchema.AgentMessageChunk("agent_message_chunk", new AcpSchema.TextContent(text), messageId));
197+
}
198+
187199
/**
188200
* Sends a thought to the client as an agent thought chunk.
189201
* Thoughts are typically displayed differently than messages,
@@ -192,6 +204,17 @@ public interface SyncPromptContext {
192204
*/
193205
void sendThought(String text);
194206

207+
/**
208+
* Sends a thought to the client as an agent thought chunk, tagged with a message ID.
209+
* Chunks sharing the same {@code messageId} belong to the same logical message.
210+
* @param text The thought text to send
211+
* @param messageId The message identifier, or {@code null} for none
212+
*/
213+
default void sendThought(String text, String messageId) {
214+
sendUpdate(getSessionId(),
215+
new AcpSchema.AgentThoughtChunk("agent_thought_chunk", new AcpSchema.TextContent(text), messageId));
216+
}
217+
195218
/**
196219
* Reads a text file from the client's file system.
197220
* @param path The path to the file

acp-core/src/test/java/com/agentclientprotocol/sdk/agent/ConvenienceApiTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,48 @@ void sendMessageSendsAgentMessageChunk() throws Exception {
148148
agent.closeGracefully();
149149
}
150150

151+
@Test
152+
void sendMessageWithMessageIdSetsMessageId() throws Exception {
153+
List<SessionNotification> receivedUpdates = new CopyOnWriteArrayList<>();
154+
CountDownLatch latch = new CountDownLatch(1);
155+
156+
AcpSyncAgent agent = AcpAgent.sync(transportPair.agentTransport())
157+
.requestTimeout(TIMEOUT)
158+
.initializeHandler(req -> InitializeResponse.ok())
159+
.newSessionHandler(req -> new NewSessionResponse("msgid-session", null, null))
160+
.promptHandler((request, context) -> {
161+
context.sendMessage("Hello with id!", "msg-7");
162+
return PromptResponse.endTurn();
163+
})
164+
.build();
165+
166+
AcpAsyncClient client = AcpClient.async(transportPair.clientTransport())
167+
.requestTimeout(TIMEOUT)
168+
.sessionUpdateConsumer(notification -> {
169+
receivedUpdates.add(notification);
170+
latch.countDown();
171+
return Mono.empty();
172+
})
173+
.build();
174+
175+
agent.start();
176+
Thread.sleep(100);
177+
178+
client.initialize(new InitializeRequest(1, new ClientCapabilities())).block(TIMEOUT);
179+
client.newSession(new NewSessionRequest("/workspace", List.of())).block(TIMEOUT);
180+
client.prompt(new PromptRequest("msgid-session", List.of(new TextContent("test")))).block(TIMEOUT);
181+
182+
assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();
183+
assertThat(receivedUpdates).hasSize(1);
184+
assertThat(receivedUpdates.get(0).update()).isInstanceOf(AgentMessageChunk.class);
185+
AgentMessageChunk chunk = (AgentMessageChunk) receivedUpdates.get(0).update();
186+
assertThat(((TextContent) chunk.content()).text()).isEqualTo("Hello with id!");
187+
assertThat(chunk.messageId()).isEqualTo("msg-7");
188+
189+
client.closeGracefully().block(TIMEOUT);
190+
agent.closeGracefully();
191+
}
192+
151193
@Test
152194
void sendThoughtSendsAgentThoughtChunk() throws Exception {
153195
List<SessionNotification> receivedUpdates = new CopyOnWriteArrayList<>();

0 commit comments

Comments
 (0)