Skip to content

Commit 94edd68

Browse files
committed
fix(agents): cover stop-labeled pre-tool commentary
1 parent 448f0d1 commit 94edd68

2 files changed

Lines changed: 44 additions & 8 deletions

File tree

src/agents/embedded-agent-runner/replay-history.test.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -318,18 +318,19 @@ describe("normalizeAssistantReplayContent", () => {
318318

319319
it("marks commentary text before tool calls as undelivered in provider replay", () => {
320320
const toolCall = { type: "toolCall", id: "call_1", name: "read", arguments: {} };
321+
const signature = JSON.stringify({
322+
v: 1,
323+
id: "commentary-0",
324+
phase: "commentary",
325+
});
321326
const messages = [
322327
userMessage("hi"),
323328
bedrockAssistant(
324329
[
325330
{
326331
type: "text",
327332
text: "Please confirm the payment details before I continue.",
328-
textSignature: JSON.stringify({
329-
v: 1,
330-
id: "commentary-0",
331-
phase: "commentary",
332-
}),
333+
textSignature: signature,
333334
},
334335
toolCall,
335336
],
@@ -361,6 +362,43 @@ describe("normalizeAssistantReplayContent", () => {
361362
expect(out[2]).toBe(messages[2]);
362363
});
363364

365+
it("marks commentary text as undelivered when tool-call turns replay with stop", () => {
366+
const toolCall = { type: "toolCall", id: "call_1", name: "read", arguments: {} };
367+
const messages = [
368+
userMessage("hi"),
369+
bedrockAssistant(
370+
[
371+
{
372+
type: "text",
373+
text: "I will check that now.",
374+
textSignature: JSON.stringify({
375+
v: 1,
376+
id: "commentary-0",
377+
phase: "commentary",
378+
}),
379+
},
380+
toolCall,
381+
],
382+
"stop",
383+
),
384+
{
385+
role: "toolResult",
386+
toolCallId: "call_1",
387+
toolName: "read",
388+
content: [{ type: "text", text: "ok" }],
389+
timestamp: 1,
390+
} as unknown as AgentMessage,
391+
];
392+
393+
const out = normalizeAssistantReplayContent(messages);
394+
395+
const normalized = out[1] as AgentMessage & { content: unknown[] };
396+
const replayText = (normalized.content[0] as { text?: string }).text ?? "";
397+
expect(replayText).toContain("was not delivered to the user/channel");
398+
expect(replayText).toContain("I will check that now.");
399+
expect(normalized.content[1]).toBe(toolCall);
400+
});
401+
364402
it("filters openclaw delivery-mirror and gateway-injected assistant messages from replay", () => {
365403
// Gateway mirror entries are transcript artifacts, not model-authored
366404
// assistant turns, so they must not be sent back to providers.

src/agents/embedded-agent-runner/replay-history.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,7 @@ function formatUndeliveredCommentaryReplayContext(text: string): string {
277277
function normalizeAssistantReplayBlockContent(message: AgentMessage, replayContent: unknown[]) {
278278
let touched = false;
279279
const sanitizedContent: unknown[] = [];
280-
const markUndeliveredCommentary =
281-
(message as { stopReason?: unknown }).stopReason === "toolUse" &&
282-
hasReplayToolCallBlock(replayContent);
280+
const markUndeliveredCommentary = hasReplayToolCallBlock(replayContent);
283281
for (const block of replayContent) {
284282
if (!block || typeof block !== "object") {
285283
sanitizedContent.push(block);

0 commit comments

Comments
 (0)