fix: unify inbound sender labels

This commit is contained in:
Peter Steinberger
2026-01-17 05:21:02 +00:00
parent 572e04d5fb
commit f7089cde54
20 changed files with 587 additions and 40 deletions

View File

@@ -0,0 +1,80 @@
import { describe, expect, it, vi } from "vitest";
import type { SlackMonitorContext } from "../context.js";
import { prepareSlackMessage } from "./prepare.js";
describe("prepareSlackMessage sender prefix", () => {
it("prefixes channel bodies with sender label", async () => {
const ctx = {
cfg: {
agents: { defaults: { model: "anthropic/claude-opus-4-5", workspace: "/tmp/clawd" } },
channels: { slack: {} },
},
accountId: "default",
botToken: "xoxb",
app: { client: {} },
runtime: {
log: vi.fn(),
error: vi.fn(),
exit: (code: number): never => {
throw new Error(`exit ${code}`);
},
},
botUserId: "BOT",
teamId: "T1",
apiAppId: "A1",
historyLimit: 0,
channelHistories: new Map(),
sessionScope: "per-sender",
mainKey: "agent:main:main",
dmEnabled: true,
dmPolicy: "open",
allowFrom: [],
groupDmEnabled: false,
groupDmChannels: [],
defaultRequireMention: true,
groupPolicy: "open",
useAccessGroups: false,
reactionMode: "off",
reactionAllowlist: [],
replyToMode: "off",
threadHistoryScope: "channel",
threadInheritParent: false,
slashCommand: { command: "/clawd", enabled: true },
textLimit: 2000,
ackReactionScope: "off",
mediaMaxBytes: 1000,
removeAckAfterReply: false,
logger: { info: vi.fn() },
markMessageSeen: () => false,
shouldDropMismatchedSlackEvent: () => false,
resolveSlackSystemEventSessionKey: () => "agent:main:slack:channel:C1",
isChannelAllowed: () => true,
resolveChannelName: async () => ({
name: "general",
type: "channel",
}),
resolveUserName: async () => ({ name: "Alice" }),
setSlackThreadStatus: async () => undefined,
} satisfies SlackMonitorContext;
const result = await prepareSlackMessage({
ctx,
account: { accountId: "default", config: {} } as never,
message: {
type: "message",
channel: "C1",
channel_type: "channel",
text: "<@BOT> hello",
user: "U1",
ts: "1700000000.0001",
event_ts: "1700000000.0001",
} as never,
opts: { source: "message", wasMentioned: true },
});
expect(result).not.toBeNull();
const body = result?.ctxPayload.Body ?? "";
expect(body).toContain("Alice (U1): <@BOT> hello");
});
});

View File

@@ -1,7 +1,10 @@
import { resolveAckReaction } from "../../../agents/identity.js";
import { hasControlCommand } from "../../../auto-reply/command-detection.js";
import { shouldHandleTextCommands } from "../../../auto-reply/commands-registry.js";
import { formatAgentEnvelope, formatThreadStarterEnvelope } from "../../../auto-reply/envelope.js";
import {
formatInboundEnvelope,
formatThreadStarterEnvelope,
} from "../../../auto-reply/envelope.js";
import {
buildPendingHistoryContextFromMap,
recordPendingHistoryEntry,
@@ -340,11 +343,13 @@ export async function prepareSlackMessage(params: {
From: slackFrom,
}) ?? (isDirectMessage ? senderName : roomLabel);
const textWithId = `${rawBody}\n[slack message id: ${message.ts} channel: ${message.channel}]`;
const body = formatAgentEnvelope({
const body = formatInboundEnvelope({
channel: "Slack",
from: envelopeFrom,
timestamp: message.ts ? Math.round(Number(message.ts) * 1000) : undefined,
body: textWithId,
chatType: isDirectMessage ? "direct" : "channel",
sender: { name: senderName, id: senderId },
});
let combinedBody = body;
@@ -355,13 +360,15 @@ export async function prepareSlackMessage(params: {
limit: ctx.historyLimit,
currentMessage: combinedBody,
formatEntry: (entry) =>
formatAgentEnvelope({
formatInboundEnvelope({
channel: "Slack",
from: roomLabel,
timestamp: entry.timestamp,
body: `${entry.sender}: ${entry.body}${
body: `${entry.body}${
entry.messageId ? ` [id:${entry.messageId} channel:${message.channel}]` : ""
}`,
chatType: "channel",
senderLabel: entry.sender,
}),
});
}