@gamalan/pi-gateway 1.0.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 (75) hide show
  1. package/README.md +366 -0
  2. package/config/config.default.json +51 -0
  3. package/dist/adapters/base.d.ts +85 -0
  4. package/dist/adapters/base.js +34 -0
  5. package/dist/adapters/base.js.map +1 -0
  6. package/dist/adapters/discord.d.ts +53 -0
  7. package/dist/adapters/discord.js +224 -0
  8. package/dist/adapters/discord.js.map +1 -0
  9. package/dist/adapters/index.d.ts +13 -0
  10. package/dist/adapters/index.js +8 -0
  11. package/dist/adapters/index.js.map +1 -0
  12. package/dist/adapters/slack.d.ts +49 -0
  13. package/dist/adapters/slack.js +231 -0
  14. package/dist/adapters/slack.js.map +1 -0
  15. package/dist/adapters/telegram.d.ts +64 -0
  16. package/dist/adapters/telegram.js +274 -0
  17. package/dist/adapters/telegram.js.map +1 -0
  18. package/dist/adapters/twitch.d.ts +75 -0
  19. package/dist/adapters/twitch.js +222 -0
  20. package/dist/adapters/twitch.js.map +1 -0
  21. package/dist/adapters/websocket.d.ts +30 -0
  22. package/dist/adapters/websocket.js +132 -0
  23. package/dist/adapters/websocket.js.map +1 -0
  24. package/dist/adapters/whatsapp.d.ts +49 -0
  25. package/dist/adapters/whatsapp.js +251 -0
  26. package/dist/adapters/whatsapp.js.map +1 -0
  27. package/dist/background/index.d.ts +1 -0
  28. package/dist/background/index.js +2 -0
  29. package/dist/background/index.js.map +1 -0
  30. package/dist/background/manager.d.ts +70 -0
  31. package/dist/background/manager.js +291 -0
  32. package/dist/background/manager.js.map +1 -0
  33. package/dist/index.d.ts +18 -0
  34. package/dist/index.js +1275 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/logger.d.ts +12 -0
  37. package/dist/logger.js +39 -0
  38. package/dist/logger.js.map +1 -0
  39. package/dist/paths.d.ts +14 -0
  40. package/dist/paths.js +32 -0
  41. package/dist/paths.js.map +1 -0
  42. package/dist/security/auth.d.ts +91 -0
  43. package/dist/security/auth.js +316 -0
  44. package/dist/security/auth.js.map +1 -0
  45. package/dist/security/index.d.ts +1 -0
  46. package/dist/security/index.js +2 -0
  47. package/dist/security/index.js.map +1 -0
  48. package/dist/security/tool-policy.d.ts +66 -0
  49. package/dist/security/tool-policy.js +467 -0
  50. package/dist/security/tool-policy.js.map +1 -0
  51. package/dist/sessions/index.d.ts +1 -0
  52. package/dist/sessions/index.js +2 -0
  53. package/dist/sessions/index.js.map +1 -0
  54. package/dist/sessions/store.d.ts +64 -0
  55. package/dist/sessions/store.js +247 -0
  56. package/dist/sessions/store.js.map +1 -0
  57. package/package.json +57 -0
  58. package/src/adapters/base.ts +124 -0
  59. package/src/adapters/discord.ts +270 -0
  60. package/src/adapters/index.ts +13 -0
  61. package/src/adapters/slack.ts +313 -0
  62. package/src/adapters/telegram.ts +394 -0
  63. package/src/adapters/twitch.ts +316 -0
  64. package/src/adapters/websocket.ts +158 -0
  65. package/src/adapters/whatsapp.ts +296 -0
  66. package/src/background/index.ts +1 -0
  67. package/src/background/manager.ts +395 -0
  68. package/src/index.ts +1665 -0
  69. package/src/logger.ts +43 -0
  70. package/src/paths.ts +40 -0
  71. package/src/security/auth.ts +458 -0
  72. package/src/security/index.ts +1 -0
  73. package/src/security/tool-policy.ts +568 -0
  74. package/src/sessions/index.ts +1 -0
  75. package/src/sessions/store.ts +360 -0
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Discord Adapter - Hermes-style Discord platform adapter
3
+ *
4
+ * Features:
5
+ * - DM and guild channel support
6
+ * - Slash command registration
7
+ * - Typing indicators
8
+ * - Message editing/deletion
9
+ * - Rate limit handling
10
+ */
11
+ import { BaseAdapter } from "./base.js";
12
+ import { logger } from "../logger.js";
13
+ export class DiscordAdapter extends BaseAdapter {
14
+ platform = "discord";
15
+ config;
16
+ httpClient = null;
17
+ wsConnection = null;
18
+ heartbeatInterval = null;
19
+ sequence = null;
20
+ sessionId = null;
21
+ intents = 0;
22
+ constructor(config) {
23
+ super();
24
+ this.config = config;
25
+ // Intents: GUILD_MESSAGES (1<<9) + DIRECT_MESSAGES (1<<12) + MESSAGE_CONTENT (1<<15)
26
+ this.intents = 1 << 9 | 1 << 12 | 1 << 15;
27
+ }
28
+ async initialize() {
29
+ // Test bot token
30
+ const response = await this.apiRequest("/users/@me");
31
+ const data = await response.json();
32
+ if (!response.ok) {
33
+ throw new Error(`Discord authentication failed: ${response.status}`);
34
+ }
35
+ logger.info(`[Discord] Bot initialized: ${data.username}`);
36
+ }
37
+ async apiRequest(endpoint, options = {}) {
38
+ const url = `https://discord.com/api/v10${endpoint}`;
39
+ return fetch(url, {
40
+ ...options,
41
+ headers: {
42
+ "Authorization": `Bot ${this.config.botToken}`,
43
+ "Content-Type": "application/json",
44
+ ...options.headers,
45
+ },
46
+ });
47
+ }
48
+ async start(callbacks) {
49
+ await super.start(callbacks);
50
+ // Connect to Gateway
51
+ const gatewayResponse = await this.apiRequest("/gateway");
52
+ const gatewayData = (await gatewayResponse.json());
53
+ const gatewayUrl = `${gatewayData.url}?v=10&encoding=json&intents=${this.intents}`;
54
+ this.wsConnection = new WebSocket(gatewayUrl);
55
+ this.wsConnection.onopen = () => {
56
+ logger.info("[Discord] WebSocket connected");
57
+ };
58
+ this.wsConnection.onmessage = async (event) => {
59
+ const data = JSON.parse(event.data);
60
+ await this.handleGatewayMessage(data);
61
+ };
62
+ this.wsConnection.onclose = () => {
63
+ logger.info("[Discord] WebSocket closed");
64
+ this.callbacks?.onDisconnect?.();
65
+ // Attempt reconnect after 5 seconds
66
+ setTimeout(() => this.start(callbacks), 5000);
67
+ };
68
+ }
69
+ async handleGatewayMessage(data) {
70
+ switch (data.op) {
71
+ case 0: // Dispatch
72
+ this.sequence = data.s;
73
+ await this.handleDispatch(data.t, data.d);
74
+ break;
75
+ case 10: // Hello
76
+ this.startHeartbeat(data.d.heartbeat_interval);
77
+ this.identify();
78
+ break;
79
+ case 11: // Heartbeat ACK
80
+ // Heartbeat acknowledged
81
+ break;
82
+ }
83
+ }
84
+ startHeartbeat(interval) {
85
+ this.heartbeatInterval = setInterval(() => {
86
+ if (this.wsConnection?.readyState === WebSocket.OPEN) {
87
+ this.wsConnection.send(JSON.stringify({
88
+ op: 1,
89
+ d: this.sequence,
90
+ }));
91
+ }
92
+ }, interval);
93
+ }
94
+ async identify() {
95
+ const identifyPayload = {
96
+ op: 2,
97
+ d: {
98
+ token: this.config.botToken,
99
+ intents: this.intents,
100
+ properties: {
101
+ os: "linux",
102
+ browser: "pi-gateway",
103
+ device: "pi-gateway",
104
+ },
105
+ },
106
+ };
107
+ this.wsConnection?.send(JSON.stringify(identifyPayload));
108
+ }
109
+ async handleDispatch(type, data) {
110
+ switch (type) {
111
+ case "READY":
112
+ this.sessionId = data.session_id;
113
+ logger.info(`[Discord] Logged in as ${data.user.username}`);
114
+ break;
115
+ case "MESSAGE_CREATE":
116
+ await this.handleMessage(data);
117
+ break;
118
+ case "MESSAGE_UPDATE":
119
+ // Handle edits if needed
120
+ break;
121
+ }
122
+ }
123
+ async handleMessage(data) {
124
+ // Ignore bots
125
+ if (data.author.bot && data.author.id !== this.getBotId())
126
+ return;
127
+ // Check if DM or allowed channel
128
+ const isDM = !data.guild_id;
129
+ if (!isDM && this.config.allowedChannels?.length) {
130
+ if (!this.config.allowedChannels.includes(data.channel_id))
131
+ return;
132
+ }
133
+ // Check mention requirement in guilds
134
+ if (!isDM && this.config.requireMention) {
135
+ const mentioned = data.content.includes(`<@${this.getBotId()}>`);
136
+ if (!mentioned)
137
+ return;
138
+ }
139
+ const message = {
140
+ id: data.id,
141
+ platform: this.platform,
142
+ channelId: data.channel_id,
143
+ userId: data.author.id,
144
+ content: data.content,
145
+ timestamp: new Date(data.timestamp).getTime(),
146
+ metadata: {
147
+ guildId: data.guild_id,
148
+ username: data.author.username,
149
+ discriminator: data.author.discriminator,
150
+ isDM,
151
+ },
152
+ };
153
+ await this.callbacks?.onMessage(message);
154
+ }
155
+ getBotId() {
156
+ // Extract from token - this is approximate
157
+ return this.config.botToken.split(".")[0];
158
+ }
159
+ async sendMessage(channelId, content) {
160
+ const response = await this.apiRequest(`/channels/${channelId}/messages`, {
161
+ method: "POST",
162
+ body: JSON.stringify({ content }),
163
+ });
164
+ if (!response.ok) {
165
+ const error = await response.text();
166
+ throw new Error(`Failed to send message: ${error}`);
167
+ }
168
+ const data = (await response.json());
169
+ return data.id;
170
+ }
171
+ async editMessage(channelId, messageId, content) {
172
+ await this.apiRequest(`/channels/${channelId}/messages/${messageId}`, {
173
+ method: "PATCH",
174
+ body: JSON.stringify({ content }),
175
+ });
176
+ }
177
+ async deleteMessage(channelId, messageId) {
178
+ await this.apiRequest(`/channels/${channelId}/messages/${messageId}`, {
179
+ method: "DELETE",
180
+ });
181
+ }
182
+ async setTyping(channelId, isTyping) {
183
+ if (!isTyping)
184
+ return; // Discord doesn't have a "stop typing" API
185
+ await this.apiRequest(`/channels/${channelId}/typing`, {
186
+ method: "POST",
187
+ });
188
+ }
189
+ async getStatus() {
190
+ try {
191
+ const response = await this.apiRequest("/gateway/bot");
192
+ const data = await response.json();
193
+ return {
194
+ connected: true,
195
+ latency: data.session_start_limit?.remaining ?? undefined,
196
+ };
197
+ }
198
+ catch {
199
+ return { connected: false };
200
+ }
201
+ }
202
+ async stop() {
203
+ if (this.heartbeatInterval) {
204
+ clearInterval(this.heartbeatInterval);
205
+ }
206
+ if (this.wsConnection) {
207
+ this.wsConnection.close();
208
+ }
209
+ await super.stop();
210
+ }
211
+ // Helper to register slash commands
212
+ async registerSlashCommands(commands) {
213
+ if (!this.config.guildId) {
214
+ logger.warn("[Discord] guildId required for slash commands");
215
+ return;
216
+ }
217
+ await this.apiRequest(`/applications/${this.getBotId()}/guilds/${this.config.guildId}/commands`, {
218
+ method: "PUT",
219
+ body: JSON.stringify(commands),
220
+ });
221
+ logger.info(`[Discord] Registered ${commands.length} slash commands`);
222
+ }
223
+ }
224
+ //# sourceMappingURL=discord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.js","sourceRoot":"","sources":["../../src/adapters/discord.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export { BaseAdapter, type PlatformMessage, type PlatformConfig, type AdapterCallbacks, type PlatformAdapter } from "./base.js";
2
+ export { DiscordAdapter } from "./discord.js";
3
+ export type { DiscordConfig } from "./discord.js";
4
+ export { TwitchAdapter } from "./twitch.js";
5
+ export type { TwitchConfig } from "./twitch.js";
6
+ export { TelegramAdapter } from "./telegram.js";
7
+ export type { TelegramConfig } from "./telegram.js";
8
+ export { SlackAdapter } from "./slack.js";
9
+ export type { SlackConfig } from "./slack.js";
10
+ export { WhatsAppAdapter } from "./whatsapp.js";
11
+ export type { WhatsAppConfig } from "./whatsapp.js";
12
+ export { WebSocketAdapter } from "./websocket.js";
13
+ export type { WebSocketConfig } from "./websocket.js";
@@ -0,0 +1,8 @@
1
+ export { BaseAdapter } from "./base.js";
2
+ export { DiscordAdapter } from "./discord.js";
3
+ export { TwitchAdapter } from "./twitch.js";
4
+ export { TelegramAdapter } from "./telegram.js";
5
+ export { SlackAdapter } from "./slack.js";
6
+ export { WhatsAppAdapter } from "./whatsapp.js";
7
+ export { WebSocketAdapter } from "./websocket.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0F,MAAM,WAAW,CAAC;AAChI,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Slack Adapter - Hermes-style Slack platform adapter
3
+ *
4
+ * Features:
5
+ * - Incoming webhooks (outbound only)
6
+ * - Web API (with bot token)
7
+ * - Slash command support
8
+ * - Block Kit support
9
+ */
10
+ import { BaseAdapter, type PlatformConfig } from "./base.js";
11
+ export interface SlackConfig extends PlatformConfig {
12
+ platform: "slack";
13
+ webhookUrl?: string;
14
+ botToken?: string;
15
+ signingSecret?: string;
16
+ teamId?: string;
17
+ defaultChannel?: string;
18
+ }
19
+ export declare class SlackAdapter extends BaseAdapter {
20
+ readonly platform: "slack";
21
+ config: SlackConfig;
22
+ private connected;
23
+ constructor(config: SlackConfig);
24
+ initialize(): Promise<void>;
25
+ private apiRequest;
26
+ start(callbacks: any): Promise<void>;
27
+ stop(): Promise<void>;
28
+ sendMessage(channelId: string, content: string): Promise<string>;
29
+ postMessage(channelId: string, content: string, blocks?: any[]): Promise<string>;
30
+ replyToThread(channelId: string, threadTs: string, content: string): Promise<string>;
31
+ editMessage(channelId: string, messageTs: string, content: string): Promise<void>;
32
+ deleteMessage(channelId: string, messageTs: string): Promise<void>;
33
+ setTyping(channelId: string, isTyping: boolean): Promise<void>;
34
+ getChannelInfo(channelId: string): Promise<{
35
+ id: string;
36
+ name: string;
37
+ numMembers: number;
38
+ topic: string;
39
+ } | null>;
40
+ listChannels(): Promise<Array<{
41
+ id: string;
42
+ name: string;
43
+ }>>;
44
+ getStatus(): Promise<{
45
+ connected: boolean;
46
+ latency?: number;
47
+ }>;
48
+ handleIncomingEvent(event: any): Promise<void>;
49
+ }
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Slack Adapter - Hermes-style Slack platform adapter
3
+ *
4
+ * Features:
5
+ * - Incoming webhooks (outbound only)
6
+ * - Web API (with bot token)
7
+ * - Slash command support
8
+ * - Block Kit support
9
+ */
10
+ import { BaseAdapter } from "./base.js";
11
+ import { logger } from "../logger.js";
12
+ export class SlackAdapter extends BaseAdapter {
13
+ platform = "slack";
14
+ config;
15
+ connected = false;
16
+ constructor(config) {
17
+ super();
18
+ this.config = {
19
+ enabled: true,
20
+ platform: "slack",
21
+ ...config,
22
+ };
23
+ }
24
+ async initialize() {
25
+ if (this.config.botToken) {
26
+ // Test bot token
27
+ const response = await this.apiRequest("auth.test", { method: "POST" });
28
+ const data = await response.json();
29
+ if (!data.ok) {
30
+ throw new Error(`Slack auth failed: ${data}`);
31
+ }
32
+ logger.info(`[Slack] Bot initialized for team: ${data.team_id}`);
33
+ }
34
+ else if (this.config.webhookUrl) {
35
+ logger.info("[Slack] Using webhook mode (outbound only)");
36
+ }
37
+ else {
38
+ throw new Error("Slack requires either botToken or webhookUrl");
39
+ }
40
+ }
41
+ async apiRequest(endpoint, options = {}) {
42
+ const url = `https://slack.com/api/${endpoint}`;
43
+ return fetch(url, {
44
+ ...options,
45
+ headers: {
46
+ "Content-Type": "application/json",
47
+ "Authorization": `Bearer ${this.config.botToken}`,
48
+ ...options.headers,
49
+ },
50
+ });
51
+ }
52
+ async start(callbacks) {
53
+ await super.start(callbacks);
54
+ this.connected = true;
55
+ if (!this.config.botToken && !this.config.webhookUrl) {
56
+ logger.warn("[Slack] No credentials configured - adapter is outbound-only");
57
+ }
58
+ }
59
+ async stop() {
60
+ this.connected = false;
61
+ await super.stop();
62
+ }
63
+ async sendMessage(channelId, content) {
64
+ // Try webhook first if available
65
+ if (this.config.webhookUrl) {
66
+ const payload = {
67
+ text: content,
68
+ ...(channelId && channelId.startsWith("#") ? { channel: channelId } : {}),
69
+ };
70
+ const response = await fetch(this.config.webhookUrl, {
71
+ method: "POST",
72
+ headers: { "Content-Type": "application/json" },
73
+ body: JSON.stringify(payload),
74
+ });
75
+ if (!response.ok) {
76
+ throw new Error(`Slack webhook failed: ${response.status}`);
77
+ }
78
+ return `webhook-${Date.now()}`;
79
+ }
80
+ // Use Web API if we have a bot token
81
+ if (this.config.botToken) {
82
+ const response = await this.apiRequest("chat.postMessage", {
83
+ method: "POST",
84
+ body: JSON.stringify({
85
+ channel: channelId,
86
+ text: content,
87
+ }),
88
+ });
89
+ const data = await response.json();
90
+ if (!data.ok) {
91
+ throw new Error(`Slack API error: ${data.error}`);
92
+ }
93
+ return data.ts || String(Date.now());
94
+ }
95
+ throw new Error("No Slack credentials configured");
96
+ }
97
+ async postMessage(channelId, content, blocks) {
98
+ if (!this.config.botToken) {
99
+ throw new Error("Bot token required for rich messages");
100
+ }
101
+ const body = {
102
+ channel: channelId,
103
+ text: content,
104
+ };
105
+ if (blocks) {
106
+ body.blocks = blocks;
107
+ }
108
+ const response = await this.apiRequest("chat.postMessage", {
109
+ method: "POST",
110
+ body: JSON.stringify(body),
111
+ });
112
+ const data = await response.json();
113
+ if (!data.ok) {
114
+ throw new Error(`Slack API error: ${data.error}`);
115
+ }
116
+ return data.ts || String(Date.now());
117
+ }
118
+ async replyToThread(channelId, threadTs, content) {
119
+ if (!this.config.botToken) {
120
+ throw new Error("Bot token required for threaded replies");
121
+ }
122
+ const response = await this.apiRequest("chat.postMessage", {
123
+ method: "POST",
124
+ body: JSON.stringify({
125
+ channel: channelId,
126
+ text: content,
127
+ thread_ts: threadTs,
128
+ }),
129
+ });
130
+ const data = await response.json();
131
+ if (!data.ok) {
132
+ throw new Error(`Slack API error: ${data.error}`);
133
+ }
134
+ return data.ts || String(Date.now());
135
+ }
136
+ async editMessage(channelId, messageTs, content) {
137
+ if (!this.config.botToken) {
138
+ throw new Error("Bot token required for editing");
139
+ }
140
+ await this.apiRequest("chat.update", {
141
+ method: "POST",
142
+ body: JSON.stringify({
143
+ channel: channelId,
144
+ ts: messageTs,
145
+ text: content,
146
+ }),
147
+ });
148
+ }
149
+ async deleteMessage(channelId, messageTs) {
150
+ if (!this.config.botToken) {
151
+ throw new Error("Bot token required for deletion");
152
+ }
153
+ await this.apiRequest("chat.delete", {
154
+ method: "POST",
155
+ body: JSON.stringify({
156
+ channel: channelId,
157
+ ts: messageTs,
158
+ }),
159
+ });
160
+ }
161
+ async setTyping(channelId, isTyping) {
162
+ if (!this.config.botToken)
163
+ return;
164
+ await this.apiRequest("chat.postEphemeral", {
165
+ method: "POST",
166
+ body: JSON.stringify({
167
+ channel: channelId,
168
+ text: isTyping ? "_typing_" : "",
169
+ }),
170
+ });
171
+ }
172
+ async getChannelInfo(channelId) {
173
+ if (!this.config.botToken) {
174
+ throw new Error("Bot token required");
175
+ }
176
+ const response = await this.apiRequest("conversations.info", {
177
+ method: "POST",
178
+ body: JSON.stringify({ channel: channelId }),
179
+ });
180
+ const data = await response.json();
181
+ if (!data.ok || !data.channel) {
182
+ return null;
183
+ }
184
+ return {
185
+ id: data.channel.id,
186
+ name: data.channel.name,
187
+ numMembers: data.channel.num_members,
188
+ topic: data.channel.topic?.value || "",
189
+ };
190
+ }
191
+ async listChannels() {
192
+ if (!this.config.botToken) {
193
+ throw new Error("Bot token required");
194
+ }
195
+ const response = await this.apiRequest("conversations.list", {
196
+ method: "POST",
197
+ body: JSON.stringify({ types: "public_channel,private_channel" }),
198
+ });
199
+ const data = await response.json();
200
+ if (!data.ok) {
201
+ return [];
202
+ }
203
+ return (data.channels || []).map(c => ({ id: c.id, name: c.name }));
204
+ }
205
+ async getStatus() {
206
+ return {
207
+ connected: this.connected,
208
+ ...(this.config.botToken ? { mode: "api" } : { mode: "webhook" })
209
+ };
210
+ }
211
+ // Handle incoming events (for WebSocket or Socket Mode)
212
+ async handleIncomingEvent(event) {
213
+ if (event.type === "message" && !event.subtype) {
214
+ const message = {
215
+ id: this.generateMessageId(),
216
+ platform: "slack",
217
+ channelId: event.channel,
218
+ userId: event.user,
219
+ content: event.text,
220
+ timestamp: parseFloat(event.ts) * 1000,
221
+ metadata: {
222
+ team: event.team,
223
+ threadTs: event.thread_ts,
224
+ username: event.username,
225
+ },
226
+ };
227
+ this.emitMessage(message);
228
+ }
229
+ }
230
+ }
231
+ //# sourceMappingURL=slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../../src/adapters/slack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Telegram Adapter - Hermes-style Telegram platform adapter
3
+ *
4
+ * Features:
5
+ * - Polling and webhook modes
6
+ * - DM and group chat support
7
+ * - Inline queries
8
+ * - Callback buttons
9
+ */
10
+ import { BaseAdapter, type PlatformConfig } from "./base.js";
11
+ interface TelegramConfig extends PlatformConfig {
12
+ platform: "telegram";
13
+ token: string;
14
+ /** Public URL Telegram sends updates to (e.g. https://example.com/webhook/telegram).
15
+ * When set, webhook mode is used. When omitted, long polling is used. */
16
+ webhookUrl?: string;
17
+ webhookSecret?: string;
18
+ allowedChats?: string[];
19
+ requireUsername?: boolean;
20
+ }
21
+ export type { TelegramConfig };
22
+ export declare class TelegramAdapter extends BaseAdapter {
23
+ readonly platform: "telegram";
24
+ config: TelegramConfig;
25
+ private offset;
26
+ private pollingActive;
27
+ private connected;
28
+ constructor(config: TelegramConfig);
29
+ initialize(): Promise<void>;
30
+ private apiRequest;
31
+ start(callbacks: any): Promise<void>;
32
+ /**
33
+ * Long polling via getUpdates.
34
+ *
35
+ * Telegram holds the connection open (up to `timeout` seconds) and
36
+ * returns immediately when a message arrives. This is NOT interval-
37
+ * based polling — it is near-real-time, similar to a persistent
38
+ * connection. Used as a fallback when no webhookUrl is configured.
39
+ */
40
+ private startLongPolling;
41
+ private longPoll;
42
+ private handleUpdate;
43
+ private sleep;
44
+ stop(): Promise<void>;
45
+ sendMessage(channelId: string, content: string): Promise<string>;
46
+ sendPhoto(channelId: string, photoUrl: string, caption?: string): Promise<string>;
47
+ sendButtons(channelId: string, text: string, buttons: Array<Array<{
48
+ text: string;
49
+ data: string;
50
+ }>>): Promise<string>;
51
+ editMessage(channelId: string, messageId: string, content: string): Promise<void>;
52
+ deleteMessage(channelId: string, messageId: string): Promise<void>;
53
+ setTyping(channelId: string, isTyping: boolean): Promise<void>;
54
+ getStatus(): Promise<{
55
+ connected: boolean;
56
+ latency?: number;
57
+ }>;
58
+ getMe(): Promise<{
59
+ id: number;
60
+ username: string;
61
+ first_name: string;
62
+ }>;
63
+ handleWebhookUpdate(update: any): Promise<void>;
64
+ }