
























@@ -1,21 +1,71 @@
1-import type { ChannelMessageActionAdapter } from "openclaw/plugin-sdk/channel-contract";
1+import type {
2+ChannelMessageActionAdapter,
3+ChannelMessageActionName,
4+ChannelMessageToolDiscovery,
5+ChannelMessageToolSchemaContribution,
6+} from "openclaw/plugin-sdk/channel-contract";
7+import { Type, type TSchema } from "typebox";
28import { isSlackInteractiveRepliesEnabled } from "./interactive-replies.js";
39import { listSlackMessageActions } from "./message-actions.js";
41011+const SLACK_MESSAGE_ID_ACTIONS = ["react", "reactions", "edit", "delete", "pin", "unpin"] as const;
12+13+function createSlackFileActionSchema(): Record<string, TSchema> {
14+return {
15+fileId: Type.Optional(
16+Type.String({
17+description:
18+'Slack file id, starting with "F" (for example F0B0LTT8M36). Required for action="download-file". Read it from inbound Slack file metadata at event.files[].id. This is not the Slack message timestamp/messageId.',
19+}),
20+),
21+};
22+}
23+24+function createSlackMessageIdActionSchema(): Record<string, TSchema> {
25+const description =
26+'Slack message timestamp/message id (for example "1777423717.666499"). Used by react, reactions, edit, delete, pin, and unpin actions. Not used by download-file, which requires fileId from event.files[].id.';
27+return {
28+messageId: Type.Optional(Type.String({ description })),
29+message_id: Type.Optional(Type.String({ description: `${description} Alias for messageId.` })),
30+};
31+}
32+533export function describeSlackMessageTool({
634 cfg,
735 accountId,
8-}: Parameters<NonNullable<ChannelMessageActionAdapter["describeMessageTool"]>>[0]) {
36+}: Parameters<
37+NonNullable<ChannelMessageActionAdapter["describeMessageTool"]>
38+>[0]): ChannelMessageToolDiscovery {
939const actions = listSlackMessageActions(cfg, accountId);
1040const capabilities = new Set<"presentation">();
41+const schema: ChannelMessageToolSchemaContribution[] = [];
1142if (actions.includes("send")) {
1243capabilities.add("presentation");
1344}
1445if (isSlackInteractiveRepliesEnabled({ cfg, accountId })) {
1546capabilities.add("presentation");
1647}
48+if (actions.includes("download-file")) {
49+schema.push({
50+properties: createSlackFileActionSchema(),
51+actions: ["download-file"],
52+});
53+}
54+const messageIdActions: ChannelMessageActionName[] = [];
55+for (const action of SLACK_MESSAGE_ID_ACTIONS) {
56+if (actions.includes(action)) {
57+messageIdActions.push(action);
58+}
59+}
60+if (messageIdActions.length > 0) {
61+schema.push({
62+properties: createSlackMessageIdActionSchema(),
63+actions: messageIdActions,
64+});
65+}
1766return {
1867 actions,
1968capabilities: Array.from(capabilities),
69+schema: schema.length > 0 ? schema : null,
2070};
2171}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。