@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 +95 -1
- package/bin/mcp.js +91 -1
- package/dist/mcp/telegram-channel.d.ts +13 -0
- package/package.json +1 -1
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.
|
|
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.
|
|
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;
|