volute 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +7 -7
  2. package/dist/{channel-7FZ6D25H.js → channel-DQ6UY7QB.js} +16 -39
  3. package/dist/chunk-5OCWMTVS.js +152 -0
  4. package/dist/chunk-MXUCNIBG.js +168 -0
  5. package/dist/{chunk-N4YNKR3Q.js → chunk-ZHCE4DPY.js} +20 -0
  6. package/dist/cli.js +29 -18
  7. package/dist/connector-DKDJTLYZ.js +152 -0
  8. package/dist/connectors/discord.js +102 -161
  9. package/dist/connectors/slack.js +170 -0
  10. package/dist/connectors/telegram.js +156 -0
  11. package/dist/daemon.js +262 -142
  12. package/dist/{import-K4MP2GX7.js → import-4CI2ZUTJ.js} +15 -0
  13. package/dist/package-Z2SFO2SV.js +89 -0
  14. package/dist/{send-UK3JBZIB.js → send-3U6OTKG7.js} +6 -2
  15. package/dist/web-assets/assets/{index-BC5eSqbY.js → index-NS621maO.js} +23 -23
  16. package/dist/web-assets/index.html +1 -1
  17. package/package.json +3 -1
  18. package/templates/_base/_skills/volute-agent/SKILL.md +3 -3
  19. package/templates/_base/home/VOLUTE.md +18 -6
  20. package/templates/_base/src/lib/file-handler.ts +46 -0
  21. package/templates/_base/src/lib/router.ts +180 -0
  22. package/templates/_base/src/lib/routing.ts +100 -0
  23. package/templates/_base/src/lib/types.ts +13 -2
  24. package/templates/_base/src/lib/volute-server.ts +20 -48
  25. package/templates/agent-sdk/src/agent.ts +268 -82
  26. package/templates/agent-sdk/src/server.ts +12 -3
  27. package/templates/pi/src/agent.ts +277 -58
  28. package/templates/pi/src/server.ts +15 -4
  29. package/dist/connector-TVJULIRT.js +0 -96
  30. package/templates/_base/src/lib/sessions.ts +0 -71
  31. package/templates/agent-sdk/src/lib/agent-sessions.ts +0 -204
  32. package/templates/pi/src/lib/agent-sessions.ts +0 -210
  33. package/dist/{create-BRG2DBWI.js → create-ILVOG75A.js} +3 -3
  34. package/dist/{delete-GQ7JEK2S.js → delete-55MXCEY5.js} +3 -3
  35. package/dist/{history-3VRUBGGV.js → history-BKG74I43.js} +3 -3
  36. package/dist/{schedule-4I5TYHFH.js → schedule-A35SH4HT.js} +3 -3
  37. package/dist/{setup-SRS7AUAA.js → setup-2FDVN7OF.js} +3 -3
  38. package/dist/{up-UT3IMKCA.js → up-F7TMTLRE.js} +0 -0
  39. package/dist/{upgrade-CDKECCGN.js → upgrade-6ZW2RD64.js} +3 -3
  40. package/dist/{variant-CVYM3EQG.js → variant-T64BKARF.js} +6 -6
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ fireAndForget,
4
+ handleAgentMessage,
5
+ loadEnv,
6
+ loadFollowedChannels,
7
+ splitMessage
8
+ } from "../chunk-MXUCNIBG.js";
9
+ import "../chunk-K3NQKI34.js";
10
+
11
+ // src/connectors/telegram.ts
12
+ import { Input, Telegraf } from "telegraf";
13
+ import { message } from "telegraf/filters";
14
+ var TELEGRAM_MAX_LENGTH = 4096;
15
+ var TYPING_INTERVAL_MS = 5e3;
16
+ var env = loadEnv();
17
+ var botToken = process.env.TELEGRAM_BOT_TOKEN;
18
+ if (!botToken) {
19
+ console.error("Missing required env var: TELEGRAM_BOT_TOKEN");
20
+ process.exit(1);
21
+ }
22
+ var followedChatIds = loadFollowedChannels(env, "telegram");
23
+ var followedChatIdSet = new Set(followedChatIds.map(String));
24
+ var bot = new Telegraf(botToken);
25
+ bot.on(message("text"), async (ctx) => {
26
+ if (ctx.message.from.is_bot) return;
27
+ const isDM = ctx.chat.type === "private";
28
+ const botUsername = ctx.botInfo.username;
29
+ const isMentioned = !isDM && ctx.message.entities?.some(
30
+ (e) => e.type === "mention" && ctx.message.text.substring(e.offset, e.offset + e.length) === `@${botUsername}`
31
+ );
32
+ const isFollowedChat = !isDM && followedChatIdSet.has(String(ctx.chat.id));
33
+ if (!isDM && !isMentioned && !isFollowedChat) return;
34
+ let text = ctx.message.text;
35
+ if (isMentioned && botUsername) {
36
+ text = text.replace(new RegExp(`@${botUsername}`, "g"), "").trim();
37
+ }
38
+ const content = [];
39
+ if (text) content.push({ type: "text", text });
40
+ if (content.length === 0) return;
41
+ const senderName = ctx.message.from.first_name + (ctx.message.from.last_name ? ` ${ctx.message.from.last_name}` : "");
42
+ const chatTitle = "title" in ctx.chat ? ctx.chat.title : void 0;
43
+ const payload = {
44
+ content,
45
+ channel: `telegram:${ctx.chat.id}`,
46
+ sender: senderName,
47
+ platform: "Telegram",
48
+ ...isDM ? { isDM: true } : {},
49
+ ...chatTitle ? { channelName: chatTitle } : {}
50
+ };
51
+ if (isFollowedChat && !isMentioned) {
52
+ await fireAndForget(env, payload);
53
+ return;
54
+ }
55
+ await handleTelegramMessage(
56
+ ctx.chat.id,
57
+ payload,
58
+ (text2) => ctx.reply(text2),
59
+ (source) => ctx.replyWithPhoto(source)
60
+ );
61
+ });
62
+ bot.on(message("photo"), async (ctx) => {
63
+ if (ctx.message.from.is_bot) return;
64
+ const isDM = ctx.chat.type === "private";
65
+ const isFollowedChat = !isDM && followedChatIdSet.has(String(ctx.chat.id));
66
+ if (!isDM && !isFollowedChat) return;
67
+ const content = [];
68
+ const caption = ctx.message.caption;
69
+ if (caption) content.push({ type: "text", text: caption });
70
+ const photos = ctx.message.photo;
71
+ const largest = photos[photos.length - 1];
72
+ try {
73
+ const fileUrl = await ctx.telegram.getFileLink(largest.file_id);
74
+ const res = await fetch(fileUrl.href);
75
+ if (!res.ok) {
76
+ console.error(`Failed to download photo: HTTP ${res.status}`);
77
+ } else {
78
+ const buffer = Buffer.from(await res.arrayBuffer());
79
+ content.push({
80
+ type: "image",
81
+ media_type: "image/jpeg",
82
+ data: buffer.toString("base64")
83
+ });
84
+ }
85
+ } catch (err) {
86
+ console.error(`Failed to download photo: ${err}`);
87
+ }
88
+ if (content.length === 0) return;
89
+ const senderName = ctx.message.from.first_name + (ctx.message.from.last_name ? ` ${ctx.message.from.last_name}` : "");
90
+ const chatTitle = "title" in ctx.chat ? ctx.chat.title : void 0;
91
+ const payload = {
92
+ content,
93
+ channel: `telegram:${ctx.chat.id}`,
94
+ sender: senderName,
95
+ platform: "Telegram",
96
+ ...chatTitle ? { channelName: chatTitle } : {}
97
+ };
98
+ if (isFollowedChat) {
99
+ await fireAndForget(env, payload);
100
+ return;
101
+ }
102
+ await handleTelegramMessage(
103
+ ctx.chat.id,
104
+ payload,
105
+ (text) => ctx.reply(text),
106
+ (source) => ctx.replyWithPhoto(source)
107
+ );
108
+ });
109
+ async function handleTelegramMessage(chatId, payload, reply, replyWithPhoto) {
110
+ const typingInterval = setInterval(() => {
111
+ bot.telegram.sendChatAction(chatId, "typing").catch(() => {
112
+ });
113
+ }, TYPING_INTERVAL_MS);
114
+ bot.telegram.sendChatAction(chatId, "typing").catch(() => {
115
+ });
116
+ try {
117
+ await handleAgentMessage(env, payload, {
118
+ onFlush: async (text, images) => {
119
+ for (const img of images) {
120
+ try {
121
+ await replyWithPhoto(Input.fromBuffer(Buffer.from(img.data, "base64")));
122
+ } catch (err) {
123
+ console.error(`Failed to send image: ${err}`);
124
+ }
125
+ }
126
+ if (!text) return;
127
+ const chunks = splitMessage(text, TELEGRAM_MAX_LENGTH);
128
+ for (const chunk of chunks) {
129
+ try {
130
+ await reply(chunk);
131
+ } catch (err) {
132
+ console.error(`Failed to send message: ${err}`);
133
+ }
134
+ }
135
+ },
136
+ onError: async (msg) => {
137
+ await reply(msg).catch(() => {
138
+ });
139
+ }
140
+ });
141
+ } finally {
142
+ clearInterval(typingInterval);
143
+ }
144
+ }
145
+ bot.launch().then(() => {
146
+ console.log(`Connected to Telegram as @${bot.botInfo?.username}`);
147
+ console.log(`Bridging to agent: ${env.agentName} via ${env.baseUrl}/message`);
148
+ if (followedChatIds.length > 0) {
149
+ console.log(`Following chats: ${followedChatIds.join(", ")}`);
150
+ }
151
+ }).catch((err) => {
152
+ console.error("Failed to start Telegram connector:", err);
153
+ process.exit(1);
154
+ });
155
+ process.once("SIGINT", () => bot.stop("SIGINT"));
156
+ process.once("SIGTERM", () => bot.stop("SIGTERM"));