CLI: preserve message send components payload

This commit is contained in:
Saurabh.Chopade
2026-02-16 21:53:14 +05:30
committed by Peter Steinberger
parent 63fb998074
commit bb5ce3b02f
4 changed files with 91 additions and 0 deletions

View File

@@ -19,6 +19,7 @@ export function registerMessageSendCommand(message: Command, helpers: MessageCli
"--buttons <json>",
"Telegram inline keyboard buttons as JSON (array of button rows)",
)
.option("--components <json>", "Discord components payload as JSON")
.option("--card <json>", "Adaptive Card JSON object (when supported by the channel)")
.option("--reply-to <id>", "Reply-to message id")
.option("--thread-id <id>", "Thread id (Telegram forum thread)")

View File

@@ -369,3 +369,20 @@ export function parseCardParam(params: Record<string, unknown>): void {
throw new Error("--card must be valid JSON");
}
}
export function parseComponentsParam(params: Record<string, unknown>): void {
const raw = params.components;
if (typeof raw !== "string") {
return;
}
const trimmed = raw.trim();
if (!trimmed) {
delete params.components;
return;
}
try {
params.components = JSON.parse(trimmed) as unknown;
} catch {
throw new Error("--components must be valid JSON");
}
}

View File

@@ -740,6 +740,77 @@ describe("runMessageAction card-only send behavior", () => {
});
});
describe("runMessageAction components parsing", () => {
const handleAction = vi.fn(async ({ params }: { params: Record<string, unknown> }) =>
jsonResult({
ok: true,
components: params.components ?? null,
}),
);
const componentsPlugin: ChannelPlugin = {
id: "discord",
meta: {
id: "discord",
label: "Discord",
selectionLabel: "Discord",
docsPath: "/channels/discord",
blurb: "Discord components send test plugin.",
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: () => ["default"],
resolveAccount: () => ({}),
isConfigured: () => true,
},
actions: {
listActions: () => ["send"],
supportsAction: ({ action }) => action === "send",
handleAction,
},
};
beforeEach(() => {
setActivePluginRegistry(
createTestRegistry([
{
pluginId: "discord",
source: "test",
plugin: componentsPlugin,
},
]),
);
handleAction.mockClear();
});
afterEach(() => {
setActivePluginRegistry(createTestRegistry([]));
vi.clearAllMocks();
});
it("parses components JSON strings before plugin dispatch", async () => {
const components = {
text: "hello",
buttons: [{ label: "A", customId: "a" }],
};
const result = await runMessageAction({
cfg: {} as OpenClawConfig,
action: "send",
params: {
channel: "discord",
target: "channel:123",
message: "hi",
components: JSON.stringify(components),
},
dryRun: false,
});
expect(result.kind).toBe("send");
expect(handleAction).toHaveBeenCalled();
expect(result.payload).toMatchObject({ ok: true, components });
});
});
describe("runMessageAction accountId defaults", () => {
const handleAction = vi.fn(async () => jsonResult({ ok: true }));
const accountPlugin: ChannelPlugin = {

View File

@@ -34,6 +34,7 @@ import {
normalizeSandboxMediaParams,
parseButtonsParam,
parseCardParam,
parseComponentsParam,
readBooleanParam,
resolveSlackAutoThreadId,
resolveTelegramAutoThreadId,
@@ -697,6 +698,7 @@ export async function runMessageAction(
: undefined);
parseButtonsParam(params);
parseCardParam(params);
parseComponentsParam(params);
const action = input.action;
if (action === "broadcast") {