



























@@ -1571,6 +1571,112 @@ describe("dispatchTelegramMessage draft streaming", () => {
15711571expect(groupHistories.get(historyKey)).toHaveLength(1);
15721572});
157315731574+it("keeps room-event history when a newer turn supersedes dispatch", async () => {
1575+const historyKey = "telegram:group:-100123";
1576+const groupHistories = new Map([
1577+[historyKey, [{ sender: "Alice", body: "lunch at two", timestamp: 1 }]],
1578+]);
1579+let releaseFirst: (() => void) | undefined;
1580+const firstGate = new Promise<void>((resolve) => {
1581+releaseFirst = resolve;
1582+});
1583+let secondStarted: (() => void) | undefined;
1584+const secondStartGate = new Promise<void>((resolve) => {
1585+secondStarted = resolve;
1586+});
1587+dispatchReplyWithBufferedBlockDispatcher
1588+.mockImplementationOnce(async () => {
1589+await firstGate;
1590+return {
1591+queuedFinal: false,
1592+counts: { block: 0, final: 0, tool: 0 },
1593+sourceReplyDeliveryMode: "message_tool_only",
1594+};
1595+})
1596+.mockImplementationOnce(async () => {
1597+secondStarted?.();
1598+return {
1599+queuedFinal: false,
1600+counts: { block: 0, final: 0, tool: 0 },
1601+sourceReplyDeliveryMode: "message_tool_only",
1602+};
1603+});
1604+1605+const createRoomContext = (messageId: number, body: string) =>
1606+createContext({
1607+ctxPayload: {
1608+InboundTurnKind: "room_event",
1609+SessionKey: "agent:main:telegram:group:-100123",
1610+ChatType: "group",
1611+MessageSid: String(messageId),
1612+RawBody: body,
1613+BodyForAgent: body,
1614+CommandBody: body,
1615+} as unknown as TelegramMessageContext["ctxPayload"],
1616+msg: {
1617+chat: { id: -100123, type: "supergroup" },
1618+message_id: messageId,
1619+} as unknown as TelegramMessageContext["msg"],
1620+chatId: -100123,
1621+isGroup: true,
1622+ historyKey,
1623+historyLimit: 10,
1624+ groupHistories,
1625+threadSpec: { id: undefined, scope: "none" },
1626+});
1627+1628+const firstPromise = dispatchWithContext({
1629+context: createRoomContext(99, "ambient one"),
1630+streamMode: "partial",
1631+});
1632+const secondPromise = dispatchWithContext({
1633+context: createRoomContext(100, "ambient two"),
1634+streamMode: "partial",
1635+});
1636+1637+await secondStartGate;
1638+releaseFirst?.();
1639+await Promise.all([firstPromise, secondPromise]);
1640+1641+expect(groupHistories.get(historyKey)).toHaveLength(1);
1642+});
1643+1644+it("does not send visible error fallbacks for room events", async () => {
1645+const historyKey = "telegram:group:-100123";
1646+const groupHistories = new Map([
1647+[historyKey, [{ sender: "Alice", body: "quiet failure", timestamp: 1 }]],
1648+]);
1649+dispatchReplyWithBufferedBlockDispatcher.mockRejectedValue(new Error("provider down"));
1650+1651+await dispatchWithContext({
1652+context: createContext({
1653+ctxPayload: {
1654+InboundTurnKind: "room_event",
1655+SessionKey: "agent:main:telegram:group:-100123",
1656+ChatType: "group",
1657+MessageSid: "101",
1658+RawBody: "ambient failure",
1659+BodyForAgent: "ambient failure",
1660+CommandBody: "ambient failure",
1661+} as unknown as TelegramMessageContext["ctxPayload"],
1662+msg: {
1663+chat: { id: -100123, type: "supergroup" },
1664+message_id: 101,
1665+} as unknown as TelegramMessageContext["msg"],
1666+chatId: -100123,
1667+isGroup: true,
1668+ historyKey,
1669+historyLimit: 10,
1670+ groupHistories,
1671+threadSpec: { id: undefined, scope: "none" },
1672+}),
1673+streamMode: "partial",
1674+});
1675+1676+expect(deliverReplies).not.toHaveBeenCalled();
1677+expect(groupHistories.get(historyKey)).toHaveLength(1);
1678+});
1679+15741680it("shows compacting reaction during auto-compaction and resumes thinking", async () => {
15751681const statusReactionController = {
15761682setThinking: vi.fn(async () => {}),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。