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,87 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const dispatchMock = vi.fn();
const readAllowFromMock = vi.fn();
vi.mock("../pairing/pairing-store.js", () => ({
readChannelAllowFromStore: (...args: unknown[]) => readAllowFromMock(...args),
upsertChannelPairingRequest: vi.fn(),
}));
describe("signal event handler sender prefix", () => {
beforeEach(() => {
dispatchMock.mockReset().mockImplementation(async ({ dispatcher, ctx }) => {
dispatcher.sendFinalReply({ text: "ok" });
return { queuedFinal: true, counts: { final: 1 }, ctx };
});
readAllowFromMock.mockReset().mockResolvedValue([]);
});
it("prefixes group bodies with sender label", async () => {
let capturedBody = "";
const dispatchModule = await import("../auto-reply/reply/dispatch-from-config.js");
vi.spyOn(dispatchModule, "dispatchReplyFromConfig").mockImplementation(
async (...args: unknown[]) => dispatchMock(...args),
);
dispatchMock.mockImplementationOnce(async ({ dispatcher, ctx }) => {
capturedBody = ctx.Body ?? "";
dispatcher.sendFinalReply({ text: "ok" });
return { queuedFinal: true, counts: { final: 1 } };
});
const { createSignalEventHandler } = await import("./monitor/event-handler.js");
const handler = createSignalEventHandler({
runtime: {
log: vi.fn(),
error: vi.fn(),
exit: (code: number): never => {
throw new Error(`exit ${code}`);
},
},
cfg: {
agents: { defaults: { model: "anthropic/claude-opus-4-5", workspace: "/tmp/clawd" } },
channels: { signal: {} },
} as never,
baseUrl: "http://localhost",
account: "+15550009999",
accountId: "default",
blockStreaming: false,
historyLimit: 0,
groupHistories: new Map(),
textLimit: 4000,
dmPolicy: "open",
allowFrom: [],
groupAllowFrom: [],
groupPolicy: "open",
reactionMode: "off",
reactionAllowlist: [],
mediaMaxBytes: 1000,
ignoreAttachments: true,
fetchAttachment: async () => null,
deliverReplies: async () => undefined,
resolveSignalReactionTargets: () => [],
isSignalReactionMessage: () => false,
shouldEmitSignalReactionNotification: () => false,
buildSignalReactionSystemEventText: () => "",
});
const payload = {
envelope: {
sourceNumber: "+15550002222",
sourceName: "Alice",
timestamp: 1700000000000,
dataMessage: {
message: "hello",
groupInfo: { groupId: "group-1", groupName: "Test Group" },
},
},
};
await handler({ event: "receive", data: JSON.stringify(payload) });
expect(dispatchMock).toHaveBeenCalled();
expect(capturedBody).toContain("Alice (+15550002222): hello");
});
});

View File

@@ -8,7 +8,7 @@ import {
type ResponsePrefixContext,
} from "../../auto-reply/reply/response-prefix-template.js";
import { hasControlCommand } from "../../auto-reply/command-detection.js";
import { formatAgentEnvelope } from "../../auto-reply/envelope.js";
import { formatInboundEnvelope } from "../../auto-reply/envelope.js";
import {
createInboundDebouncer,
resolveInboundDebounceMs,
@@ -68,11 +68,13 @@ export function createSignalEventHandler(deps: SignalEventHandlerDeps) {
const fromLabel = entry.isGroup
? `${entry.groupName ?? "Signal Group"} id:${entry.groupId}`
: `${entry.senderName} id:${entry.senderDisplay}`;
const body = formatAgentEnvelope({
const body = formatInboundEnvelope({
channel: "Signal",
from: fromLabel,
timestamp: entry.timestamp ?? undefined,
body: entry.bodyText,
chatType: entry.isGroup ? "group" : "direct",
sender: { name: entry.senderName, id: entry.senderDisplay },
});
let combinedBody = body;
const historyKey = entry.isGroup ? String(entry.groupId ?? "unknown") : undefined;
@@ -83,13 +85,15 @@ export function createSignalEventHandler(deps: SignalEventHandlerDeps) {
limit: deps.historyLimit,
currentMessage: combinedBody,
formatEntry: (historyEntry) =>
formatAgentEnvelope({
formatInboundEnvelope({
channel: "Signal",
from: fromLabel,
timestamp: historyEntry.timestamp,
body: `${historyEntry.sender}: ${historyEntry.body}${
body: `${historyEntry.body}${
historyEntry.messageId ? ` [id:${historyEntry.messageId}]` : ""
}`,
chatType: "group",
senderLabel: historyEntry.sender,
}),
});
}