@hasna/conversations 0.2.38 → 0.2.39

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.
package/bin/index.js CHANGED
@@ -14914,7 +14914,7 @@ var init_presence = __esm(() => {
14914
14914
  var require_package = __commonJS((exports, module) => {
14915
14915
  module.exports = {
14916
14916
  name: "@hasna/conversations",
14917
- version: "0.2.38",
14917
+ version: "0.2.39",
14918
14918
  description: "Real-time CLI messaging for AI agents",
14919
14919
  type: "module",
14920
14920
  bin: {
@@ -47026,6 +47026,98 @@ var init_cloud = __esm(() => {
47026
47026
  CONFLICT_TABLES = new Set(["spaces", "projects", "agent_presence"]);
47027
47027
  });
47028
47028
 
47029
+ // src/mcp/telegram-channel.ts
47030
+ async function telegramRequest(token, method, params) {
47031
+ const url2 = `https://api.telegram.org/bot${token}/${method}`;
47032
+ const res = await fetch(url2, {
47033
+ method: "POST",
47034
+ headers: { "Content-Type": "application/json" },
47035
+ body: params ? JSON.stringify(params) : undefined
47036
+ });
47037
+ const data = await res.json();
47038
+ if (!data.ok)
47039
+ throw new Error(`Telegram API error: ${data.description}`);
47040
+ return data.result;
47041
+ }
47042
+ function registerTelegramChannel(server) {
47043
+ const token = process.env.TELEGRAM_BOT_TOKEN;
47044
+ if (!token)
47045
+ return;
47046
+ let lastUpdateId = 0;
47047
+ let pollTimer = null;
47048
+ let botUsername = "bot";
47049
+ telegramRequest(token, "getMe").then((me) => {
47050
+ botUsername = me.username || me.first_name || "bot";
47051
+ console.error(`[telegram-channel] connected as @${botUsername}`);
47052
+ }).catch(() => {});
47053
+ server.registerTool("telegram_send", {
47054
+ description: "Send a message to a Telegram chat. Use this to reply to Telegram messages received via the channel bridge.",
47055
+ inputSchema: {
47056
+ chat_id: exports_external2.coerce.number().describe("Telegram chat ID to send to (from the incoming message's chat_id meta)"),
47057
+ text: exports_external2.string().describe("Message text to send"),
47058
+ parse_mode: exports_external2.string().optional().describe("Optional: HTML or MarkdownV2"),
47059
+ reply_to_message_id: exports_external2.coerce.number().optional().describe("Optional: message ID to reply to")
47060
+ }
47061
+ }, async (args) => {
47062
+ const result = await telegramRequest(token, "sendMessage", {
47063
+ chat_id: args.chat_id,
47064
+ text: args.text,
47065
+ parse_mode: args.parse_mode,
47066
+ reply_to_message_id: args.reply_to_message_id
47067
+ });
47068
+ return { content: [{ type: "text", text: JSON.stringify(result) }] };
47069
+ });
47070
+ function pushNotification(update) {
47071
+ const msg = update.message;
47072
+ if (!msg?.text)
47073
+ return;
47074
+ const from = msg.from?.username || msg.from?.first_name || "unknown";
47075
+ const chatTitle = msg.chat.title || msg.chat.username || String(msg.chat.id);
47076
+ const context = [
47077
+ `From: ${from}`,
47078
+ `Chat: ${chatTitle} (${msg.chat.id})`,
47079
+ `Message ID: ${msg.message_id}`,
47080
+ msg.chat.type !== "private" ? `Type: ${msg.chat.type}` : null
47081
+ ].filter(Boolean).join(" | ");
47082
+ const enrichedContent = `[${context}]
47083
+ ${msg.text}`;
47084
+ server.server.notification({
47085
+ method: "notifications/claude/channel",
47086
+ params: {
47087
+ content: enrichedContent,
47088
+ meta: {
47089
+ from,
47090
+ chat_id: String(msg.chat.id),
47091
+ message_id: String(msg.message_id),
47092
+ chat_type: msg.chat.type,
47093
+ ...msg.chat.title ? { chat_title: msg.chat.title } : {}
47094
+ }
47095
+ }
47096
+ }).catch(() => {});
47097
+ }
47098
+ async function poll() {
47099
+ try {
47100
+ const updates = await telegramRequest(token, "getUpdates", {
47101
+ offset: lastUpdateId + 1,
47102
+ timeout: 1,
47103
+ allowed_updates: ["message"]
47104
+ });
47105
+ for (const update of updates) {
47106
+ lastUpdateId = update.update_id;
47107
+ pushNotification(update);
47108
+ }
47109
+ } catch {}
47110
+ }
47111
+ setTimeout(() => {
47112
+ pollTimer = setInterval(() => poll(), POLL_INTERVAL_MS2);
47113
+ console.error("[telegram-channel] polling started");
47114
+ }, 2000);
47115
+ }
47116
+ var POLL_INTERVAL_MS2 = 2000;
47117
+ var init_telegram_channel = __esm(() => {
47118
+ init_zod2();
47119
+ });
47120
+
47029
47121
  // src/mcp/tools/tmux.ts
47030
47122
  function sleep2(ms) {
47031
47123
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -47166,6 +47258,7 @@ var init_mcp2 = __esm(() => {
47166
47258
  init_advanced();
47167
47259
  init_cloud();
47168
47260
  init_channel();
47261
+ init_telegram_channel();
47169
47262
  init_tmux2();
47170
47263
  import__package2 = __toESM(require_package(), 1);
47171
47264
  server = new McpServer({
@@ -47180,6 +47273,7 @@ var init_mcp2 = __esm(() => {
47180
47273
  registerAdvancedTools(server, import__package2.default.version);
47181
47274
  registerTmuxTools(server);
47182
47275
  registerChannelBridge(server);
47276
+ registerTelegramChannel(server);
47183
47277
  isDirectRun = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("mcp.js") || process.argv[1]?.endsWith("mcp.ts");
47184
47278
  if (isDirectRun) {
47185
47279
  startMcpServer().catch((error48) => {
package/bin/mcp.js CHANGED
@@ -44169,6 +44169,95 @@ function formatError2(e) {
44169
44169
  return String(e);
44170
44170
  }
44171
44171
 
44172
+ // src/mcp/telegram-channel.ts
44173
+ var POLL_INTERVAL_MS2 = 2000;
44174
+ async function telegramRequest(token, method, params) {
44175
+ const url2 = `https://api.telegram.org/bot${token}/${method}`;
44176
+ const res = await fetch(url2, {
44177
+ method: "POST",
44178
+ headers: { "Content-Type": "application/json" },
44179
+ body: params ? JSON.stringify(params) : undefined
44180
+ });
44181
+ const data = await res.json();
44182
+ if (!data.ok)
44183
+ throw new Error(`Telegram API error: ${data.description}`);
44184
+ return data.result;
44185
+ }
44186
+ function registerTelegramChannel(server) {
44187
+ const token = process.env.TELEGRAM_BOT_TOKEN;
44188
+ if (!token)
44189
+ return;
44190
+ let lastUpdateId = 0;
44191
+ let pollTimer = null;
44192
+ let botUsername = "bot";
44193
+ telegramRequest(token, "getMe").then((me) => {
44194
+ botUsername = me.username || me.first_name || "bot";
44195
+ console.error(`[telegram-channel] connected as @${botUsername}`);
44196
+ }).catch(() => {});
44197
+ server.registerTool("telegram_send", {
44198
+ description: "Send a message to a Telegram chat. Use this to reply to Telegram messages received via the channel bridge.",
44199
+ inputSchema: {
44200
+ chat_id: exports_external.coerce.number().describe("Telegram chat ID to send to (from the incoming message's chat_id meta)"),
44201
+ text: exports_external.string().describe("Message text to send"),
44202
+ parse_mode: exports_external.string().optional().describe("Optional: HTML or MarkdownV2"),
44203
+ reply_to_message_id: exports_external.coerce.number().optional().describe("Optional: message ID to reply to")
44204
+ }
44205
+ }, async (args) => {
44206
+ const result = await telegramRequest(token, "sendMessage", {
44207
+ chat_id: args.chat_id,
44208
+ text: args.text,
44209
+ parse_mode: args.parse_mode,
44210
+ reply_to_message_id: args.reply_to_message_id
44211
+ });
44212
+ return { content: [{ type: "text", text: JSON.stringify(result) }] };
44213
+ });
44214
+ function pushNotification(update) {
44215
+ const msg = update.message;
44216
+ if (!msg?.text)
44217
+ return;
44218
+ const from = msg.from?.username || msg.from?.first_name || "unknown";
44219
+ const chatTitle = msg.chat.title || msg.chat.username || String(msg.chat.id);
44220
+ const context = [
44221
+ `From: ${from}`,
44222
+ `Chat: ${chatTitle} (${msg.chat.id})`,
44223
+ `Message ID: ${msg.message_id}`,
44224
+ msg.chat.type !== "private" ? `Type: ${msg.chat.type}` : null
44225
+ ].filter(Boolean).join(" | ");
44226
+ const enrichedContent = `[${context}]
44227
+ ${msg.text}`;
44228
+ server.server.notification({
44229
+ method: "notifications/claude/channel",
44230
+ params: {
44231
+ content: enrichedContent,
44232
+ meta: {
44233
+ from,
44234
+ chat_id: String(msg.chat.id),
44235
+ message_id: String(msg.message_id),
44236
+ chat_type: msg.chat.type,
44237
+ ...msg.chat.title ? { chat_title: msg.chat.title } : {}
44238
+ }
44239
+ }
44240
+ }).catch(() => {});
44241
+ }
44242
+ async function poll() {
44243
+ try {
44244
+ const updates = await telegramRequest(token, "getUpdates", {
44245
+ offset: lastUpdateId + 1,
44246
+ timeout: 1,
44247
+ allowed_updates: ["message"]
44248
+ });
44249
+ for (const update of updates) {
44250
+ lastUpdateId = update.update_id;
44251
+ pushNotification(update);
44252
+ }
44253
+ } catch {}
44254
+ }
44255
+ setTimeout(() => {
44256
+ pollTimer = setInterval(() => poll(), POLL_INTERVAL_MS2);
44257
+ console.error("[telegram-channel] polling started");
44258
+ }, 2000);
44259
+ }
44260
+
44172
44261
  // src/cli/commands/tmux.ts
44173
44262
  import { execSync } from "child_process";
44174
44263
  function sleep(ms) {
@@ -44317,7 +44406,7 @@ function registerTmuxTools(server) {
44317
44406
  // package.json
44318
44407
  var package_default = {
44319
44408
  name: "@hasna/conversations",
44320
- version: "0.2.38",
44409
+ version: "0.2.39",
44321
44410
  description: "Real-time CLI messaging for AI agents",
44322
44411
  type: "module",
44323
44412
  bin: {
@@ -44421,6 +44510,7 @@ registerAgentTools(server, agentFocus, getAgentFocus);
44421
44510
  registerAdvancedTools(server, package_default.version);
44422
44511
  registerTmuxTools(server);
44423
44512
  registerChannelBridge(server);
44513
+ registerTelegramChannel(server);
44424
44514
  async function startMcpServer() {
44425
44515
  const transport = new StdioServerTransport;
44426
44516
  registerCloudSyncTools(server);
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Telegram channel bridge for conversations MCP server.
3
+ *
4
+ * Polls a Telegram bot for new messages and pushes them as
5
+ * `notifications/claude/channel` events. Also registers a
6
+ * `telegram_send` tool for replying.
7
+ *
8
+ * Requires: TELEGRAM_BOT_TOKEN env var or connect-telegram profile.
9
+ *
10
+ * Usage: Set TELEGRAM_BOT_TOKEN and the bridge auto-starts.
11
+ */
12
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13
+ export declare function registerTelegramChannel(server: McpServer): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/conversations",
3
- "version": "0.2.38",
3
+ "version": "0.2.39",
4
4
  "description": "Real-time CLI messaging for AI agents",
5
5
  "type": "module",
6
6
  "bin": {