KeiSeiKit-1.0/_ts_packages/packages/telegram-adapter/src/tools.ts
Parfii-bot 0be354a920 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

112 lines
3.6 KiB
TypeScript

// Tool definitions for the Telegram adapter. Each tool is a small wrapper
// around TelegramClient + a zod schema, returning a string to MCP.
import { z } from "zod";
import { TelegramClient } from "./client.js";
import {
ChatInfoArgs,
SendFileArgs,
SendTextArgs,
SendVoiceArgs,
} from "./types.js";
export interface TelegramTool {
name: string;
description: string;
inputSchema: z.ZodObject<Record<string, z.ZodTypeAny>>;
handler: (args: Record<string, unknown>) => Promise<string>;
}
export function buildTelegramTools(client: TelegramClient): TelegramTool[] {
return [
{
name: "telegram_status",
description: "Telegram bot identity and connectivity.",
inputSchema: z.object({}),
handler: async () => {
const s = await client.status();
return `bot=@${s.username} id=${s.id}`;
},
},
{
name: "telegram_groups",
description: "List groups the bot has observed.",
inputSchema: z.object({}),
handler: async () => {
const gs = client.listGroups();
if (gs.length === 0) return "No groups tracked yet.";
return gs.map((g) => `${g.chatId} | ${g.title} [${g.type}]`).join("\n");
},
},
{
name: "telegram_contacts",
description: "List known Telegram contacts.",
inputSchema: z.object({}),
handler: async () => {
const cs = client.listContacts();
if (cs.length === 0) return "No contacts yet.";
return cs.map(formatContact).join("\n");
},
},
{
name: "telegram_chat_info",
description: "Chat metadata for a given chat ID or @username.",
inputSchema: ChatInfoArgs,
handler: async (raw) => {
const args = ChatInfoArgs.parse(raw);
const info = await client.chatInfo(args.chat);
return `id=${info.id}\ntitle=${info.title}\ntype=${info.type}`;
},
},
{
name: "telegram_send",
description: "Send a text message.",
inputSchema: SendTextArgs,
handler: async (raw) => {
const args = SendTextArgs.parse(raw);
const id = await client.sendText(args.chat, args.text);
return `sent message_id=${id}`;
},
},
{
name: "telegram_send_file",
description: "Send a document, photo, or video file.",
inputSchema: SendFileArgs,
handler: async (raw) => {
const args = SendFileArgs.parse(raw);
const id = await dispatchFile(client, args);
return `sent ${args.kind} message_id=${id}`;
},
},
{
name: "telegram_send_voice",
description: "Send a pre-recorded voice note file.",
inputSchema: SendVoiceArgs,
handler: async (raw) => {
const args = SendVoiceArgs.parse(raw);
const id = await client.sendVoice(args.chat, args.file, args.caption);
return `sent voice message_id=${id}`;
},
},
];
}
function formatContact(c: {
userId: number;
firstName: string;
lastName?: string | undefined;
username?: string | undefined;
}): string {
const name = c.lastName ? `${c.firstName} ${c.lastName}` : c.firstName;
const handle = c.username ? ` @${c.username}` : "";
return `${c.userId} | ${name}${handle}`;
}
async function dispatchFile(
client: TelegramClient,
args: { chat: string | number; file: string; kind: "document" | "photo" | "video"; caption?: string | undefined },
): Promise<number> {
if (args.kind === "photo") return client.sendPhoto(args.chat, args.file, args.caption);
if (args.kind === "video") return client.sendVideo(args.chat, args.file, args.caption);
return client.sendDocument(args.chat, args.file, args.caption);
}