mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-19 14:00:51 +00:00
Signal: move message actions behind plugin boundary
This commit is contained in:
@@ -32,3 +32,22 @@ describe("signalPlugin outbound sendMedia", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("signalPlugin actions", () => {
|
||||
it("owns unified message tool discovery", () => {
|
||||
const discovery = signalPlugin.actions?.describeMessageTool?.({
|
||||
cfg: {
|
||||
channels: {
|
||||
signal: {
|
||||
actions: { reactions: false },
|
||||
accounts: {
|
||||
work: { account: "+15550001111", actions: { reactions: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
});
|
||||
|
||||
expect(discovery?.actions).toEqual(["send", "react"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
normalizeSignalMessagingTarget,
|
||||
PAIRING_APPROVED_MESSAGE,
|
||||
resolveChannelMediaMaxBytes,
|
||||
type ChannelMessageActionAdapter,
|
||||
type ChannelPlugin,
|
||||
} from "openclaw/plugin-sdk/signal";
|
||||
import { resolveSignalAccount, type ResolvedSignalAccount } from "./accounts.js";
|
||||
@@ -30,25 +29,12 @@ import {
|
||||
resolveSignalRecipient,
|
||||
resolveSignalSender,
|
||||
} from "./identity.js";
|
||||
import { signalMessageActions } from "./message-actions.js";
|
||||
import type { SignalProbe } from "./probe.js";
|
||||
import { getSignalRuntime } from "./runtime.js";
|
||||
import { signalSetupAdapter } from "./setup-core.js";
|
||||
import { createSignalPluginBase, signalConfigAccessors, signalSetupWizard } from "./shared.js";
|
||||
|
||||
const signalMessageActions: ChannelMessageActionAdapter = {
|
||||
describeMessageTool: (ctx) =>
|
||||
getSignalRuntime().channel.signal.messageActions?.describeMessageTool?.(ctx) ?? null,
|
||||
supportsAction: (ctx) =>
|
||||
getSignalRuntime().channel.signal.messageActions?.supportsAction?.(ctx) ?? false,
|
||||
handleAction: async (ctx) => {
|
||||
const ma = getSignalRuntime().channel.signal.messageActions;
|
||||
if (!ma?.handleAction) {
|
||||
throw new Error("Signal message actions not available");
|
||||
}
|
||||
return ma.handleAction(ctx);
|
||||
},
|
||||
};
|
||||
|
||||
type SignalSendFn = ReturnType<typeof getSignalRuntime>["channel"]["signal"]["sendMessageSignal"];
|
||||
|
||||
function resolveSignalSendContext(params: {
|
||||
|
||||
@@ -3,3 +3,4 @@ export { probeSignal } from "./probe.js";
|
||||
export { sendMessageSignal } from "./send.js";
|
||||
export { sendReactionSignal, removeReactionSignal } from "./send-reactions.js";
|
||||
export { resolveSignalReactionLevel } from "./reaction-level.js";
|
||||
export { signalMessageActions } from "./message-actions.js";
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { createActionGate, jsonResult, readStringParam } from "../../../agents/tools/common.js";
|
||||
import { resolveSignalAccount } from "../../../plugin-sdk/account-resolution.js";
|
||||
import {
|
||||
listEnabledSignalAccounts,
|
||||
removeReactionSignal,
|
||||
resolveSignalReactionLevel,
|
||||
sendReactionSignal,
|
||||
} from "../../../plugin-sdk/signal.js";
|
||||
import type { ChannelMessageActionAdapter, ChannelMessageActionName } from "../types.js";
|
||||
import { resolveReactionMessageId } from "./reaction-message-id.js";
|
||||
createActionGate,
|
||||
jsonResult,
|
||||
readStringParam,
|
||||
resolveReactionMessageId,
|
||||
type ChannelMessageActionAdapter,
|
||||
type ChannelMessageActionName,
|
||||
} from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { listEnabledSignalAccounts, resolveSignalAccount } from "./accounts.js";
|
||||
import { resolveSignalReactionLevel } from "./reaction-level.js";
|
||||
import { removeReactionSignal, sendReactionSignal } from "./send-reactions.js";
|
||||
|
||||
const providerId = "signal";
|
||||
const GROUP_PREFIX = "group:";
|
||||
@@ -103,7 +104,6 @@ export const signalMessageActions: ChannelMessageActionAdapter = {
|
||||
}
|
||||
|
||||
if (action === "react") {
|
||||
// Check reaction level first
|
||||
const reactionLevelInfo = resolveSignalReactionLevel({
|
||||
cfg,
|
||||
accountId: accountId ?? undefined,
|
||||
@@ -115,7 +115,6 @@ export const signalMessageActions: ChannelMessageActionAdapter = {
|
||||
);
|
||||
}
|
||||
|
||||
// Also check the action gate for backward compatibility
|
||||
const actionConfig = resolveSignalAccount({ cfg, accountId }).config.actions;
|
||||
const isActionEnabled = createActionGate(actionConfig);
|
||||
if (!isActionEnabled("reactions")) {
|
||||
@@ -1,10 +1,9 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { removeReactionSignal, sendReactionSignal } from "./send-reactions.js";
|
||||
|
||||
const rpcMock = vi.fn();
|
||||
|
||||
vi.mock("../../../src/config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/config/config.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => ({}),
|
||||
@@ -25,9 +24,14 @@ vi.mock("./client.js", () => ({
|
||||
signalRpcRequest: (...args: unknown[]) => rpcMock(...args),
|
||||
}));
|
||||
|
||||
let sendReactionSignal: typeof import("./send-reactions.js").sendReactionSignal;
|
||||
let removeReactionSignal: typeof import("./send-reactions.js").removeReactionSignal;
|
||||
|
||||
describe("sendReactionSignal", () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
rpcMock.mockClear().mockResolvedValue({ timestamp: 123 });
|
||||
({ sendReactionSignal, removeReactionSignal } = await import("./send-reactions.js"));
|
||||
});
|
||||
|
||||
it("uses recipients array and targetAuthor for uuid dms", async () => {
|
||||
|
||||
@@ -28,7 +28,7 @@ vi.mock("../../../../extensions/slack/src/action-runtime.js", () => ({
|
||||
let discordMessageActions: typeof import("./discord.js").discordMessageActions;
|
||||
let handleDiscordMessageAction: typeof import("./discord/handle-action.js").handleDiscordMessageAction;
|
||||
let telegramMessageActions: typeof import("./telegram.js").telegramMessageActions;
|
||||
let signalMessageActions: typeof import("./signal.js").signalMessageActions;
|
||||
let signalMessageActions: typeof import("../../../../extensions/signal/src/message-actions.js").signalMessageActions;
|
||||
let createSlackActions: typeof import("../../../../extensions/slack/src/channel-actions.js").createSlackActions;
|
||||
|
||||
function getDescribedActions(params: {
|
||||
@@ -204,7 +204,7 @@ beforeEach(async () => {
|
||||
({ discordMessageActions } = await import("./discord.js"));
|
||||
({ handleDiscordMessageAction } = await import("./discord/handle-action.js"));
|
||||
({ telegramMessageActions } = await import("./telegram.js"));
|
||||
({ signalMessageActions } = await import("./signal.js"));
|
||||
({ signalMessageActions } = await import("../../../../extensions/signal/src/message-actions.js"));
|
||||
({ createSlackActions } = await import("../../../../extensions/slack/src/channel-actions.js"));
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
@@ -44,6 +44,7 @@ export * from "../channels/plugins/whatsapp-heartbeat.js";
|
||||
export * from "../infra/outbound/send-deps.js";
|
||||
export * from "../polls.js";
|
||||
export * from "../utils/message-channel.js";
|
||||
export { createActionGate, jsonResult, readStringParam } from "../agents/tools/common.js";
|
||||
export * from "./channel-lifecycle.js";
|
||||
export type {
|
||||
InteractiveButtonStyle,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {
|
||||
monitorSignalProvider,
|
||||
probeSignal,
|
||||
signalMessageActions,
|
||||
sendMessageSignal,
|
||||
} from "../../../extensions/signal/runtime-api.js";
|
||||
import { signalMessageActions } from "../../channels/plugins/actions/signal.js";
|
||||
import type { PluginRuntimeChannel } from "./types-channel.js";
|
||||
|
||||
export function createRuntimeSignal(): PluginRuntimeChannel["signal"] {
|
||||
|
||||
@@ -197,7 +197,7 @@ export type PluginRuntimeChannel = {
|
||||
probeSignal: typeof import("../../../extensions/signal/runtime-api.js").probeSignal;
|
||||
sendMessageSignal: typeof import("../../../extensions/signal/runtime-api.js").sendMessageSignal;
|
||||
monitorSignalProvider: typeof import("../../../extensions/signal/runtime-api.js").monitorSignalProvider;
|
||||
messageActions: typeof import("../../channels/plugins/actions/signal.js").signalMessageActions;
|
||||
messageActions: typeof import("../../../extensions/signal/runtime-api.js").signalMessageActions;
|
||||
};
|
||||
imessage: {
|
||||
monitorIMessageProvider: typeof import("../../../extensions/imessage/runtime-api.js").monitorIMessageProvider;
|
||||
|
||||
@@ -164,7 +164,6 @@ function buildCoreDistEntries(): Record<string, string> {
|
||||
"channels/plugins/agent-tools/whatsapp-login":
|
||||
"src/channels/plugins/agent-tools/whatsapp-login.ts",
|
||||
"channels/plugins/actions/discord": "src/channels/plugins/actions/discord.ts",
|
||||
"channels/plugins/actions/signal": "src/channels/plugins/actions/signal.ts",
|
||||
"channels/plugins/actions/telegram": "src/channels/plugins/actions/telegram.ts",
|
||||
"telegram/audit": "extensions/telegram/src/audit.ts",
|
||||
"telegram/token": "extensions/telegram/src/token.ts",
|
||||
|
||||
Reference in New Issue
Block a user