Skip to content

Commit b1df548

Browse files
author
Sleek
committed
Reuse MCP message activity signal
Refresh one expiring row-protection signal after each approved app message instead of accumulating a signal per confirmation. Signed-off-by: Sleek <93c2629a5f1f93118df6264f931480b8f7b585d5f425aa459e48efd6e883ee14@buzz.block.builderlab.xyz>
1 parent 7b2dad6 commit b1df548

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

src/features/chat/ui/McpAppView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ export function McpAppView({
504504
pending.resolve(accepted === false ? { isError: true } : {});
505505
if (accepted !== false) {
506506
setMcpActivity("recent-message", true, {
507-
sourceId: `mcp-message:${pending.nonce}`,
507+
sourceId: "mcp-message",
508508
});
509509
}
510510
} catch {

src/features/chat/ui/__tests__/McpAppView.test.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,50 @@ describe("McpAppView nested tool calls", () => {
221221
await expect(resultPromise).resolves.toEqual({});
222222
});
223223

224+
it("refreshes one recent-message protection signal across approvals", async () => {
225+
const registry = createTranscriptRowStateRegistry();
226+
const onSendMessage = vi.fn(() => true);
227+
render(
228+
<TranscriptRowStateProvider
229+
registry={registry}
230+
sessionId="virtual-session"
231+
rowId="mcp-row"
232+
>
233+
<McpAppView
234+
payload={createPayload()}
235+
toolResponse={createToolResponse()}
236+
onSendMessage={onSendMessage}
237+
/>
238+
</TranscriptRowStateProvider>,
239+
);
240+
await waitFor(() => {
241+
expect(screen.getByTestId("mock-app-renderer")).toBeInTheDocument();
242+
});
243+
244+
for (const text of ["first", "second"]) {
245+
let resultPromise: Promise<{ isError?: boolean } | undefined> | undefined;
246+
await act(async () => {
247+
resultPromise = getLatestAppRendererProps().onMessage?.(
248+
{ role: "user", content: [{ type: "text", text }] },
249+
{} as RequestHandlerExtra,
250+
);
251+
});
252+
const sendButton = await screen.findByRole("button", {
253+
name: "Send message",
254+
});
255+
await act(async () => {
256+
fireEvent.click(sendButton);
257+
await resultPromise;
258+
});
259+
await expect(resultPromise).resolves.toEqual({});
260+
}
261+
262+
expect(onSendMessage).toHaveBeenCalledTimes(2);
263+
expect(registry.cleanupSession("virtual-session")).toMatchObject({
264+
removedProtectionSignalCount: 1,
265+
});
266+
});
267+
224268
it("rejects a pending app message without sending it", async () => {
225269
const onSendMessage = vi.fn(() => true);
226270
render(

0 commit comments

Comments
 (0)