






















@@ -115,6 +115,48 @@ async function deliverDiscordDirectMessageCompletion(params: {
115115});
116116}
117117118+async function deliverTelegramDirectMessageCompletion(params: {
119+callGateway: typeof runtimeCallGateway;
120+sendMessage?: typeof runtimeSendMessage;
121+internalEvents?: AgentInternalEvent[];
122+isActive?: boolean;
123+queueEmbeddedPiMessage?: (sessionId: string, message: string) => boolean;
124+}) {
125+const origin = {
126+channel: "telegram",
127+to: "123456789",
128+accountId: "bot-1",
129+};
130+__testing.setDepsForTest({
131+callGateway: params.callGateway,
132+getRequesterSessionActivity: () => ({
133+sessionId: "requester-session-telegram",
134+isActive: params.isActive === true,
135+}),
136+loadConfig: () => ({}) as never,
137+ ...(params.queueEmbeddedPiMessage
138+ ? { queueEmbeddedPiMessage: params.queueEmbeddedPiMessage }
139+ : {}),
140+ ...(params.sendMessage ? { sendMessage: params.sendMessage } : {}),
141+});
142+143+return deliverSubagentAnnouncement({
144+requesterSessionKey: "agent:main:telegram:123456789",
145+targetRequesterSessionKey: "agent:main:telegram:123456789",
146+triggerMessage: "child done",
147+steerMessage: "child done",
148+requesterOrigin: origin,
149+requesterSessionOrigin: origin,
150+completionDirectOrigin: origin,
151+directOrigin: origin,
152+requesterIsSubagent: false,
153+expectsCompletionMessage: true,
154+bestEffortDeliver: true,
155+directIdempotencyKey: "announce-telegram-dm-fallback",
156+internalEvents: params.internalEvents,
157+});
158+}
159+118160async function deliverSlackChannelAnnouncement(params: {
119161callGateway: typeof runtimeCallGateway;
120162isActive: boolean;
@@ -510,6 +552,92 @@ describe("deliverSubagentAnnouncement completion delivery", () => {
510552);
511553});
512554555+it("uses direct fallback for Telegram DMs when announce-agent delivery fails", async () => {
556+const callGateway = vi.fn(async () => {
557+throw new Error("UNAVAILABLE: requester wake failed");
558+}) as unknown as typeof runtimeCallGateway;
559+const sendMessage = createSendMessageMock();
560+const result = await deliverTelegramDirectMessageCompletion({
561+ callGateway,
562+ sendMessage,
563+internalEvents: [
564+{
565+type: "task_completion",
566+source: "subagent",
567+childSessionKey: "agent:worker:subagent:child",
568+childSessionId: "child-session-id",
569+announceType: "subagent task",
570+taskLabel: "telegram completion smoke",
571+status: "ok",
572+statusLabel: "completed successfully",
573+result: "child completion output",
574+replyInstruction: "Summarize the result.",
575+},
576+],
577+});
578+579+expect(result).toEqual(
580+expect.objectContaining({
581+delivered: true,
582+path: "direct-fallback",
583+}),
584+);
585+expect(sendMessage).toHaveBeenCalledWith(
586+expect.objectContaining({
587+channel: "telegram",
588+accountId: "bot-1",
589+to: "123456789",
590+threadId: undefined,
591+content: "child completion output",
592+requesterSessionKey: "agent:main:telegram:123456789",
593+bestEffort: true,
594+idempotencyKey: "announce-telegram-dm-fallback",
595+}),
596+);
597+});
598+599+it("uses direct fallback when an active Telegram requester cannot be woken", async () => {
600+const callGateway = createGatewayMock();
601+const sendMessage = createSendMessageMock();
602+const queueEmbeddedPiMessage = vi.fn(() => false);
603+const result = await deliverTelegramDirectMessageCompletion({
604+ callGateway,
605+ sendMessage,
606+isActive: true,
607+ queueEmbeddedPiMessage,
608+internalEvents: [
609+{
610+type: "task_completion",
611+source: "subagent",
612+childSessionKey: "agent:worker:subagent:child",
613+childSessionId: "child-session-id",
614+announceType: "subagent task",
615+taskLabel: "telegram wake smoke",
616+status: "ok",
617+statusLabel: "completed successfully",
618+result: "child completion output",
619+replyInstruction: "Summarize the result.",
620+},
621+],
622+});
623+624+expect(result).toEqual(
625+expect.objectContaining({
626+delivered: true,
627+path: "direct-fallback",
628+}),
629+);
630+expect(queueEmbeddedPiMessage).toHaveBeenCalledWith("requester-session-telegram", "child done");
631+expect(callGateway).not.toHaveBeenCalled();
632+expect(sendMessage).toHaveBeenCalledWith(
633+expect.objectContaining({
634+channel: "telegram",
635+to: "123456789",
636+content: "child completion output",
637+}),
638+);
639+});
640+513641it("uses a direct thread fallback when announce-agent returns no visible output", async () => {
514642const callGateway = createGatewayMock({
515643result: {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。