@agentick/connector-telegram 0.8.0 → 0.9.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.
- package/dist/confirmation-utils.d.ts +19 -0
- package/dist/confirmation-utils.d.ts.map +1 -0
- package/dist/confirmation-utils.js +41 -0
- package/dist/confirmation-utils.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/telegram-plugin.d.ts +46 -0
- package/dist/telegram-plugin.d.ts.map +1 -0
- package/dist/telegram-plugin.js +187 -0
- package/dist/telegram-plugin.js.map +1 -0
- package/package.json +4 -4
- package/dist/telegram-platform.d.ts +0 -47
- package/dist/telegram-platform.d.ts.map +0 -1
- package/dist/telegram-platform.js +0 -161
- package/dist/telegram-platform.js.map +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ToolConfirmationResponse } from "@agentick/shared";
|
|
2
|
+
/**
|
|
3
|
+
* Parse a natural language confirmation response.
|
|
4
|
+
*
|
|
5
|
+
* Accepts common affirmative phrases ("yes", "y", "ok", "go ahead", "do it")
|
|
6
|
+
* and treats everything else as denial. The full text is always passed as
|
|
7
|
+
* `reason` so the model can interpret nuanced responses like
|
|
8
|
+
* "yes but skip the tests".
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseTextConfirmation(text: string): ToolConfirmationResponse;
|
|
11
|
+
/**
|
|
12
|
+
* Format a tool confirmation request as a human-readable message.
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatConfirmationMessage(request: {
|
|
15
|
+
name: string;
|
|
16
|
+
message?: string;
|
|
17
|
+
arguments: Record<string, unknown>;
|
|
18
|
+
}): string;
|
|
19
|
+
//# sourceMappingURL=confirmation-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirmation-utils.d.ts","sourceRoot":"","sources":["../src/confirmation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAEjE;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB,CAgB5E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,GAAG,MAAM,CAcT"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a natural language confirmation response.
|
|
3
|
+
*
|
|
4
|
+
* Accepts common affirmative phrases ("yes", "y", "ok", "go ahead", "do it")
|
|
5
|
+
* and treats everything else as denial. The full text is always passed as
|
|
6
|
+
* `reason` so the model can interpret nuanced responses like
|
|
7
|
+
* "yes but skip the tests".
|
|
8
|
+
*/
|
|
9
|
+
export function parseTextConfirmation(text) {
|
|
10
|
+
const lower = text.trim().toLowerCase();
|
|
11
|
+
const approved = lower === "yes" ||
|
|
12
|
+
lower === "y" ||
|
|
13
|
+
lower === "ok" ||
|
|
14
|
+
lower === "approve" ||
|
|
15
|
+
lower === "go" ||
|
|
16
|
+
lower === "go ahead" ||
|
|
17
|
+
lower === "do it" ||
|
|
18
|
+
lower.startsWith("yes ");
|
|
19
|
+
return {
|
|
20
|
+
approved,
|
|
21
|
+
reason: text.trim(),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Format a tool confirmation request as a human-readable message.
|
|
26
|
+
*/
|
|
27
|
+
export function formatConfirmationMessage(request) {
|
|
28
|
+
const msg = request.message ?? `Allow ${request.name} to execute?`;
|
|
29
|
+
const args = Object.entries(request.arguments);
|
|
30
|
+
if (args.length === 0)
|
|
31
|
+
return msg;
|
|
32
|
+
const argSummary = args
|
|
33
|
+
.map(([k, v]) => {
|
|
34
|
+
const val = typeof v === "string" ? v : JSON.stringify(v);
|
|
35
|
+
const short = val.length > 80 ? val.slice(0, 80) + "..." : val;
|
|
36
|
+
return ` ${k}: ${short}`;
|
|
37
|
+
})
|
|
38
|
+
.join("\n");
|
|
39
|
+
return `${msg}\n\n${argSummary}`;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=confirmation-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirmation-utils.js","sourceRoot":"","sources":["../src/confirmation-utils.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,QAAQ,GACZ,KAAK,KAAK,KAAK;QACf,KAAK,KAAK,GAAG;QACb,KAAK,KAAK,IAAI;QACd,KAAK,KAAK,SAAS;QACnB,KAAK,KAAK,IAAI;QACd,KAAK,KAAK,UAAU;QACpB,KAAK,KAAK,OAAO;QACjB,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAE3B,OAAO;QACL,QAAQ;QACR,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE;KACpB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAIzC;IACC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,OAAO,CAAC,IAAI,cAAc,CAAC;IACnE,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAElC,MAAM,UAAU,GAAG,IAAI;SACpB,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;QACd,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;QAC/D,OAAO,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC;IAC5B,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,GAAG,GAAG,OAAO,UAAU,EAAE,CAAC;AACnC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { TelegramPlugin, type TelegramPluginOptions } from "./telegram-plugin.js";
|
|
2
2
|
export { escapeMarkdownV2 } from "./telegram-format.js";
|
|
3
|
+
export { parseTextConfirmation, formatConfirmationMessage } from "./confirmation-utils.js";
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { TelegramPlugin } from "./telegram-plugin.js";
|
|
2
2
|
export { escapeMarkdownV2 } from "./telegram-format.js";
|
|
3
|
+
export { parseTextConfirmation, formatConfirmationMessage } from "./confirmation-utils.js";
|
|
3
4
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { GatewayPlugin, PluginContext } from "@agentick/gateway";
|
|
2
|
+
export interface TelegramPluginOptions {
|
|
3
|
+
/** Telegram bot token. */
|
|
4
|
+
token: string;
|
|
5
|
+
/** Whitelist of allowed Telegram user IDs. Empty = allow all. */
|
|
6
|
+
allowedUsers?: number[];
|
|
7
|
+
/** Specific chat ID to use. If omitted, auto-detects from first message. */
|
|
8
|
+
chatId?: number;
|
|
9
|
+
/** How to present tool confirmations. Default: "inline-keyboard". */
|
|
10
|
+
confirmationStyle?: "inline-keyboard" | "text";
|
|
11
|
+
/** Session key pattern. Default: "default:telegram-{chatId}" */
|
|
12
|
+
sessionKeyPattern?: (chatId: number) => string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Telegram gateway plugin.
|
|
16
|
+
*
|
|
17
|
+
* Bridges a Telegram bot to agent sessions via the gateway plugin system.
|
|
18
|
+
* Receives messages from Telegram, routes them to sessions via
|
|
19
|
+
* `PluginContext.sendToSession()`, and delivers responses back.
|
|
20
|
+
* Tool confirmations are presented as inline keyboards or text prompts.
|
|
21
|
+
*
|
|
22
|
+
* Registers a `telegram:send` method for outbound messaging from tool handlers.
|
|
23
|
+
*/
|
|
24
|
+
export declare class TelegramPlugin implements GatewayPlugin {
|
|
25
|
+
readonly id = "telegram";
|
|
26
|
+
private readonly _bot;
|
|
27
|
+
private readonly _options;
|
|
28
|
+
private readonly _allowedUsers;
|
|
29
|
+
private readonly _confirmationStyle;
|
|
30
|
+
private _ctx;
|
|
31
|
+
private _chatId;
|
|
32
|
+
/** Pending inline-keyboard confirmations keyed by toolUseId. */
|
|
33
|
+
private _pendingKeyboardConfirmations;
|
|
34
|
+
/** Pending text-based confirmation (only one at a time). */
|
|
35
|
+
private _pendingTextConfirmation;
|
|
36
|
+
constructor(options: TelegramPluginOptions);
|
|
37
|
+
initialize(ctx: PluginContext): Promise<void>;
|
|
38
|
+
destroy(): Promise<void>;
|
|
39
|
+
private _sessionKey;
|
|
40
|
+
private _setupMessageHandler;
|
|
41
|
+
private _setupCallbackHandler;
|
|
42
|
+
/** Core event loop: observe execution, deliver response, handle confirmations */
|
|
43
|
+
private _processEvents;
|
|
44
|
+
private _handleConfirmation;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=telegram-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram-plugin.d.ts","sourceRoot":"","sources":["../src/telegram-plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAWtE,MAAM,WAAW,qBAAqB;IACpC,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IAC/C,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CAChD;AAED;;;;;;;;;GASG;AACH,qBAAa,cAAe,YAAW,aAAa;IAClD,QAAQ,CAAC,EAAE,cAAc;IAEzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAChE,OAAO,CAAC,IAAI,CAA8B;IAC1C,OAAO,CAAC,OAAO,CAAgB;IAE/B,gEAAgE;IAChE,OAAO,CAAC,6BAA6B,CAGjC;IAEJ,4DAA4D;IAC5D,OAAO,CAAC,wBAAwB,CAGhB;gBAEJ,OAAO,EAAE,qBAAqB;IAQpC,UAAU,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,oBAAoB;IA4C5B,OAAO,CAAC,qBAAqB;IAiC7B,iFAAiF;YACnE,cAAc;YAsCd,mBAAmB;CAiClC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { Bot, InlineKeyboard } from "grammy";
|
|
2
|
+
import { splitMessage } from "@agentick/shared";
|
|
3
|
+
import { parseTextConfirmation, formatConfirmationMessage } from "./confirmation-utils.js";
|
|
4
|
+
const TELEGRAM_MAX_LENGTH = 4096;
|
|
5
|
+
/**
|
|
6
|
+
* Telegram gateway plugin.
|
|
7
|
+
*
|
|
8
|
+
* Bridges a Telegram bot to agent sessions via the gateway plugin system.
|
|
9
|
+
* Receives messages from Telegram, routes them to sessions via
|
|
10
|
+
* `PluginContext.sendToSession()`, and delivers responses back.
|
|
11
|
+
* Tool confirmations are presented as inline keyboards or text prompts.
|
|
12
|
+
*
|
|
13
|
+
* Registers a `telegram:send` method for outbound messaging from tool handlers.
|
|
14
|
+
*/
|
|
15
|
+
export class TelegramPlugin {
|
|
16
|
+
id = "telegram";
|
|
17
|
+
_bot;
|
|
18
|
+
_options;
|
|
19
|
+
_allowedUsers;
|
|
20
|
+
_confirmationStyle;
|
|
21
|
+
_ctx = null;
|
|
22
|
+
_chatId;
|
|
23
|
+
/** Pending inline-keyboard confirmations keyed by toolUseId. */
|
|
24
|
+
_pendingKeyboardConfirmations = new Map();
|
|
25
|
+
/** Pending text-based confirmation (only one at a time). */
|
|
26
|
+
_pendingTextConfirmation = null;
|
|
27
|
+
constructor(options) {
|
|
28
|
+
this._bot = new Bot(options.token);
|
|
29
|
+
this._options = options;
|
|
30
|
+
this._allowedUsers = new Set(options.allowedUsers ?? []);
|
|
31
|
+
this._chatId = options.chatId ?? null;
|
|
32
|
+
this._confirmationStyle = options.confirmationStyle ?? "inline-keyboard";
|
|
33
|
+
}
|
|
34
|
+
async initialize(ctx) {
|
|
35
|
+
this._ctx = ctx;
|
|
36
|
+
// Register outbound method: telegram:send
|
|
37
|
+
ctx.registerMethod("telegram:send", async (params) => {
|
|
38
|
+
const { chatId: explicitChatId, text } = params;
|
|
39
|
+
const chatId = explicitChatId ?? this._chatId;
|
|
40
|
+
if (!chatId)
|
|
41
|
+
throw new Error("No chatId available");
|
|
42
|
+
if (!text)
|
|
43
|
+
throw new Error("text is required");
|
|
44
|
+
const chunks = splitMessage(text, { maxLength: TELEGRAM_MAX_LENGTH });
|
|
45
|
+
for (const chunk of chunks) {
|
|
46
|
+
await this._bot.api.sendMessage(chatId, chunk);
|
|
47
|
+
}
|
|
48
|
+
return { ok: true, chatId };
|
|
49
|
+
});
|
|
50
|
+
// Set up grammy handlers
|
|
51
|
+
this._setupMessageHandler();
|
|
52
|
+
this._setupCallbackHandler();
|
|
53
|
+
// Validate token (fails fast on 401)
|
|
54
|
+
await this._bot.api.getMe();
|
|
55
|
+
// Start long polling (fire-and-forget)
|
|
56
|
+
this._bot.start().catch((err) => {
|
|
57
|
+
console.error("Telegram plugin polling error:", err);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async destroy() {
|
|
61
|
+
await this._bot.stop();
|
|
62
|
+
this._ctx = null;
|
|
63
|
+
this._pendingKeyboardConfirmations.clear();
|
|
64
|
+
this._pendingTextConfirmation = null;
|
|
65
|
+
}
|
|
66
|
+
_sessionKey(chatId) {
|
|
67
|
+
return this._options.sessionKeyPattern?.(chatId) ?? `default:telegram-${chatId}`;
|
|
68
|
+
}
|
|
69
|
+
_setupMessageHandler() {
|
|
70
|
+
this._bot.on("message:text", async (tgCtx) => {
|
|
71
|
+
const userId = tgCtx.from.id;
|
|
72
|
+
const chatId = tgCtx.chat.id;
|
|
73
|
+
if (this._allowedUsers.size > 0 && !this._allowedUsers.has(userId))
|
|
74
|
+
return;
|
|
75
|
+
if (this._chatId === null)
|
|
76
|
+
this._chatId = chatId;
|
|
77
|
+
if (chatId !== this._chatId)
|
|
78
|
+
return;
|
|
79
|
+
const text = tgCtx.message.text;
|
|
80
|
+
// Handle pending text confirmation
|
|
81
|
+
if (this._pendingTextConfirmation) {
|
|
82
|
+
const { sessionKey, callId } = this._pendingTextConfirmation;
|
|
83
|
+
this._pendingTextConfirmation = null;
|
|
84
|
+
const response = parseTextConfirmation(text);
|
|
85
|
+
await this._ctx.respondToConfirmation(sessionKey, callId, response);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Send to session and observe response
|
|
89
|
+
const sessionKey = this._sessionKey(chatId);
|
|
90
|
+
this._bot.api.sendChatAction(chatId, "typing").catch(() => { });
|
|
91
|
+
try {
|
|
92
|
+
const events = await this._ctx.sendToSession(sessionKey, {
|
|
93
|
+
messages: [
|
|
94
|
+
{
|
|
95
|
+
role: "user",
|
|
96
|
+
content: [{ type: "text", text }],
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
// Iterate events in background — deliver response + handle confirmations
|
|
101
|
+
this._processEvents(sessionKey, chatId, events).catch((err) => {
|
|
102
|
+
console.error("Telegram event processing error:", err);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
console.error("Telegram sendToSession error:", err);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
_setupCallbackHandler() {
|
|
111
|
+
this._bot.on("callback_query:data", async (tgCtx) => {
|
|
112
|
+
const data = tgCtx.callbackQuery.data;
|
|
113
|
+
if (!data.startsWith("confirm:"))
|
|
114
|
+
return;
|
|
115
|
+
// Always answer to dismiss the loading spinner (even on double-click race)
|
|
116
|
+
await tgCtx.answerCallbackQuery();
|
|
117
|
+
// Parse confirm:<callId>:<action> — callId may contain colons
|
|
118
|
+
const lastColon = data.lastIndexOf(":");
|
|
119
|
+
const callId = data.slice(8, lastColon); // 8 = "confirm:".length
|
|
120
|
+
const action = data.slice(lastColon + 1);
|
|
121
|
+
const pending = this._pendingKeyboardConfirmations.get(callId);
|
|
122
|
+
if (!pending)
|
|
123
|
+
return; // Stale or already resolved — graceful no-op
|
|
124
|
+
this._pendingKeyboardConfirmations.delete(callId);
|
|
125
|
+
const approved = action === "approve";
|
|
126
|
+
const response = { approved };
|
|
127
|
+
await this._ctx.respondToConfirmation(pending.sessionKey, callId, response);
|
|
128
|
+
try {
|
|
129
|
+
await tgCtx.editMessageText(`${pending.messageText}\n\n${approved ? "Approved" : "Denied"}`);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// Message may have been deleted
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/** Core event loop: observe execution, deliver response, handle confirmations */
|
|
137
|
+
async _processEvents(sessionKey, chatId, events) {
|
|
138
|
+
let responseText = "";
|
|
139
|
+
for await (const event of events) {
|
|
140
|
+
switch (event.type) {
|
|
141
|
+
case "content_delta":
|
|
142
|
+
if ("blockType" in event && event.blockType === "text" && "delta" in event) {
|
|
143
|
+
responseText += event.delta;
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
case "tool_confirmation_required":
|
|
147
|
+
await this._handleConfirmation(sessionKey, chatId, event);
|
|
148
|
+
break;
|
|
149
|
+
case "tick_start":
|
|
150
|
+
this._bot.api.sendChatAction(chatId, "typing").catch(() => { });
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Deliver accumulated response
|
|
155
|
+
if (responseText.trim()) {
|
|
156
|
+
const chunks = splitMessage(responseText.trim(), { maxLength: TELEGRAM_MAX_LENGTH });
|
|
157
|
+
for (const chunk of chunks) {
|
|
158
|
+
await this._bot.api.sendMessage(chatId, chunk);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async _handleConfirmation(sessionKey, chatId, event) {
|
|
163
|
+
const text = formatConfirmationMessage({
|
|
164
|
+
name: event.name,
|
|
165
|
+
message: event.message,
|
|
166
|
+
arguments: event.input,
|
|
167
|
+
});
|
|
168
|
+
if (this._confirmationStyle === "inline-keyboard") {
|
|
169
|
+
this._pendingKeyboardConfirmations.set(event.callId, {
|
|
170
|
+
sessionKey,
|
|
171
|
+
callId: event.callId,
|
|
172
|
+
messageText: text,
|
|
173
|
+
});
|
|
174
|
+
const keyboard = new InlineKeyboard()
|
|
175
|
+
.text("Approve", `confirm:${event.callId}:approve`)
|
|
176
|
+
.text("Deny", `confirm:${event.callId}:deny`);
|
|
177
|
+
await this._bot.api.sendMessage(chatId, text, {
|
|
178
|
+
reply_markup: keyboard,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
this._pendingTextConfirmation = { sessionKey, callId: event.callId };
|
|
183
|
+
await this._bot.api.sendMessage(chatId, `${text}\n\nReply yes/no (or explain what you'd like instead)`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=telegram-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram-plugin.js","sourceRoot":"","sources":["../src/telegram-plugin.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentick/connector-telegram",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Telegram
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Telegram plugin for Agentick gateway — bridge Telegram bots to agent sessions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
7
7
|
"ai",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@agentick/
|
|
35
|
-
"@agentick/shared": "0.
|
|
34
|
+
"@agentick/gateway": "0.9.0",
|
|
35
|
+
"@agentick/shared": "0.9.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"grammy": "^1.35.0",
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { ConnectorPlatform, ConnectorBridge, ConnectorStatus } from "@agentick/connector";
|
|
2
|
-
declare module "@agentick/shared" {
|
|
3
|
-
interface MessageSourceTypes {
|
|
4
|
-
telegram: {
|
|
5
|
-
type: "telegram";
|
|
6
|
-
chatId: number;
|
|
7
|
-
userId?: number;
|
|
8
|
-
username?: string;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
export interface TelegramConnectorOptions {
|
|
13
|
-
/** Telegram bot token. */
|
|
14
|
-
token: string;
|
|
15
|
-
/** Whitelist of allowed Telegram user IDs. Empty = allow all. */
|
|
16
|
-
allowedUsers?: number[];
|
|
17
|
-
/** Specific chat ID to use. If omitted, auto-detects from first message. */
|
|
18
|
-
chatId?: number;
|
|
19
|
-
/** How to present tool confirmations. Default: "inline-keyboard". */
|
|
20
|
-
confirmationStyle?: "inline-keyboard" | "text";
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Telegram platform adapter for the Agentick connector system.
|
|
24
|
-
*
|
|
25
|
-
* Receives messages from a Telegram bot and delivers agent responses
|
|
26
|
-
* back as Telegram messages. Tool confirmations can use inline keyboards
|
|
27
|
-
* or text-based confirmation.
|
|
28
|
-
*/
|
|
29
|
-
export declare class TelegramPlatform implements ConnectorPlatform {
|
|
30
|
-
private readonly _bot;
|
|
31
|
-
private readonly _allowedUsers;
|
|
32
|
-
private readonly _confirmationStyle;
|
|
33
|
-
private _chatId;
|
|
34
|
-
private _bridge;
|
|
35
|
-
private _status;
|
|
36
|
-
/** Pending inline-keyboard confirmations keyed by toolUseId. */
|
|
37
|
-
private _pendingKeyboardConfirmations;
|
|
38
|
-
/** Pending text-based confirmation (only one at a time). */
|
|
39
|
-
private _pendingTextConfirmation;
|
|
40
|
-
constructor(options: TelegramConnectorOptions);
|
|
41
|
-
get status(): ConnectorStatus;
|
|
42
|
-
start(bridge: ConnectorBridge): Promise<void>;
|
|
43
|
-
stop(): Promise<void>;
|
|
44
|
-
private _handleDelivery;
|
|
45
|
-
private _handleConfirmation;
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=telegram-platform.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"telegram-platform.d.ts","sourceRoot":"","sources":["../src/telegram-platform.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EAEf,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAS7B,OAAO,QAAQ,kBAAkB,CAAC;IAChC,UAAU,kBAAkB;QAC1B,QAAQ,EAAE;YAAE,IAAI,EAAE,UAAU,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KACpF;CACF;AAID,MAAM,WAAW,wBAAwB;IACvC,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;CAChD;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAChE,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,OAAO,CAAmC;IAElD,gEAAgE;IAChE,OAAO,CAAC,6BAA6B,CAGjC;IAEJ,4DAA4D;IAC5D,OAAO,CAAC,wBAAwB,CAEhB;gBAEJ,OAAO,EAAE,wBAAwB;IAO7C,IAAI,MAAM,IAAI,eAAe,CAE5B;IAEK,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAuG7C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAUb,eAAe;YAcf,mBAAmB;CA6BlC"}
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { Bot, InlineKeyboard } from "grammy";
|
|
2
|
-
import { extractText, splitMessage, parseTextConfirmation, formatConfirmationMessage, } from "@agentick/connector";
|
|
3
|
-
const TELEGRAM_MAX_LENGTH = 4096;
|
|
4
|
-
/**
|
|
5
|
-
* Telegram platform adapter for the Agentick connector system.
|
|
6
|
-
*
|
|
7
|
-
* Receives messages from a Telegram bot and delivers agent responses
|
|
8
|
-
* back as Telegram messages. Tool confirmations can use inline keyboards
|
|
9
|
-
* or text-based confirmation.
|
|
10
|
-
*/
|
|
11
|
-
export class TelegramPlatform {
|
|
12
|
-
_bot;
|
|
13
|
-
_allowedUsers;
|
|
14
|
-
_confirmationStyle;
|
|
15
|
-
_chatId;
|
|
16
|
-
_bridge = null;
|
|
17
|
-
_status = "disconnected";
|
|
18
|
-
/** Pending inline-keyboard confirmations keyed by toolUseId. */
|
|
19
|
-
_pendingKeyboardConfirmations = new Map();
|
|
20
|
-
/** Pending text-based confirmation (only one at a time). */
|
|
21
|
-
_pendingTextConfirmation = null;
|
|
22
|
-
constructor(options) {
|
|
23
|
-
this._bot = new Bot(options.token);
|
|
24
|
-
this._allowedUsers = new Set(options.allowedUsers ?? []);
|
|
25
|
-
this._chatId = options.chatId ?? null;
|
|
26
|
-
this._confirmationStyle = options.confirmationStyle ?? "inline-keyboard";
|
|
27
|
-
}
|
|
28
|
-
get status() {
|
|
29
|
-
return this._status;
|
|
30
|
-
}
|
|
31
|
-
async start(bridge) {
|
|
32
|
-
this._bridge = bridge;
|
|
33
|
-
this._status = "connecting";
|
|
34
|
-
bridge.reportStatus("connecting");
|
|
35
|
-
// Handle text messages
|
|
36
|
-
this._bot.on("message:text", async (ctx) => {
|
|
37
|
-
const userId = ctx.from.id;
|
|
38
|
-
const chatId = ctx.chat.id;
|
|
39
|
-
if (this._allowedUsers.size > 0 && !this._allowedUsers.has(userId)) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (this._chatId === null) {
|
|
43
|
-
this._chatId = chatId;
|
|
44
|
-
}
|
|
45
|
-
if (chatId !== this._chatId)
|
|
46
|
-
return;
|
|
47
|
-
const text = ctx.message.text;
|
|
48
|
-
// Text-based confirmation response
|
|
49
|
-
if (this._pendingTextConfirmation) {
|
|
50
|
-
const { respond } = this._pendingTextConfirmation;
|
|
51
|
-
this._pendingTextConfirmation = null;
|
|
52
|
-
respond(parseTextConfirmation(text));
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
bridge.send(text, {
|
|
56
|
-
type: "telegram",
|
|
57
|
-
chatId,
|
|
58
|
-
userId,
|
|
59
|
-
username: ctx.from.username,
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
// Single callback query handler — routes to pending confirmations by toolUseId
|
|
63
|
-
this._bot.on("callback_query:data", async (ctx) => {
|
|
64
|
-
const data = ctx.callbackQuery.data;
|
|
65
|
-
if (!data.startsWith("confirm:"))
|
|
66
|
-
return;
|
|
67
|
-
// Always answer the callback query to dismiss the loading spinner,
|
|
68
|
-
// even if the confirmation is already resolved (double-click race)
|
|
69
|
-
await ctx.answerCallbackQuery();
|
|
70
|
-
// Parse confirm:<toolUseId>:<action> — toolUseId may contain colons
|
|
71
|
-
const lastColon = data.lastIndexOf(":");
|
|
72
|
-
const toolUseId = data.slice(8, lastColon); // 8 = "confirm:".length
|
|
73
|
-
const action = data.slice(lastColon + 1);
|
|
74
|
-
const pending = this._pendingKeyboardConfirmations.get(toolUseId);
|
|
75
|
-
if (!pending)
|
|
76
|
-
return;
|
|
77
|
-
this._pendingKeyboardConfirmations.delete(toolUseId);
|
|
78
|
-
const confirmed = action === "approve";
|
|
79
|
-
pending.respond({ approved: confirmed });
|
|
80
|
-
try {
|
|
81
|
-
await ctx.editMessageText(`${pending.messageText}\n\n${confirmed ? "Approved" : "Denied"}`);
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
// Message may have been deleted
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
// Subscribe to delivery events
|
|
88
|
-
bridge.onDeliver((output) => {
|
|
89
|
-
return this._handleDelivery(output);
|
|
90
|
-
});
|
|
91
|
-
// Subscribe to confirmation requests
|
|
92
|
-
bridge.onConfirmation((request, respond) => {
|
|
93
|
-
this._handleConfirmation(request, respond).catch((err) => {
|
|
94
|
-
console.error("Telegram confirmation error:", err);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
// Typing indicator on execution start
|
|
98
|
-
bridge.onExecutionStart(() => {
|
|
99
|
-
if (this._chatId) {
|
|
100
|
-
this._bot.api.sendChatAction(this._chatId, "typing").catch(() => { });
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
// Validate token before starting (fails fast on 401)
|
|
104
|
-
await this._bot.api.getMe();
|
|
105
|
-
// Start long polling (fire-and-forget — errors reported via status)
|
|
106
|
-
this._bot
|
|
107
|
-
.start({
|
|
108
|
-
onStart: () => {
|
|
109
|
-
this._status = "connected";
|
|
110
|
-
bridge.reportStatus("connected");
|
|
111
|
-
},
|
|
112
|
-
})
|
|
113
|
-
.catch((err) => {
|
|
114
|
-
this._status = "error";
|
|
115
|
-
bridge.reportStatus("error", err);
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
async stop() {
|
|
119
|
-
await this._bot.stop();
|
|
120
|
-
this._status = "disconnected";
|
|
121
|
-
this._bridge = null;
|
|
122
|
-
this._pendingTextConfirmation = null;
|
|
123
|
-
this._pendingKeyboardConfirmations.clear();
|
|
124
|
-
}
|
|
125
|
-
// --- Private ---
|
|
126
|
-
async _handleDelivery(output) {
|
|
127
|
-
if (!this._chatId)
|
|
128
|
-
return;
|
|
129
|
-
for (const message of output.messages) {
|
|
130
|
-
const text = extractText(message.content, "\n\n");
|
|
131
|
-
if (!text)
|
|
132
|
-
continue;
|
|
133
|
-
const chunks = splitMessage(text, { maxLength: TELEGRAM_MAX_LENGTH });
|
|
134
|
-
for (const chunk of chunks) {
|
|
135
|
-
await this._bot.api.sendMessage(this._chatId, chunk);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
async _handleConfirmation(request, respond) {
|
|
140
|
-
if (!this._chatId)
|
|
141
|
-
return;
|
|
142
|
-
const text = formatConfirmationMessage(request);
|
|
143
|
-
if (this._confirmationStyle === "inline-keyboard") {
|
|
144
|
-
this._pendingKeyboardConfirmations.set(request.toolUseId, {
|
|
145
|
-
respond,
|
|
146
|
-
messageText: text,
|
|
147
|
-
});
|
|
148
|
-
const keyboard = new InlineKeyboard()
|
|
149
|
-
.text("Approve", `confirm:${request.toolUseId}:approve`)
|
|
150
|
-
.text("Deny", `confirm:${request.toolUseId}:deny`);
|
|
151
|
-
await this._bot.api.sendMessage(this._chatId, text, {
|
|
152
|
-
reply_markup: keyboard,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
this._pendingTextConfirmation = { respond };
|
|
157
|
-
await this._bot.api.sendMessage(this._chatId, `${text}\n\nReply yes/no (or explain what you'd like instead)`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
//# sourceMappingURL=telegram-platform.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"telegram-platform.js","sourceRoot":"","sources":["../src/telegram-platform.ts"],"names":[],"mappings":"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"}
|