mirror of https://github.com/openclaw/openclaw.git
fix(signal): fall back to toolContext.currentMessageId for reactions
Signal reactions required an explicit messageId parameter, unlike Telegram which already fell back to toolContext.currentMessageId. This made agent-initiated reactions fail on Signal because the inbound message ID was available in tool context but never used. - Destructure toolContext in Signal action handler - Fall back to toolContext.currentMessageId when messageId omitted - Update reaction schema descriptions (not Telegram-specific) - Add tests for fallback and missing-messageId rejection Closes #17651
This commit is contained in:
parent
f25be781c4
commit
d9fdec12ab
|
|
@ -242,14 +242,14 @@ function buildReactionSchema() {
|
|||
messageId: Type.Optional(
|
||||
Type.String({
|
||||
description:
|
||||
"Target message id for reaction. For Telegram, if omitted, defaults to the current inbound message id when available.",
|
||||
"Target message id for reaction. If omitted, defaults to the current inbound message id when available.",
|
||||
}),
|
||||
),
|
||||
message_id: Type.Optional(
|
||||
Type.String({
|
||||
// Intentional duplicate alias for tool-schema discoverability in LLMs.
|
||||
description:
|
||||
"snake_case alias of messageId. For Telegram, if omitted, defaults to the current inbound message id when available.",
|
||||
"snake_case alias of messageId. If omitted, defaults to the current inbound message id when available.",
|
||||
}),
|
||||
),
|
||||
emoji: Type.Optional(Type.String()),
|
||||
|
|
|
|||
|
|
@ -61,7 +61,11 @@ type SignalActionInput = Parameters<NonNullable<typeof signalMessageActions.hand
|
|||
async function runSignalAction(
|
||||
action: SignalActionInput["action"],
|
||||
params: SignalActionInput["params"],
|
||||
options?: { cfg?: OpenClawConfig; accountId?: string },
|
||||
options?: {
|
||||
cfg?: OpenClawConfig;
|
||||
accountId?: string;
|
||||
toolContext?: SignalActionInput["toolContext"];
|
||||
},
|
||||
) {
|
||||
const cfg =
|
||||
options?.cfg ?? ({ channels: { signal: { account: "+15550001111" } } } as OpenClawConfig);
|
||||
|
|
@ -75,6 +79,7 @@ async function runSignalAction(
|
|||
params,
|
||||
cfg,
|
||||
accountId: options?.accountId,
|
||||
toolContext: options?.toolContext,
|
||||
});
|
||||
return { cfg };
|
||||
}
|
||||
|
|
@ -852,6 +857,33 @@ describe("signalMessageActions", () => {
|
|||
}
|
||||
});
|
||||
|
||||
it("falls back to toolContext.currentMessageId for reactions when messageId is omitted", async () => {
|
||||
sendReactionSignal.mockClear();
|
||||
await runSignalAction(
|
||||
"react",
|
||||
{ to: "+15559999999", emoji: "🔥" },
|
||||
{ toolContext: { currentMessageId: "1737630212345" } },
|
||||
);
|
||||
expect(sendReactionSignal).toHaveBeenCalledTimes(1);
|
||||
expect(sendReactionSignal).toHaveBeenCalledWith(
|
||||
"+15559999999",
|
||||
1737630212345,
|
||||
"🔥",
|
||||
expect.objectContaining({}),
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects reaction when neither messageId nor toolContext.currentMessageId is provided", async () => {
|
||||
const cfg = {
|
||||
channels: { signal: { account: "+15550001111" } },
|
||||
} as OpenClawConfig;
|
||||
await expectSignalActionRejected(
|
||||
{ to: "+15559999999", emoji: "✅" },
|
||||
/messageId.*required/,
|
||||
cfg,
|
||||
);
|
||||
});
|
||||
|
||||
it("requires targetAuthor for group reactions", async () => {
|
||||
const cfg = {
|
||||
channels: { signal: { account: "+15550001111" } },
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export const signalMessageActions: ChannelMessageActionAdapter = {
|
|||
},
|
||||
supportsAction: ({ action }) => action !== "send",
|
||||
|
||||
handleAction: async ({ action, params, cfg, accountId }) => {
|
||||
handleAction: async ({ action, params, cfg, accountId, toolContext }) => {
|
||||
if (action === "send") {
|
||||
throw new Error("Send should be handled by outbound, not actions handler.");
|
||||
}
|
||||
|
|
@ -126,10 +126,14 @@ export const signalMessageActions: ChannelMessageActionAdapter = {
|
|||
throw new Error("recipient or group required");
|
||||
}
|
||||
|
||||
const messageId = readStringParam(params, "messageId", {
|
||||
required: true,
|
||||
label: "messageId (timestamp)",
|
||||
});
|
||||
const messageId =
|
||||
readStringParam(params, "messageId") ??
|
||||
(toolContext?.currentMessageId != null ? String(toolContext.currentMessageId) : undefined);
|
||||
if (!messageId) {
|
||||
throw new Error(
|
||||
"messageId (timestamp) required. Provide messageId explicitly or react to the current inbound message.",
|
||||
);
|
||||
}
|
||||
const targetAuthor = readStringParam(params, "targetAuthor");
|
||||
const targetAuthorUuid = readStringParam(params, "targetAuthorUuid");
|
||||
if (target.groupId && !targetAuthor && !targetAuthorUuid) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue