Skip to content

Commit cc95479

Browse files
authored
fix(imessage): honor disabled reply actions (#93137)
Co-authored-by: Omar Shahine <[email protected]>
1 parent 4fc8053 commit cc95479

2 files changed

Lines changed: 56 additions & 1 deletion

File tree

extensions/imessage/src/send.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,30 @@ describe("sendMessageIMessage receipts", () => {
121121
expect(result.receipt.sentAt).toBeGreaterThan(0);
122122
});
123123

124+
it("drops reply metadata from text sends when reply actions are disabled", async () => {
125+
const client = createClient({ guid: "p:0/imsg-plain" });
126+
127+
const result = await sendMessageIMessage("chat_id:42", "hello", {
128+
config: {
129+
channels: {
130+
imessage: {
131+
actions: { reply: false },
132+
accounts: { default: {} },
133+
},
134+
},
135+
},
136+
client,
137+
replyToId: "reply-1",
138+
});
139+
140+
const sendParams = getClientMocks(client).request.mock.calls[0]?.[1] as
141+
| Record<string, unknown>
142+
| undefined;
143+
expect(sendParams).not.toHaveProperty("reply_to");
144+
expect(result.receipt.replyToId).toBeUndefined();
145+
expect(result.receipt.parts[0]?.replyToId).toBeUndefined();
146+
});
147+
124148
it("passes the default RPC send transport", async () => {
125149
const client = createClient({ guid: "p:0/imsg-transport-default" });
126150

@@ -299,6 +323,35 @@ describe("sendMessageIMessage receipts", () => {
299323
expect(client["request"]).not.toHaveBeenCalled();
300324
});
301325

326+
it("drops reply metadata from media sends when reply actions are disabled", async () => {
327+
const client = createClient({ message_id: 12345 });
328+
const runCliJson = vi.fn().mockResolvedValueOnce({ messageId: "p:0/plain-media-guid" });
329+
330+
const result = await sendMessageIMessage("chat_guid:chat-1", "", {
331+
config: {
332+
channels: {
333+
imessage: {
334+
actions: { reply: false },
335+
accounts: { default: {} },
336+
},
337+
},
338+
},
339+
client,
340+
mediaUrl: "/tmp/image.png",
341+
replyToId: "p:0/reply-guid",
342+
resolveAttachmentImpl: async () => ({ path: "/tmp/image.png", contentType: "image/png" }),
343+
runCliJson,
344+
});
345+
346+
expect(result.messageId).toBe("p:0/plain-media-guid");
347+
expect(runCliJson.mock.calls).toEqual([
348+
[["send-attachment", "--chat", "chat-1", "--file", "/tmp/image.png", "--transport", "auto"]],
349+
]);
350+
expect(result.receipt.replyToId).toBeUndefined();
351+
expect(result.receipt.parts[0]?.replyToId).toBeUndefined();
352+
expect(client["request"]).not.toHaveBeenCalled();
353+
});
354+
302355
it("resolves chat_id media-only payloads before using send-attachment", async () => {
303356
const client = createClient({ message_id: 12345 });
304357
const runCliJson = vi

extensions/imessage/src/send.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { constants, accessSync, readFileSync } from "node:fs";
44
import { createRequire } from "node:module";
55
import os from "node:os";
66
import path from "node:path";
7+
import { createActionGate } from "openclaw/plugin-sdk/channel-actions";
78
import {
89
createMessageReceiptFromOutboundResults,
910
type MessageReceipt,
@@ -948,7 +949,8 @@ export async function sendMessageIMessage(
948949
throw new Error("iMessage send requires text or media");
949950
}
950951
const echoText = resolveOutboundEchoText(message, filePath ? mediaContentType : undefined);
951-
const resolvedReplyToId = sanitizeReplyToId(opts.replyToId);
952+
const replyActionsEnabled = createActionGate(account.config.actions)("reply");
953+
const resolvedReplyToId = replyActionsEnabled ? sanitizeReplyToId(opts.replyToId) : undefined;
952954
const runCliJson =
953955
opts.runCliJson ??
954956
((args: readonly string[]) => runIMessageCliJson(cliPath, dbPath, args, timeoutMs));

0 commit comments

Comments
 (0)