Merge remote-tracking branch 'origin/main' into feature/agent-avatar-support

This commit is contained in:
Peter Steinberger
2026-01-22 06:27:45 +00:00
10 changed files with 352 additions and 93 deletions

View File

@@ -120,7 +120,6 @@ const getOnHandler = (event: string) => {
};
const ORIGINAL_TZ = process.env.TZ;
describe("createTelegramBot", () => {
beforeEach(() => {
process.env.TZ = "UTC";
@@ -153,6 +152,11 @@ describe("createTelegramBot", () => {
replySpy.mockReset();
loadConfig.mockReturnValue({
agents: {
defaults: {
envelopeTimezone: "utc",
},
},
identity: { name: "Bert" },
messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
channels: {
@@ -195,6 +199,11 @@ describe("createTelegramBot", () => {
replySpy.mockReset();
loadConfig.mockReturnValue({
agents: {
defaults: {
envelopeTimezone: "utc",
},
},
channels: {
telegram: {
groupPolicy: "open",

View File

@@ -129,6 +129,11 @@ describe("createTelegramBot", () => {
process.env.TZ = "UTC";
resetInboundDedupe();
loadConfig.mockReturnValue({
agents: {
defaults: {
envelopeTimezone: "utc",
},
},
channels: {
telegram: { dmPolicy: "open", allowFrom: ["*"] },
},

View File

@@ -149,12 +149,16 @@ const getOnHandler = (event: string) => {
};
const ORIGINAL_TZ = process.env.TZ;
describe("createTelegramBot", () => {
beforeEach(() => {
process.env.TZ = "UTC";
resetInboundDedupe();
loadConfig.mockReturnValue({
agents: {
defaults: {
envelopeTimezone: "utc",
},
},
channels: {
telegram: { dmPolicy: "open", allowFrom: ["*"] },
},
@@ -562,106 +566,104 @@ describe("createTelegramBot", () => {
});
it("accepts group messages when mentionPatterns match (without @botUsername)", async () => {
const originalTz = process.env.TZ;
process.env.TZ = "UTC";
onSpy.mockReset();
const replySpy = replyModule.__replySpy as unknown as ReturnType<typeof vi.fn>;
replySpy.mockReset();
try {
loadConfig.mockReturnValue({
identity: { name: "Bert" },
messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
channels: {
telegram: {
groupPolicy: "open",
groups: { "*": { requireMention: true } },
},
loadConfig.mockReturnValue({
agents: {
defaults: {
envelopeTimezone: "utc",
},
});
createTelegramBot({ token: "tok" });
const handler = getOnHandler("message") as (ctx: Record<string, unknown>) => Promise<void>;
await handler({
message: {
chat: { id: 7, type: "group", title: "Test Group" },
text: "bert: introduce yourself",
date: 1736380800,
message_id: 1,
from: { id: 9, first_name: "Ada" },
},
identity: { name: "Bert" },
messages: { groupChat: { mentionPatterns: ["\\bbert\\b"] } },
channels: {
telegram: {
groupPolicy: "open",
groups: { "*": { requireMention: true } },
},
me: { username: "clawdbot_bot" },
getFile: async () => ({ download: async () => new Uint8Array() }),
});
},
});
expect(replySpy).toHaveBeenCalledTimes(1);
const payload = replySpy.mock.calls[0][0];
expectInboundContextContract(payload);
expect(payload.WasMentioned).toBe(true);
const expectedTimestamp = formatEnvelopeTimestamp(new Date("2025-01-09T00:00:00Z"));
const timestampPattern = escapeRegExp(expectedTimestamp);
expect(payload.Body).toMatch(
new RegExp(`^\\[Telegram Test Group id:7 (\\+\\d+[smhd] )?${timestampPattern}\\]`),
);
expect(payload.SenderName).toBe("Ada");
expect(payload.SenderId).toBe("9");
} finally {
process.env.TZ = originalTz;
}
createTelegramBot({ token: "tok" });
const handler = getOnHandler("message") as (ctx: Record<string, unknown>) => Promise<void>;
await handler({
message: {
chat: { id: 7, type: "group", title: "Test Group" },
text: "bert: introduce yourself",
date: 1736380800,
message_id: 1,
from: { id: 9, first_name: "Ada" },
},
me: { username: "clawdbot_bot" },
getFile: async () => ({ download: async () => new Uint8Array() }),
});
expect(replySpy).toHaveBeenCalledTimes(1);
const payload = replySpy.mock.calls[0][0];
expectInboundContextContract(payload);
expect(payload.WasMentioned).toBe(true);
const expectedTimestamp = formatEnvelopeTimestamp(new Date("2025-01-09T00:00:00Z"));
const timestampPattern = escapeRegExp(expectedTimestamp);
expect(payload.Body).toMatch(
new RegExp(`^\\[Telegram Test Group id:7 (\\+\\d+[smhd] )?${timestampPattern}\\]`),
);
expect(payload.SenderName).toBe("Ada");
expect(payload.SenderId).toBe("9");
});
it("includes sender identity in group envelope headers", async () => {
const originalTz = process.env.TZ;
process.env.TZ = "UTC";
onSpy.mockReset();
const replySpy = replyModule.__replySpy as unknown as ReturnType<typeof vi.fn>;
replySpy.mockReset();
try {
loadConfig.mockReturnValue({
channels: {
telegram: {
groupPolicy: "open",
groups: { "*": { requireMention: false } },
},
loadConfig.mockReturnValue({
agents: {
defaults: {
envelopeTimezone: "utc",
},
});
createTelegramBot({ token: "tok" });
const handler = getOnHandler("message") as (ctx: Record<string, unknown>) => Promise<void>;
await handler({
message: {
chat: { id: 42, type: "group", title: "Ops" },
text: "hello",
date: 1736380800,
message_id: 2,
from: {
id: 99,
first_name: "Ada",
last_name: "Lovelace",
username: "ada",
},
},
channels: {
telegram: {
groupPolicy: "open",
groups: { "*": { requireMention: false } },
},
me: { username: "clawdbot_bot" },
getFile: async () => ({ download: async () => new Uint8Array() }),
});
},
});
expect(replySpy).toHaveBeenCalledTimes(1);
const payload = replySpy.mock.calls[0][0];
expectInboundContextContract(payload);
const expectedTimestamp = formatEnvelopeTimestamp(new Date("2025-01-09T00:00:00Z"));
const timestampPattern = escapeRegExp(expectedTimestamp);
expect(payload.Body).toMatch(
new RegExp(`^\\[Telegram Ops id:42 (\\+\\d+[smhd] )?${timestampPattern}\\]`),
);
expect(payload.SenderName).toBe("Ada Lovelace");
expect(payload.SenderId).toBe("99");
expect(payload.SenderUsername).toBe("ada");
} finally {
process.env.TZ = originalTz;
}
createTelegramBot({ token: "tok" });
const handler = getOnHandler("message") as (ctx: Record<string, unknown>) => Promise<void>;
await handler({
message: {
chat: { id: 42, type: "group", title: "Ops" },
text: "hello",
date: 1736380800,
message_id: 2,
from: {
id: 99,
first_name: "Ada",
last_name: "Lovelace",
username: "ada",
},
},
me: { username: "clawdbot_bot" },
getFile: async () => ({ download: async () => new Uint8Array() }),
});
expect(replySpy).toHaveBeenCalledTimes(1);
const payload = replySpy.mock.calls[0][0];
expectInboundContextContract(payload);
const expectedTimestamp = formatEnvelopeTimestamp(new Date("2025-01-09T00:00:00Z"));
const timestampPattern = escapeRegExp(expectedTimestamp);
expect(payload.Body).toMatch(
new RegExp(`^\\[Telegram Ops id:42 (\\+\\d+[smhd] )?${timestampPattern}\\]`),
);
expect(payload.SenderName).toBe("Ada Lovelace");
expect(payload.SenderId).toBe("99");
expect(payload.SenderUsername).toBe("ada");
});
it("reacts to mention-gated group messages when ackReaction is enabled", async () => {