@herdctl/slack 0.0.1 → 0.2.1
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/LICENSE +21 -0
- package/dist/__tests__/command-handler.test.d.ts +2 -0
- package/dist/__tests__/command-handler.test.d.ts.map +1 -0
- package/dist/__tests__/command-handler.test.js +141 -0
- package/dist/__tests__/command-handler.test.js.map +1 -0
- package/dist/__tests__/error-handler.test.d.ts +2 -0
- package/dist/__tests__/error-handler.test.d.ts.map +1 -0
- package/dist/__tests__/error-handler.test.js +168 -0
- package/dist/__tests__/error-handler.test.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +133 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/formatting.test.d.ts +2 -0
- package/dist/__tests__/formatting.test.d.ts.map +1 -0
- package/dist/__tests__/formatting.test.js +216 -0
- package/dist/__tests__/formatting.test.js.map +1 -0
- package/dist/__tests__/logger.test.d.ts +2 -0
- package/dist/__tests__/logger.test.d.ts.map +1 -0
- package/dist/__tests__/logger.test.js +97 -0
- package/dist/__tests__/logger.test.js.map +1 -0
- package/dist/__tests__/message-handler.test.d.ts +2 -0
- package/dist/__tests__/message-handler.test.d.ts.map +1 -0
- package/dist/__tests__/message-handler.test.js +78 -0
- package/dist/__tests__/message-handler.test.js.map +1 -0
- package/dist/__tests__/session-manager.test.d.ts +2 -0
- package/dist/__tests__/session-manager.test.d.ts.map +1 -0
- package/dist/__tests__/session-manager.test.js +214 -0
- package/dist/__tests__/session-manager.test.js.map +1 -0
- package/dist/__tests__/slack-connector.test.d.ts +2 -0
- package/dist/__tests__/slack-connector.test.d.ts.map +1 -0
- package/dist/__tests__/slack-connector.test.js +376 -0
- package/dist/__tests__/slack-connector.test.js.map +1 -0
- package/dist/commands/command-handler.d.ts +72 -0
- package/dist/commands/command-handler.d.ts.map +1 -0
- package/dist/commands/command-handler.js +85 -0
- package/dist/commands/command-handler.js.map +1 -0
- package/dist/commands/help.d.ts +6 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +22 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/commands/index.d.ts +11 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +10 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/reset.d.ts +6 -0
- package/dist/commands/reset.d.ts.map +1 -0
- package/dist/commands/reset.js +18 -0
- package/dist/commands/reset.js.map +1 -0
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +94 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/error-handler.d.ts +50 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +123 -0
- package/dist/error-handler.js.map +1 -0
- package/dist/errors.d.ts +59 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +73 -0
- package/dist/errors.js.map +1 -0
- package/dist/formatting.d.ts +83 -0
- package/dist/formatting.d.ts.map +1 -0
- package/dist/formatting.js +155 -0
- package/dist/formatting.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +28 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +41 -0
- package/dist/logger.js.map +1 -0
- package/dist/message-handler.d.ts +62 -0
- package/dist/message-handler.d.ts.map +1 -0
- package/dist/message-handler.js +85 -0
- package/dist/message-handler.js.map +1 -0
- package/dist/session-manager/errors.d.ts +58 -0
- package/dist/session-manager/errors.d.ts.map +1 -0
- package/dist/session-manager/errors.js +70 -0
- package/dist/session-manager/errors.js.map +1 -0
- package/dist/session-manager/index.d.ts +9 -0
- package/dist/session-manager/index.d.ts.map +1 -0
- package/dist/session-manager/index.js +13 -0
- package/dist/session-manager/index.js.map +1 -0
- package/dist/session-manager/session-manager.d.ts +62 -0
- package/dist/session-manager/session-manager.d.ts.map +1 -0
- package/dist/session-manager/session-manager.js +320 -0
- package/dist/session-manager/session-manager.js.map +1 -0
- package/dist/session-manager/types.d.ts +154 -0
- package/dist/session-manager/types.d.ts.map +1 -0
- package/dist/session-manager/types.js +57 -0
- package/dist/session-manager/types.js.map +1 -0
- package/dist/slack-connector.d.ts +53 -0
- package/dist/slack-connector.d.ts.map +1 -0
- package/dist/slack-connector.js +447 -0
- package/dist/slack-connector.js.map +1 -0
- package/dist/types.d.ts +211 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -4
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slack Connector
|
|
3
|
+
*
|
|
4
|
+
* Single Bolt App instance with channel->agent routing.
|
|
5
|
+
* Uses Socket Mode for connection (no public URL needed).
|
|
6
|
+
*
|
|
7
|
+
* Key design:
|
|
8
|
+
* - ONE connector shared across all agents (not N connectors)
|
|
9
|
+
* - Channel->agent routing via channelAgentMap
|
|
10
|
+
* - Channel-based conversations (channelId as session key, matching Discord)
|
|
11
|
+
* - Hourglass emoji reaction as typing indicator
|
|
12
|
+
*/
|
|
13
|
+
import { EventEmitter } from "node:events";
|
|
14
|
+
import { shouldProcessMessage, processMessage, isBotMentioned, } from "./message-handler.js";
|
|
15
|
+
import { CommandHandler, helpCommand, resetCommand, statusCommand, } from "./commands/index.js";
|
|
16
|
+
import { markdownToMrkdwn } from "./formatting.js";
|
|
17
|
+
import { AlreadyConnectedError, SlackConnectionError } from "./errors.js";
|
|
18
|
+
import { createDefaultSlackLogger } from "./logger.js";
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Slack Connector Implementation
|
|
21
|
+
// =============================================================================
|
|
22
|
+
export class SlackConnector extends EventEmitter {
|
|
23
|
+
botToken;
|
|
24
|
+
appToken;
|
|
25
|
+
channelAgentMap;
|
|
26
|
+
channelConfigs;
|
|
27
|
+
sessionManagers;
|
|
28
|
+
logger;
|
|
29
|
+
// Bolt App instance (dynamically imported)
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
app = null;
|
|
32
|
+
// Command handler for prefix commands (!help, !reset, !status)
|
|
33
|
+
commandHandler = null;
|
|
34
|
+
// Connection state
|
|
35
|
+
status = "disconnected";
|
|
36
|
+
connectedAt = null;
|
|
37
|
+
disconnectedAt = null;
|
|
38
|
+
reconnectAttempts = 0;
|
|
39
|
+
lastError = null;
|
|
40
|
+
botUserId = null;
|
|
41
|
+
botUsername = null;
|
|
42
|
+
// Message stats
|
|
43
|
+
messagesReceived = 0;
|
|
44
|
+
messagesSent = 0;
|
|
45
|
+
messagesIgnored = 0;
|
|
46
|
+
constructor(options) {
|
|
47
|
+
super();
|
|
48
|
+
this.botToken = options.botToken;
|
|
49
|
+
this.appToken = options.appToken;
|
|
50
|
+
this.channelAgentMap = options.channelAgentMap;
|
|
51
|
+
this.channelConfigs = options.channelConfigs ?? new Map();
|
|
52
|
+
this.sessionManagers = options.sessionManagers;
|
|
53
|
+
this.logger = options.logger ?? createDefaultSlackLogger();
|
|
54
|
+
}
|
|
55
|
+
// ===========================================================================
|
|
56
|
+
// ISlackConnector Implementation
|
|
57
|
+
// ===========================================================================
|
|
58
|
+
async connect() {
|
|
59
|
+
if (this.status === "connected" || this.status === "connecting") {
|
|
60
|
+
throw new AlreadyConnectedError();
|
|
61
|
+
}
|
|
62
|
+
this.status = "connecting";
|
|
63
|
+
this.logger.debug("Connecting to Slack via Socket Mode...");
|
|
64
|
+
try {
|
|
65
|
+
// Dynamically import @slack/bolt
|
|
66
|
+
const { App } = await import("@slack/bolt");
|
|
67
|
+
this.app = new App({
|
|
68
|
+
token: this.botToken,
|
|
69
|
+
appToken: this.appToken,
|
|
70
|
+
socketMode: true,
|
|
71
|
+
});
|
|
72
|
+
// Register event handlers
|
|
73
|
+
this.registerEventHandlers();
|
|
74
|
+
// Start the app
|
|
75
|
+
await this.app.start();
|
|
76
|
+
// Get bot info
|
|
77
|
+
const authResult = await this.app.client.auth.test();
|
|
78
|
+
this.botUserId = authResult.user_id;
|
|
79
|
+
this.botUsername = authResult.user;
|
|
80
|
+
// Initialize command handler with built-in commands
|
|
81
|
+
this.commandHandler = new CommandHandler({ logger: this.logger });
|
|
82
|
+
this.commandHandler.registerCommand(helpCommand);
|
|
83
|
+
this.commandHandler.registerCommand(resetCommand);
|
|
84
|
+
this.commandHandler.registerCommand(statusCommand);
|
|
85
|
+
this.status = "connected";
|
|
86
|
+
this.connectedAt = new Date().toISOString();
|
|
87
|
+
this.disconnectedAt = null;
|
|
88
|
+
this.reconnectAttempts = 0;
|
|
89
|
+
this.lastError = null;
|
|
90
|
+
this.logger.info("Connected to Slack", {
|
|
91
|
+
botUserId: this.botUserId,
|
|
92
|
+
botUsername: this.botUsername,
|
|
93
|
+
channelCount: this.channelAgentMap.size,
|
|
94
|
+
});
|
|
95
|
+
this.emit("ready", {
|
|
96
|
+
botUser: {
|
|
97
|
+
id: this.botUserId,
|
|
98
|
+
username: this.botUsername ?? "unknown",
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
// Clean up expired sessions on startup (matching Discord behavior)
|
|
102
|
+
for (const [agentName, sessionManager] of this.sessionManagers) {
|
|
103
|
+
try {
|
|
104
|
+
const cleaned = await sessionManager.cleanupExpiredSessions();
|
|
105
|
+
if (cleaned > 0) {
|
|
106
|
+
this.logger.info(`Cleaned ${cleaned} expired session(s) for agent '${agentName}'`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (cleanupError) {
|
|
110
|
+
this.logger.warn(`Failed to cleanup sessions for agent '${agentName}'`, {
|
|
111
|
+
error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
this.status = "error";
|
|
118
|
+
this.lastError =
|
|
119
|
+
error instanceof Error ? error.message : String(error);
|
|
120
|
+
this.logger.error("Failed to connect to Slack", {
|
|
121
|
+
error: this.lastError,
|
|
122
|
+
});
|
|
123
|
+
throw new SlackConnectionError(`Failed to connect to Slack: ${this.lastError}`, { cause: error instanceof Error ? error : undefined });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async disconnect() {
|
|
127
|
+
if (this.status === "disconnected" ||
|
|
128
|
+
this.status === "disconnecting") {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
this.status = "disconnecting";
|
|
132
|
+
this.logger.info("Disconnecting from Slack...");
|
|
133
|
+
try {
|
|
134
|
+
if (this.app) {
|
|
135
|
+
await this.app.stop();
|
|
136
|
+
this.app = null;
|
|
137
|
+
}
|
|
138
|
+
this.commandHandler = null;
|
|
139
|
+
this.status = "disconnected";
|
|
140
|
+
this.disconnectedAt = new Date().toISOString();
|
|
141
|
+
this.logger.info("Disconnected from Slack", {
|
|
142
|
+
messagesReceived: this.messagesReceived,
|
|
143
|
+
messagesSent: this.messagesSent,
|
|
144
|
+
messagesIgnored: this.messagesIgnored,
|
|
145
|
+
});
|
|
146
|
+
this.emit("disconnect", { reason: "Intentional disconnect" });
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
this.status = "error";
|
|
150
|
+
this.lastError =
|
|
151
|
+
error instanceof Error ? error.message : String(error);
|
|
152
|
+
this.logger.error("Error disconnecting from Slack", {
|
|
153
|
+
error: this.lastError,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
isConnected() {
|
|
158
|
+
return this.status === "connected" && this.app !== null;
|
|
159
|
+
}
|
|
160
|
+
getState() {
|
|
161
|
+
return {
|
|
162
|
+
status: this.status,
|
|
163
|
+
connectedAt: this.connectedAt,
|
|
164
|
+
disconnectedAt: this.disconnectedAt,
|
|
165
|
+
reconnectAttempts: this.reconnectAttempts,
|
|
166
|
+
lastError: this.lastError,
|
|
167
|
+
botUser: this.botUserId
|
|
168
|
+
? {
|
|
169
|
+
id: this.botUserId,
|
|
170
|
+
username: this.botUsername ?? "unknown",
|
|
171
|
+
}
|
|
172
|
+
: null,
|
|
173
|
+
messageStats: {
|
|
174
|
+
received: this.messagesReceived,
|
|
175
|
+
sent: this.messagesSent,
|
|
176
|
+
ignored: this.messagesIgnored,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// ===========================================================================
|
|
181
|
+
// File Upload
|
|
182
|
+
// ===========================================================================
|
|
183
|
+
async uploadFile(params) {
|
|
184
|
+
if (!this.app?.client) {
|
|
185
|
+
throw new Error("Cannot upload file: not connected to Slack");
|
|
186
|
+
}
|
|
187
|
+
const response = await this.app.client.files.uploadV2({
|
|
188
|
+
channel_id: params.channelId,
|
|
189
|
+
file: params.fileBuffer,
|
|
190
|
+
filename: params.filename,
|
|
191
|
+
initial_comment: params.message ?? "",
|
|
192
|
+
});
|
|
193
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
194
|
+
const fileId = response.files?.[0]?.id ?? "unknown";
|
|
195
|
+
this.logger.info("File uploaded to Slack", {
|
|
196
|
+
fileId,
|
|
197
|
+
filename: params.filename,
|
|
198
|
+
channelId: params.channelId,
|
|
199
|
+
size: params.fileBuffer.length,
|
|
200
|
+
});
|
|
201
|
+
return { fileId };
|
|
202
|
+
}
|
|
203
|
+
// ===========================================================================
|
|
204
|
+
// Event Handlers
|
|
205
|
+
// ===========================================================================
|
|
206
|
+
registerEventHandlers() {
|
|
207
|
+
if (!this.app)
|
|
208
|
+
return;
|
|
209
|
+
// Handle @mentions
|
|
210
|
+
this.app.event("app_mention", async ({ event, say }) => {
|
|
211
|
+
this.messagesReceived++;
|
|
212
|
+
if (!this.botUserId)
|
|
213
|
+
return;
|
|
214
|
+
// Find which agent handles this channel
|
|
215
|
+
const agentName = this.channelAgentMap.get(event.channel);
|
|
216
|
+
if (!agentName) {
|
|
217
|
+
this.messagesIgnored++;
|
|
218
|
+
this.emit("messageIgnored", {
|
|
219
|
+
agentName: "unknown",
|
|
220
|
+
reason: "not_configured",
|
|
221
|
+
channelId: event.channel,
|
|
222
|
+
messageTs: event.ts,
|
|
223
|
+
});
|
|
224
|
+
this.logger.debug("Ignoring mention in unconfigured channel", {
|
|
225
|
+
channel: event.channel,
|
|
226
|
+
});
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const prompt = processMessage(event.text, this.botUserId);
|
|
230
|
+
if (!prompt) {
|
|
231
|
+
this.messagesIgnored++;
|
|
232
|
+
this.emit("messageIgnored", {
|
|
233
|
+
agentName,
|
|
234
|
+
reason: "empty_prompt",
|
|
235
|
+
channelId: event.channel,
|
|
236
|
+
messageTs: event.ts,
|
|
237
|
+
});
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
// Check for prefix commands before processing as a message
|
|
241
|
+
const wasCommand = await this.tryExecuteCommand(prompt, agentName, event.channel, event.user, say);
|
|
242
|
+
if (wasCommand)
|
|
243
|
+
return;
|
|
244
|
+
const messageEvent = this.buildMessageEvent(agentName, prompt, event.channel, event.ts, event.user, true, say);
|
|
245
|
+
this.emit("message", messageEvent);
|
|
246
|
+
});
|
|
247
|
+
// Handle all messages — thread replies AND top-level channel messages
|
|
248
|
+
this.app.event("message", async ({ event, say }) => {
|
|
249
|
+
this.messagesReceived++;
|
|
250
|
+
if (!this.botUserId)
|
|
251
|
+
return;
|
|
252
|
+
// Ignore bot messages and own messages
|
|
253
|
+
if (!shouldProcessMessage(event, this.botUserId)) {
|
|
254
|
+
this.messagesIgnored++;
|
|
255
|
+
this.emit("messageIgnored", {
|
|
256
|
+
agentName: "unknown",
|
|
257
|
+
reason: "bot_message",
|
|
258
|
+
channelId: event.channel,
|
|
259
|
+
messageTs: event.ts,
|
|
260
|
+
});
|
|
261
|
+
this.logger.debug("Skipping bot/own message", {
|
|
262
|
+
channel: event.channel,
|
|
263
|
+
botId: event.bot_id,
|
|
264
|
+
user: event.user,
|
|
265
|
+
});
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
// Skip @mentions — handled by the app_mention handler above
|
|
269
|
+
if (typeof event.text === "string" &&
|
|
270
|
+
isBotMentioned(event.text, this.botUserId)) {
|
|
271
|
+
this.logger.debug("Skipping @mention message (handled by app_mention)", {
|
|
272
|
+
channel: event.channel,
|
|
273
|
+
ts: event.ts,
|
|
274
|
+
});
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
// Resolve agent for this channel
|
|
278
|
+
const resolvedAgent = this.channelAgentMap.get(event.channel);
|
|
279
|
+
if (!resolvedAgent) {
|
|
280
|
+
this.messagesIgnored++;
|
|
281
|
+
this.emit("messageIgnored", {
|
|
282
|
+
agentName: "unknown",
|
|
283
|
+
reason: "no_agent_resolved",
|
|
284
|
+
channelId: event.channel,
|
|
285
|
+
messageTs: event.ts,
|
|
286
|
+
});
|
|
287
|
+
this.logger.debug("No agent resolved for message", {
|
|
288
|
+
channel: event.channel,
|
|
289
|
+
});
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
// For top-level messages (no thread_ts), check channel mode
|
|
293
|
+
if (!event.thread_ts) {
|
|
294
|
+
const channelConfig = this.channelConfigs.get(event.channel);
|
|
295
|
+
const mode = channelConfig?.mode ?? "mention";
|
|
296
|
+
if (mode === "mention") {
|
|
297
|
+
this.messagesIgnored++;
|
|
298
|
+
this.emit("messageIgnored", {
|
|
299
|
+
agentName: resolvedAgent,
|
|
300
|
+
reason: "not_configured",
|
|
301
|
+
channelId: event.channel,
|
|
302
|
+
messageTs: event.ts,
|
|
303
|
+
});
|
|
304
|
+
this.logger.debug("Ignoring top-level message in mention-mode channel", {
|
|
305
|
+
channel: event.channel,
|
|
306
|
+
agent: resolvedAgent,
|
|
307
|
+
mode,
|
|
308
|
+
});
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
this.logger.debug("Top-level channel message (auto mode)", {
|
|
312
|
+
channel: event.channel,
|
|
313
|
+
agent: resolvedAgent,
|
|
314
|
+
ts: event.ts,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
const prompt = processMessage(event.text ?? "", this.botUserId);
|
|
318
|
+
if (!prompt) {
|
|
319
|
+
this.messagesIgnored++;
|
|
320
|
+
this.emit("messageIgnored", {
|
|
321
|
+
agentName: resolvedAgent,
|
|
322
|
+
reason: "empty_prompt",
|
|
323
|
+
channelId: event.channel,
|
|
324
|
+
messageTs: event.ts,
|
|
325
|
+
});
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
// Check for prefix commands before processing as a message
|
|
329
|
+
const wasCommand = await this.tryExecuteCommand(prompt, resolvedAgent, event.channel, event.user ?? "", say);
|
|
330
|
+
if (wasCommand)
|
|
331
|
+
return;
|
|
332
|
+
const messageEvent = this.buildMessageEvent(resolvedAgent, prompt, event.channel, event.ts, event.user ?? "", false, say);
|
|
333
|
+
this.emit("message", messageEvent);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
// ===========================================================================
|
|
337
|
+
// Command Handling
|
|
338
|
+
// ===========================================================================
|
|
339
|
+
/**
|
|
340
|
+
* Try to execute a prefix command. Returns true if a command was handled.
|
|
341
|
+
*/
|
|
342
|
+
async tryExecuteCommand(prompt, agentName, channelId, userId,
|
|
343
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
344
|
+
say) {
|
|
345
|
+
if (!this.commandHandler || !this.commandHandler.isCommand(prompt)) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
const sessionManager = this.sessionManagers.get(agentName);
|
|
349
|
+
if (!sessionManager) {
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
const executed = await this.commandHandler.executeCommand(prompt, {
|
|
353
|
+
agentName,
|
|
354
|
+
channelId,
|
|
355
|
+
userId,
|
|
356
|
+
reply: async (content) => {
|
|
357
|
+
await say({ text: content });
|
|
358
|
+
},
|
|
359
|
+
sessionManager,
|
|
360
|
+
connectorState: this.getState(),
|
|
361
|
+
});
|
|
362
|
+
if (executed) {
|
|
363
|
+
const commandName = prompt.trim().slice(1).split(/\s+/)[0];
|
|
364
|
+
this.logger.info("Command executed", {
|
|
365
|
+
command: commandName,
|
|
366
|
+
agentName,
|
|
367
|
+
channelId,
|
|
368
|
+
});
|
|
369
|
+
this.emit("commandExecuted", {
|
|
370
|
+
agentName,
|
|
371
|
+
commandName,
|
|
372
|
+
userId,
|
|
373
|
+
channelId,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
return executed;
|
|
377
|
+
}
|
|
378
|
+
// ===========================================================================
|
|
379
|
+
// Message Building
|
|
380
|
+
// ===========================================================================
|
|
381
|
+
buildMessageEvent(agentName, prompt, channelId, messageTs, userId, wasMentioned,
|
|
382
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
383
|
+
say) {
|
|
384
|
+
const reply = async (content) => {
|
|
385
|
+
await say({
|
|
386
|
+
text: markdownToMrkdwn(content),
|
|
387
|
+
});
|
|
388
|
+
this.messagesSent++;
|
|
389
|
+
};
|
|
390
|
+
const startProcessingIndicator = () => {
|
|
391
|
+
// Add hourglass reaction while processing
|
|
392
|
+
if (this.app?.client) {
|
|
393
|
+
this.app.client.reactions
|
|
394
|
+
.add({
|
|
395
|
+
channel: channelId,
|
|
396
|
+
name: "hourglass_flowing_sand",
|
|
397
|
+
timestamp: messageTs,
|
|
398
|
+
})
|
|
399
|
+
.catch(() => {
|
|
400
|
+
// Ignore reaction errors — not critical
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
return () => {
|
|
404
|
+
// Remove hourglass reaction when done
|
|
405
|
+
if (this.app?.client) {
|
|
406
|
+
this.app.client.reactions
|
|
407
|
+
.remove({
|
|
408
|
+
channel: channelId,
|
|
409
|
+
name: "hourglass_flowing_sand",
|
|
410
|
+
timestamp: messageTs,
|
|
411
|
+
})
|
|
412
|
+
.catch(() => {
|
|
413
|
+
// Ignore reaction errors — not critical
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
};
|
|
418
|
+
return {
|
|
419
|
+
agentName,
|
|
420
|
+
prompt,
|
|
421
|
+
metadata: {
|
|
422
|
+
channelId,
|
|
423
|
+
messageTs,
|
|
424
|
+
userId,
|
|
425
|
+
wasMentioned,
|
|
426
|
+
},
|
|
427
|
+
reply,
|
|
428
|
+
startProcessingIndicator,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
// ===========================================================================
|
|
432
|
+
// Type-Safe Event Emitter Overrides
|
|
433
|
+
// ===========================================================================
|
|
434
|
+
emit(event, payload) {
|
|
435
|
+
return super.emit(event, payload);
|
|
436
|
+
}
|
|
437
|
+
on(event, listener) {
|
|
438
|
+
return super.on(event, listener);
|
|
439
|
+
}
|
|
440
|
+
once(event, listener) {
|
|
441
|
+
return super.once(event, listener);
|
|
442
|
+
}
|
|
443
|
+
off(event, listener) {
|
|
444
|
+
return super.off(event, listener);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
//# sourceMappingURL=slack-connector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack-connector.js","sourceRoot":"","sources":["../src/slack-connector.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Slack connector
|
|
3
|
+
*
|
|
4
|
+
* Provides interfaces for connector configuration, state tracking,
|
|
5
|
+
* and event definitions.
|
|
6
|
+
*/
|
|
7
|
+
import type { EventEmitter } from "node:events";
|
|
8
|
+
/**
|
|
9
|
+
* Slack connector connection status
|
|
10
|
+
*/
|
|
11
|
+
export type SlackConnectionStatus = "disconnected" | "connecting" | "connected" | "reconnecting" | "disconnecting" | "error";
|
|
12
|
+
/**
|
|
13
|
+
* Current state of the Slack connector
|
|
14
|
+
*/
|
|
15
|
+
export interface SlackConnectorState {
|
|
16
|
+
/** Current connection status */
|
|
17
|
+
status: SlackConnectionStatus;
|
|
18
|
+
/** ISO timestamp when the connector connected */
|
|
19
|
+
connectedAt: string | null;
|
|
20
|
+
/** ISO timestamp when the connector disconnected */
|
|
21
|
+
disconnectedAt: string | null;
|
|
22
|
+
/** Number of reconnect attempts */
|
|
23
|
+
reconnectAttempts: number;
|
|
24
|
+
/** Last error message */
|
|
25
|
+
lastError: string | null;
|
|
26
|
+
/** Bot user info (only present when connected) */
|
|
27
|
+
botUser: {
|
|
28
|
+
id: string;
|
|
29
|
+
username: string;
|
|
30
|
+
} | null;
|
|
31
|
+
/** Message statistics */
|
|
32
|
+
messageStats: {
|
|
33
|
+
received: number;
|
|
34
|
+
sent: number;
|
|
35
|
+
ignored: number;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Options for creating a SlackConnector
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* Per-channel configuration
|
|
43
|
+
*/
|
|
44
|
+
export interface SlackChannelConfig {
|
|
45
|
+
/** Channel message mode: "mention" = only @mentions, "auto" = all messages */
|
|
46
|
+
mode: "mention" | "auto";
|
|
47
|
+
/** Number of context messages (future use) */
|
|
48
|
+
contextMessages: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Options for creating a SlackConnector
|
|
52
|
+
*/
|
|
53
|
+
export interface SlackConnectorOptions {
|
|
54
|
+
/** Slack Bot Token (xoxb-...) */
|
|
55
|
+
botToken: string;
|
|
56
|
+
/** Slack App Token for Socket Mode (xapp-...) */
|
|
57
|
+
appToken: string;
|
|
58
|
+
/** Map of channel ID to agent name for routing */
|
|
59
|
+
channelAgentMap: Map<string, string>;
|
|
60
|
+
/** Per-channel configuration (keyed by channel ID) */
|
|
61
|
+
channelConfigs?: Map<string, SlackChannelConfig>;
|
|
62
|
+
/** Session managers keyed by agent name */
|
|
63
|
+
sessionManagers: Map<string, ISlackSessionManager>;
|
|
64
|
+
/** Logger for connector operations */
|
|
65
|
+
logger?: SlackConnectorLogger;
|
|
66
|
+
/** State directory for persistence */
|
|
67
|
+
stateDir?: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Logger interface for Slack connector operations
|
|
71
|
+
*/
|
|
72
|
+
export interface SlackConnectorLogger {
|
|
73
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
74
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
75
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
76
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Message event payload from SlackConnector
|
|
80
|
+
*/
|
|
81
|
+
export interface SlackMessageEvent {
|
|
82
|
+
/** Name of the agent handling this message */
|
|
83
|
+
agentName: string;
|
|
84
|
+
/** The processed prompt text */
|
|
85
|
+
prompt: string;
|
|
86
|
+
/** Slack-specific metadata */
|
|
87
|
+
metadata: {
|
|
88
|
+
/** Channel ID where the message was sent */
|
|
89
|
+
channelId: string;
|
|
90
|
+
/** Message timestamp */
|
|
91
|
+
messageTs: string;
|
|
92
|
+
/** User ID who sent the message */
|
|
93
|
+
userId: string;
|
|
94
|
+
/** Whether this was triggered by a mention */
|
|
95
|
+
wasMentioned: boolean;
|
|
96
|
+
};
|
|
97
|
+
/** Function to send a reply in the same thread */
|
|
98
|
+
reply: (content: string) => Promise<void>;
|
|
99
|
+
/** Add hourglass reaction while processing, returns remove function */
|
|
100
|
+
startProcessingIndicator: () => () => void;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Error event payload from SlackConnector
|
|
104
|
+
*/
|
|
105
|
+
export interface SlackErrorEvent {
|
|
106
|
+
agentName: string;
|
|
107
|
+
error: Error;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Interface for the Slack connector
|
|
111
|
+
*/
|
|
112
|
+
/**
|
|
113
|
+
* Parameters for uploading a file to Slack
|
|
114
|
+
*/
|
|
115
|
+
export interface SlackFileUploadParams {
|
|
116
|
+
/** Channel ID to upload to */
|
|
117
|
+
channelId: string;
|
|
118
|
+
/** File contents */
|
|
119
|
+
fileBuffer: Buffer;
|
|
120
|
+
/** Filename for the upload */
|
|
121
|
+
filename: string;
|
|
122
|
+
/** Optional message to accompany the file */
|
|
123
|
+
message?: string;
|
|
124
|
+
}
|
|
125
|
+
export interface ISlackConnector extends EventEmitter {
|
|
126
|
+
/** Connect to Slack via Socket Mode */
|
|
127
|
+
connect(): Promise<void>;
|
|
128
|
+
/** Disconnect from Slack */
|
|
129
|
+
disconnect(): Promise<void>;
|
|
130
|
+
/** Check if connected */
|
|
131
|
+
isConnected(): boolean;
|
|
132
|
+
/** Get current state */
|
|
133
|
+
getState(): SlackConnectorState;
|
|
134
|
+
/** Upload a file to a Slack channel/thread */
|
|
135
|
+
uploadFile(params: SlackFileUploadParams): Promise<{
|
|
136
|
+
fileId: string;
|
|
137
|
+
}>;
|
|
138
|
+
/** Type-safe event subscription */
|
|
139
|
+
on<K extends SlackConnectorEventName>(event: K, listener: (payload: SlackConnectorEventMap[K]) => void): this;
|
|
140
|
+
once<K extends SlackConnectorEventName>(event: K, listener: (payload: SlackConnectorEventMap[K]) => void): this;
|
|
141
|
+
off<K extends SlackConnectorEventName>(event: K, listener: (payload: SlackConnectorEventMap[K]) => void): this;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Session manager interface for Slack
|
|
145
|
+
*
|
|
146
|
+
* Keyed by channelId (matching Discord's approach).
|
|
147
|
+
*/
|
|
148
|
+
export interface ISlackSessionManager {
|
|
149
|
+
readonly agentName: string;
|
|
150
|
+
getOrCreateSession(channelId: string): Promise<{
|
|
151
|
+
sessionId: string;
|
|
152
|
+
isNew: boolean;
|
|
153
|
+
}>;
|
|
154
|
+
getSession(channelId: string): Promise<{
|
|
155
|
+
sessionId: string;
|
|
156
|
+
lastMessageAt: string;
|
|
157
|
+
} | null>;
|
|
158
|
+
setSession(channelId: string, sessionId: string): Promise<void>;
|
|
159
|
+
touchSession(channelId: string): Promise<void>;
|
|
160
|
+
clearSession(channelId: string): Promise<boolean>;
|
|
161
|
+
cleanupExpiredSessions(): Promise<number>;
|
|
162
|
+
getActiveSessionCount(): Promise<number>;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Strongly-typed event map for SlackConnector
|
|
166
|
+
*
|
|
167
|
+
* Uses object syntax matching Discord's DiscordConnectorEventMap pattern.
|
|
168
|
+
*/
|
|
169
|
+
export interface SlackConnectorEventMap {
|
|
170
|
+
/** Emitted when connection is established and ready */
|
|
171
|
+
ready: {
|
|
172
|
+
botUser: {
|
|
173
|
+
id: string;
|
|
174
|
+
username: string;
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
/** Emitted when connection is lost */
|
|
178
|
+
disconnect: {
|
|
179
|
+
reason: string;
|
|
180
|
+
};
|
|
181
|
+
/** Emitted on connection error */
|
|
182
|
+
error: {
|
|
183
|
+
error: Error;
|
|
184
|
+
};
|
|
185
|
+
/** Emitted when a processable message is received */
|
|
186
|
+
message: SlackMessageEvent;
|
|
187
|
+
/** Emitted when a message is ignored */
|
|
188
|
+
messageIgnored: {
|
|
189
|
+
agentName: string;
|
|
190
|
+
reason: "not_configured" | "bot_message" | "no_agent_resolved" | "empty_prompt";
|
|
191
|
+
channelId: string;
|
|
192
|
+
messageTs: string;
|
|
193
|
+
};
|
|
194
|
+
/** Emitted when a prefix command is executed */
|
|
195
|
+
commandExecuted: {
|
|
196
|
+
agentName: string;
|
|
197
|
+
commandName: string;
|
|
198
|
+
userId: string;
|
|
199
|
+
channelId: string;
|
|
200
|
+
};
|
|
201
|
+
/** Emitted when a session is created, resumed, expired, or cleared */
|
|
202
|
+
sessionLifecycle: {
|
|
203
|
+
agentName: string;
|
|
204
|
+
event: "created" | "resumed" | "expired" | "cleared";
|
|
205
|
+
channelId: string;
|
|
206
|
+
sessionId: string;
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
export type SlackConnectorEventName = keyof SlackConnectorEventMap;
|
|
210
|
+
export type SlackConnectorEventPayload<E extends SlackConnectorEventName> = SlackConnectorEventMap[E];
|
|
211
|
+
//# sourceMappingURL=types.d.ts.map
|