Files
clawdbot/src/agents/tools/message-tool.ts
2026-01-09 06:44:20 +01:00

113 lines
3.7 KiB
TypeScript

import { Type } from "@sinclair/typebox";
import {
sendMessage,
sendPoll,
type MessagePollResult,
type MessageSendResult,
} from "../../infra/outbound/message.js";
import type { AnyAgentTool } from "./common.js";
import {
jsonResult,
readNumberParam,
readStringArrayParam,
readStringParam,
} from "./common.js";
const MessageToolSchema = Type.Object({
action: Type.Union([Type.Literal("send"), Type.Literal("poll")]),
to: Type.Optional(Type.String()),
content: Type.Optional(Type.String()),
mediaUrl: Type.Optional(Type.String()),
gifPlayback: Type.Optional(Type.Boolean()),
provider: Type.Optional(Type.String()),
accountId: Type.Optional(Type.String()),
dryRun: Type.Optional(Type.Boolean()),
bestEffort: Type.Optional(Type.Boolean()),
question: Type.Optional(Type.String()),
options: Type.Optional(Type.Array(Type.String())),
maxSelections: Type.Optional(Type.Number()),
durationHours: Type.Optional(Type.Number()),
gatewayUrl: Type.Optional(Type.String()),
gatewayToken: Type.Optional(Type.String()),
timeoutMs: Type.Optional(Type.Number()),
});
export function createMessageTool(): AnyAgentTool {
return {
label: "Message",
name: "message",
description:
"Send messages and polls across providers (send/poll). Prefer this for general outbound messaging.",
parameters: MessageToolSchema,
execute: async (_toolCallId, args) => {
const params = args as Record<string, unknown>;
const action = readStringParam(params, "action", { required: true });
const gateway = {
url: readStringParam(params, "gatewayUrl", { trim: false }),
token: readStringParam(params, "gatewayToken", { trim: false }),
timeoutMs: readNumberParam(params, "timeoutMs"),
clientName: "agent" as const,
mode: "agent" as const,
};
const dryRun = Boolean(params.dryRun);
if (action === "send") {
const to = readStringParam(params, "to", { required: true });
const content = readStringParam(params, "content", {
required: true,
allowEmpty: true,
});
const mediaUrl = readStringParam(params, "mediaUrl", { trim: false });
const provider = readStringParam(params, "provider");
const accountId = readStringParam(params, "accountId");
const gifPlayback =
typeof params.gifPlayback === "boolean" ? params.gifPlayback : false;
const bestEffort =
typeof params.bestEffort === "boolean" ? params.bestEffort : undefined;
const result: MessageSendResult = await sendMessage({
to,
content,
mediaUrl: mediaUrl || undefined,
provider: provider || undefined,
accountId: accountId || undefined,
gifPlayback,
dryRun,
bestEffort,
gateway,
});
return jsonResult(result);
}
if (action === "poll") {
const to = readStringParam(params, "to", { required: true });
const question = readStringParam(params, "question", { required: true });
const options =
readStringArrayParam(params, "options", { required: true }) ?? [];
const maxSelections = readNumberParam(params, "maxSelections", {
integer: true,
});
const durationHours = readNumberParam(params, "durationHours", {
integer: true,
});
const provider = readStringParam(params, "provider");
const result: MessagePollResult = await sendPoll({
to,
question,
options,
maxSelections,
durationHours,
provider: provider || undefined,
dryRun,
gateway,
});
return jsonResult(result);
}
throw new Error(`Unknown action: ${action}`);
},
};
}