diff --git a/CHANGELOG.md b/CHANGELOG.md index dfff788e944..7fcc92a6cb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Auto-reply/Inbound metadata: hide direct-chat `message_id`/`message_id_full` and sender metadata only from normalized chat type (not sender-id sentinels), preserving group metadata visibility and preventing sender-id spoofed direct-mode classification. (#24373) thanks @jd316. - Security/Exec: detect obfuscated commands before exec allowlist decisions and require explicit approval for obfuscation patterns. (#8592) Thanks @CornBrother0x and @vincentkoc. - Agents/Compaction: pass `agentDir` into manual `/compact` command runs so compaction auth/profile resolution stays scoped to the active agent. (#24133) thanks @Glucksberg. - Agents/Models: codify `agents.defaults.model` / `agents.defaults.imageModel` config-boundary input as `string | {primary,fallbacks}`, split explicit vs effective model resolution, and fix `models status --agent` source attribution so defaults-inherited agents are labeled as `defaults` while runtime selection still honors defaults fallback. (#24210) thanks @bianbiandashen. diff --git a/src/auto-reply/reply/inbound-meta.test.ts b/src/auto-reply/reply/inbound-meta.test.ts index 915c4800e68..239aa23bc11 100644 --- a/src/auto-reply/reply/inbound-meta.test.ts +++ b/src/auto-reply/reply/inbound-meta.test.ts @@ -83,6 +83,30 @@ describe("buildInboundUserContextPrefix", () => { expect(text).toBe(""); }); + it("hides message identifiers for direct chats", () => { + const text = buildInboundUserContextPrefix({ + ChatType: "direct", + MessageSid: "short-id", + MessageSidFull: "provider-full-id", + } as TemplateContext); + + expect(text).toBe(""); + }); + + it("does not treat group chats as direct based on sender id", () => { + const text = buildInboundUserContextPrefix({ + ChatType: "group", + SenderId: "openclaw-control-ui", + MessageSid: "123", + ConversationLabel: "some-label", + } as TemplateContext); + + const conversationInfo = parseConversationInfoPayload(text); + expect(conversationInfo["message_id"]).toBe("123"); + expect(conversationInfo["sender_id"]).toBe("openclaw-control-ui"); + expect(conversationInfo["conversation_label"]).toBe("some-label"); + }); + it("keeps conversation label for group chats", () => { const text = buildInboundUserContextPrefix({ ChatType: "group", @@ -95,7 +119,7 @@ describe("buildInboundUserContextPrefix", () => { it("includes sender identifier in conversation info", () => { const text = buildInboundUserContextPrefix({ - ChatType: "direct", + ChatType: "group", SenderE164: " +15551234567 ", } as TemplateContext); @@ -105,7 +129,7 @@ describe("buildInboundUserContextPrefix", () => { it("includes message_id in conversation info", () => { const text = buildInboundUserContextPrefix({ - ChatType: "direct", + ChatType: "group", MessageSid: " msg-123 ", } as TemplateContext); @@ -127,7 +151,7 @@ describe("buildInboundUserContextPrefix", () => { it("omits message_id_full when it matches message_id", () => { const text = buildInboundUserContextPrefix({ - ChatType: "direct", + ChatType: "group", MessageSid: "same-id", MessageSidFull: "same-id", } as TemplateContext); @@ -139,7 +163,7 @@ describe("buildInboundUserContextPrefix", () => { it("includes reply_to_id in conversation info", () => { const text = buildInboundUserContextPrefix({ - ChatType: "direct", + ChatType: "group", MessageSid: "msg-200", ReplyToId: "msg-199", } as TemplateContext); @@ -161,7 +185,7 @@ describe("buildInboundUserContextPrefix", () => { it("trims sender_id in conversation info", () => { const text = buildInboundUserContextPrefix({ - ChatType: "direct", + ChatType: "group", MessageSid: "msg-457", SenderId: " 289522496 ", } as TemplateContext); @@ -172,7 +196,7 @@ describe("buildInboundUserContextPrefix", () => { it("falls back to SenderId when sender phone is missing", () => { const text = buildInboundUserContextPrefix({ - ChatType: "direct", + ChatType: "group", SenderId: " user@example.com ", } as TemplateContext); diff --git a/src/auto-reply/reply/inbound-meta.ts b/src/auto-reply/reply/inbound-meta.ts index bbcbc5dabac..80a2d3c3ce8 100644 --- a/src/auto-reply/reply/inbound-meta.ts +++ b/src/auto-reply/reply/inbound-meta.ts @@ -75,12 +75,18 @@ export function buildInboundUserContextPrefix(ctx: TemplateContext): string { const messageId = safeTrim(ctx.MessageSid); const messageIdFull = safeTrim(ctx.MessageSidFull); const conversationInfo = { - message_id: messageId, - message_id_full: messageIdFull && messageIdFull !== messageId ? messageIdFull : undefined, - reply_to_id: safeTrim(ctx.ReplyToId), - sender_id: safeTrim(ctx.SenderId), + message_id: isDirect ? undefined : messageId, + message_id_full: isDirect + ? undefined + : messageIdFull && messageIdFull !== messageId + ? messageIdFull + : undefined, + reply_to_id: isDirect ? undefined : safeTrim(ctx.ReplyToId), + sender_id: isDirect ? undefined : safeTrim(ctx.SenderId), conversation_label: isDirect ? undefined : safeTrim(ctx.ConversationLabel), - sender: safeTrim(ctx.SenderE164) ?? safeTrim(ctx.SenderId) ?? safeTrim(ctx.SenderUsername), + sender: isDirect + ? undefined + : (safeTrim(ctx.SenderE164) ?? safeTrim(ctx.SenderId) ?? safeTrim(ctx.SenderUsername)), group_subject: safeTrim(ctx.GroupSubject), group_channel: safeTrim(ctx.GroupChannel), group_space: safeTrim(ctx.GroupSpace),