feat: mirror delivered outbound messages (#1031)
Co-authored-by: T Savo <TSavo@users.noreply.github.com>
This commit is contained in:
@@ -2,7 +2,22 @@ import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import { markdownToSignalTextChunks } from "../../signal/format.js";
|
||||
import { deliverOutboundPayloads, normalizeOutboundPayloads } from "./deliver.js";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
appendAssistantMessageToSessionTranscript: vi.fn(async () => ({ ok: true, sessionFile: "x" })),
|
||||
}));
|
||||
|
||||
vi.mock("../../config/sessions.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("../../config/sessions.js")>(
|
||||
"../../config/sessions.js",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
appendAssistantMessageToSessionTranscript: mocks.appendAssistantMessageToSessionTranscript,
|
||||
};
|
||||
});
|
||||
|
||||
const { deliverOutboundPayloads, normalizeOutboundPayloads } = await import("./deliver.js");
|
||||
|
||||
describe("deliverOutboundPayloads", () => {
|
||||
it("chunks telegram markdown and passes through accountId", async () => {
|
||||
@@ -193,4 +208,29 @@ describe("deliverOutboundPayloads", () => {
|
||||
expect(onError).toHaveBeenCalledTimes(1);
|
||||
expect(results).toEqual([{ channel: "whatsapp", messageId: "w2", toJid: "jid" }]);
|
||||
});
|
||||
|
||||
it("mirrors delivered output when mirror options are provided", async () => {
|
||||
const sendTelegram = vi.fn().mockResolvedValue({ messageId: "m1", chatId: "c1" });
|
||||
const cfg: ClawdbotConfig = {
|
||||
channels: { telegram: { botToken: "tok-1", textChunkLimit: 2 } },
|
||||
};
|
||||
mocks.appendAssistantMessageToSessionTranscript.mockClear();
|
||||
|
||||
await deliverOutboundPayloads({
|
||||
cfg,
|
||||
channel: "telegram",
|
||||
to: "123",
|
||||
payloads: [{ text: "caption", mediaUrl: "https://example.com/files/report.pdf?sig=1" }],
|
||||
deps: { sendTelegram },
|
||||
mirror: {
|
||||
sessionKey: "agent:main:main",
|
||||
text: "caption",
|
||||
mediaUrls: ["https://example.com/files/report.pdf?sig=1"],
|
||||
},
|
||||
});
|
||||
|
||||
expect(mocks.appendAssistantMessageToSessionTranscript).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ text: "report.pdf" }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,6 +11,10 @@ import { sendMessageSignal } from "../../signal/send.js";
|
||||
import type { sendMessageSlack } from "../../slack/send.js";
|
||||
import type { sendMessageTelegram } from "../../telegram/send.js";
|
||||
import type { sendMessageWhatsApp } from "../../web/outbound.js";
|
||||
import {
|
||||
appendAssistantMessageToSessionTranscript,
|
||||
resolveMirroredTranscriptText,
|
||||
} from "../../config/sessions.js";
|
||||
import type { NormalizedOutboundPayload } from "./payloads.js";
|
||||
import { normalizeOutboundPayloads } from "./payloads.js";
|
||||
import type { OutboundChannel } from "./targets.js";
|
||||
@@ -159,6 +163,12 @@ export async function deliverOutboundPayloads(params: {
|
||||
bestEffort?: boolean;
|
||||
onError?: (err: unknown, payload: NormalizedOutboundPayload) => void;
|
||||
onPayload?: (payload: NormalizedOutboundPayload) => void;
|
||||
mirror?: {
|
||||
sessionKey: string;
|
||||
agentId?: string;
|
||||
text?: string;
|
||||
mediaUrls?: string[];
|
||||
};
|
||||
}): Promise<OutboundDeliveryResult[]> {
|
||||
const { cfg, channel, to, payloads } = params;
|
||||
const accountId = params.accountId;
|
||||
@@ -279,5 +289,18 @@ export async function deliverOutboundPayloads(params: {
|
||||
params.onError?.(err, payload);
|
||||
}
|
||||
}
|
||||
if (params.mirror && results.length > 0) {
|
||||
const mirrorText = resolveMirroredTranscriptText({
|
||||
text: params.mirror.text,
|
||||
mediaUrls: params.mirror.mediaUrls,
|
||||
});
|
||||
if (mirrorText) {
|
||||
await appendAssistantMessageToSessionTranscript({
|
||||
agentId: params.mirror.agentId,
|
||||
sessionKey: params.mirror.sessionKey,
|
||||
text: mirrorText,
|
||||
});
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ export type RunMessageActionParams = {
|
||||
toolContext?: ChannelThreadingToolContext;
|
||||
gateway?: MessageActionRunnerGateway;
|
||||
deps?: OutboundSendDeps;
|
||||
sessionKey?: string;
|
||||
agentId?: string;
|
||||
dryRun?: boolean;
|
||||
};
|
||||
|
||||
@@ -265,6 +267,13 @@ export async function runMessageAction(
|
||||
bestEffort: bestEffort ?? undefined,
|
||||
deps: input.deps,
|
||||
gateway,
|
||||
mirror:
|
||||
input.sessionKey && !dryRun
|
||||
? {
|
||||
sessionKey: input.sessionKey,
|
||||
agentId: input.agentId,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -42,6 +42,10 @@ type MessageSendParams = {
|
||||
cfg?: ClawdbotConfig;
|
||||
gateway?: MessageGatewayOptions;
|
||||
idempotencyKey?: string;
|
||||
mirror?: {
|
||||
sessionKey: string;
|
||||
agentId?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type MessageSendResult = {
|
||||
@@ -142,6 +146,13 @@ export async function sendMessage(params: MessageSendParams): Promise<MessageSen
|
||||
gifPlayback: params.gifPlayback,
|
||||
deps: params.deps,
|
||||
bestEffort: params.bestEffort,
|
||||
mirror: params.mirror
|
||||
? {
|
||||
...params.mirror,
|
||||
text: params.content,
|
||||
mediaUrls: params.mediaUrl ? [params.mediaUrl] : undefined,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -165,6 +176,7 @@ export async function sendMessage(params: MessageSendParams): Promise<MessageSen
|
||||
gifPlayback: params.gifPlayback,
|
||||
accountId: params.accountId,
|
||||
channel,
|
||||
sessionKey: params.mirror?.sessionKey,
|
||||
idempotencyKey: params.idempotencyKey ?? randomIdempotencyKey(),
|
||||
},
|
||||
timeoutMs: gateway.timeoutMs,
|
||||
|
||||
Reference in New Issue
Block a user