From fa0f7d1e7398f7a4f40675393bafbd1c23f6de7c Mon Sep 17 00:00:00 2001 From: harish ganeshmurthy Date: Mon, 27 Apr 2026 14:41:33 +0400 Subject: [PATCH] fix(webchat): hide reset startup prompt from history Closes #72369. Remote validation (Blacksmith Testbox tbx_01kq7874j733m8pxesmgvfz1x1): - pnpm test src/auto-reply/reply/get-reply-run.media-only.test.ts src/gateway/server-methods/server-methods.test.ts - node scripts/run-vitest.mjs run --config test/vitest/vitest.unit-ui.config.ts ui/src/ui/controllers/chat.test.ts - pnpm check:changed Co-authored-by: haishmg <4529977+haishmg@users.noreply.github.com> --- CHANGELOG.md | 1 + .../reply/get-reply-run.media-only.test.ts | 79 +++++++++++++++++++ src/auto-reply/reply/get-reply-run.ts | 8 +- 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9e04004dae..f773b92da09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Memory-core: re-resolve the active runtime config whenever `memory_search` or `memory_get` executes, so provider changes made by `config.patch` stop leaving stale embedding backends behind in existing tool instances. Fixes #61098. Thanks @BradGroux and @Linux2010. +- WebChat: keep bare `/new` and `/reset` startup instructions out of visible chat history while preserving `/reset ` as user-visible transcript text. Fixes #72369. Thanks @collynes and @haishmg. - Channels/setup: treat bundled channel plugins as already bundled during `channels add` and onboarding, enabling them without writing redundant `plugins.load.paths` entries or path install records. Fixes #72740. Thanks @iCodePoet. - WhatsApp: honor gateway `HTTPS_PROXY` / `HTTP_PROXY` env vars for QR-login WebSocket connections, while respecting `NO_PROXY`, so proxied networks no longer fall back to direct `mmg.whatsapp.net` connections that time out with 408. Fixes #72547; supersedes #72692. Thanks @mebusw and @SymbolStar. - Bonjour: default mDNS advertisements to the system hostname when it is DNS-safe, avoiding `openclaw.local` probing conflicts and Gateway restart loops on hosts such as `Lobster` or `ubuntu`. Fixes #72355 and #72689; supersedes #72694. Thanks @mscheuerlein-bot, @gcusms, @moyuwuhen601, @pavan987, @zml-0912, @hhq365, and @SymbolStar. diff --git a/src/auto-reply/reply/get-reply-run.media-only.test.ts b/src/auto-reply/reply/get-reply-run.media-only.test.ts index 91bc70a1645..c17dc56a084 100644 --- a/src/auto-reply/reply/get-reply-run.media-only.test.ts +++ b/src/auto-reply/reply/get-reply-run.media-only.test.ts @@ -1017,6 +1017,85 @@ describe("runPreparedReply media-only handling", () => { expect(call?.transcriptCommandBody).toBe("[OpenClaw heartbeat poll]"); expect(call?.followupRun.transcriptPrompt).toBe("[OpenClaw heartbeat poll]"); }); + + it("keeps bare reset startup instructions out of visible transcript prompt", async () => { + await runPreparedReply( + baseParams({ + ctx: { + Body: "/new", + RawBody: "/new", + CommandBody: "/new", + Provider: "webchat", + Surface: "webchat", + ChatType: "direct", + }, + sessionCtx: { + Body: "", + BodyStripped: "", + Provider: "webchat", + Surface: "webchat", + ChatType: "direct", + }, + command: { + surface: "webchat", + channel: "webchat", + isAuthorizedSender: true, + abortKey: "session-key", + ownerList: [], + senderIsOwner: true, + rawBodyNormalized: "/new", + commandBodyNormalized: "/new", + } as never, + }), + ); + + const call = vi.mocked(runReplyAgent).mock.calls.at(-1)?.[0]; + expect(call?.commandBody).toContain("A new session was started via /new or /reset."); + expect(call?.followupRun.prompt).toContain("A new session was started via /new or /reset."); + expect(call?.transcriptCommandBody).toBe(""); + expect(call?.followupRun.transcriptPrompt).toBe(""); + }); + + it("keeps reset user notes visible while hiding startup instructions", async () => { + await runPreparedReply( + baseParams({ + ctx: { + Body: "/reset summarize my workspace", + RawBody: "/reset summarize my workspace", + CommandBody: "/reset summarize my workspace", + Provider: "webchat", + Surface: "webchat", + ChatType: "direct", + }, + sessionCtx: { + Body: "", + BodyStripped: "", + Provider: "webchat", + Surface: "webchat", + ChatType: "direct", + }, + command: { + surface: "webchat", + channel: "webchat", + isAuthorizedSender: true, + abortKey: "session-key", + ownerList: [], + senderIsOwner: true, + rawBodyNormalized: "/reset summarize my workspace", + commandBodyNormalized: "/reset summarize my workspace", + softResetTriggered: true, + softResetTail: "summarize my workspace", + } as never, + }), + ); + + const call = vi.mocked(runReplyAgent).mock.calls.at(-1)?.[0]; + expect(call?.commandBody).toContain("A new session was started via /new or /reset."); + expect(call?.commandBody).toContain("summarize my workspace"); + expect(call?.transcriptCommandBody).toBe("summarize my workspace"); + expect(call?.followupRun.transcriptPrompt).toBe("summarize my workspace"); + }); + it("uses inbound origin channel for run messageProvider", async () => { await runPreparedReply( baseParams({ diff --git a/src/auto-reply/reply/get-reply-run.ts b/src/auto-reply/reply/get-reply-run.ts index 84ad7bd4ccc..9660af0633e 100644 --- a/src/auto-reply/reply/get-reply-run.ts +++ b/src/auto-reply/reply/get-reply-run.ts @@ -501,9 +501,11 @@ export async function runPreparedReply( : [inboundUserContext, "[User sent media without caption]"].filter(Boolean).join("\n\n"); const transcriptBodyBase = isHeartbeat ? HEARTBEAT_TRANSCRIPT_PROMPT - : hasUserBody - ? baseBodyFinal - : "[User sent media without caption]"; + : isBareSessionReset + ? softResetTail + : hasUserBody + ? baseBodyFinal + : "[User sent media without caption]"; let prefixedBodyBase = await applySessionHints({ baseBody: effectiveBaseBody, abortedLastRun,