@memberjunction/messaging-adapters 0.0.1 → 5.18.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 (58) hide show
  1. package/README.md +231 -43
  2. package/dist/base/BaseMessagingAdapter.d.ts +428 -0
  3. package/dist/base/BaseMessagingAdapter.d.ts.map +1 -0
  4. package/dist/base/BaseMessagingAdapter.js +934 -0
  5. package/dist/base/BaseMessagingAdapter.js.map +1 -0
  6. package/dist/base/message-formatter.d.ts +70 -0
  7. package/dist/base/message-formatter.d.ts.map +1 -0
  8. package/dist/base/message-formatter.js +201 -0
  9. package/dist/base/message-formatter.js.map +1 -0
  10. package/dist/base/types.d.ts +211 -0
  11. package/dist/base/types.d.ts.map +1 -0
  12. package/dist/base/types.js +6 -0
  13. package/dist/base/types.js.map +1 -0
  14. package/dist/index.d.ts +72 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +76 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/slack/SlackAdapter.d.ts +141 -0
  19. package/dist/slack/SlackAdapter.d.ts.map +1 -0
  20. package/dist/slack/SlackAdapter.js +291 -0
  21. package/dist/slack/SlackAdapter.js.map +1 -0
  22. package/dist/slack/SlackMessagingExtension.d.ts +148 -0
  23. package/dist/slack/SlackMessagingExtension.d.ts.map +1 -0
  24. package/dist/slack/SlackMessagingExtension.js +433 -0
  25. package/dist/slack/SlackMessagingExtension.js.map +1 -0
  26. package/dist/slack/slack-block-builder.d.ts +133 -0
  27. package/dist/slack/slack-block-builder.d.ts.map +1 -0
  28. package/dist/slack/slack-block-builder.js +748 -0
  29. package/dist/slack/slack-block-builder.js.map +1 -0
  30. package/dist/slack/slack-formatter.d.ts +37 -0
  31. package/dist/slack/slack-formatter.d.ts.map +1 -0
  32. package/dist/slack/slack-formatter.js +116 -0
  33. package/dist/slack/slack-formatter.js.map +1 -0
  34. package/dist/slack/slack-interactivity.d.ts +38 -0
  35. package/dist/slack/slack-interactivity.d.ts.map +1 -0
  36. package/dist/slack/slack-interactivity.js +414 -0
  37. package/dist/slack/slack-interactivity.js.map +1 -0
  38. package/dist/slack/slack-routes.d.ts +35 -0
  39. package/dist/slack/slack-routes.d.ts.map +1 -0
  40. package/dist/slack/slack-routes.js +98 -0
  41. package/dist/slack/slack-routes.js.map +1 -0
  42. package/dist/teams/TeamsAdapter.d.ts +155 -0
  43. package/dist/teams/TeamsAdapter.d.ts.map +1 -0
  44. package/dist/teams/TeamsAdapter.js +383 -0
  45. package/dist/teams/TeamsAdapter.js.map +1 -0
  46. package/dist/teams/TeamsMessagingExtension.d.ts +75 -0
  47. package/dist/teams/TeamsMessagingExtension.d.ts.map +1 -0
  48. package/dist/teams/TeamsMessagingExtension.js +176 -0
  49. package/dist/teams/TeamsMessagingExtension.js.map +1 -0
  50. package/dist/teams/teams-card-builder.d.ts +94 -0
  51. package/dist/teams/teams-card-builder.d.ts.map +1 -0
  52. package/dist/teams/teams-card-builder.js +648 -0
  53. package/dist/teams/teams-card-builder.js.map +1 -0
  54. package/dist/teams/teams-formatter.d.ts +39 -0
  55. package/dist/teams/teams-formatter.d.ts.map +1 -0
  56. package/dist/teams/teams-formatter.js +107 -0
  57. package/dist/teams/teams-formatter.js.map +1 -0
  58. package/package.json +40 -7
@@ -0,0 +1,148 @@
1
+ /**
2
+ * @module @memberjunction/messaging-adapters
3
+ * @description Slack Server Extension — registers webhook routes and delegates to SlackAdapter.
4
+ *
5
+ * This is the entry point for Slack integration. It extends `BaseServerExtension`
6
+ * to plug into MJServer's extension framework, registering a POST webhook endpoint
7
+ * that receives Slack Events API payloads.
8
+ *
9
+ * ## Slack App Setup
10
+ *
11
+ * 1. Create a Slack App at https://api.slack.com/apps
12
+ * 2. Enable Event Subscriptions and point the Request URL to `{your-server}/webhook/slack`
13
+ * 3. Subscribe to bot events: `message.im`, `message.channels`, `message.groups`, `app_mention`
14
+ * - `message.im` — direct messages to the bot
15
+ * - `message.channels` / `message.groups` — thread replies in public/private channels
16
+ * - `app_mention` — @mentions of the bot in channels
17
+ * 4. Add OAuth scopes: `chat:write`, `channels:history`, `groups:history`,
18
+ * `im:history`, `users:read`, `users:read.email`, `app_mentions:read`
19
+ * 5. Install the app to your workspace
20
+ * 6. Copy the Bot User OAuth Token and Signing Secret to your `mj.config.cjs`
21
+ *
22
+ * ## Configuration
23
+ *
24
+ * ```javascript
25
+ * // mj.config.cjs
26
+ * serverExtensions: [{
27
+ * Enabled: true,
28
+ * DriverClass: 'SlackMessagingExtension',
29
+ * RootPath: '/webhook/slack',
30
+ * Settings: {
31
+ * DefaultAgentName: 'Sage',
32
+ * ContextUserEmail: 'bot@company.com',
33
+ * BotToken: process.env.SLACK_BOT_TOKEN,
34
+ * SigningSecret: process.env.SLACK_SIGNING_SECRET,
35
+ * ConnectionMode: 'http', // or 'socket' for Socket Mode
36
+ * MaxThreadMessages: 50,
37
+ * StreamingUpdateIntervalMs: 1500,
38
+ * }
39
+ * }]
40
+ * ```
41
+ */
42
+ import { Application } from 'express';
43
+ import { BaseServerExtension, ServerExtensionConfig, ExtensionInitResult, ExtensionHealthResult } from '@memberjunction/server-extensions-core';
44
+ /**
45
+ * Server Extension that registers Slack webhook routes and delegates
46
+ * message handling to the `SlackAdapter`.
47
+ *
48
+ * Supports two connection modes:
49
+ * - **HTTP** (default): Registers a POST endpoint for Slack Events API webhooks
50
+ * - **Socket Mode**: Uses Slack's WebSocket-based Socket Mode (no public URL needed,
51
+ * ideal for local development)
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * // Auto-discovered by MJServer when package is imported and config is present
56
+ * // No manual instantiation needed — just add to mj.config.cjs
57
+ * ```
58
+ */
59
+ export declare class SlackMessagingExtension extends BaseServerExtension {
60
+ /** The Slack adapter handling message processing. */
61
+ private adapter;
62
+ /** Slack WebClient for interactivity handlers (modals, etc.). */
63
+ private interactClient;
64
+ /** The signing secret for webhook verification. */
65
+ private signingSecret;
66
+ /** Slash command → agent name mapping from config. */
67
+ private slashCommands;
68
+ /** Socket Mode client (only used when ConnectionMode is 'socket'). */
69
+ private socketModeClient;
70
+ /** The active connection mode for health reporting. */
71
+ private connectionMode;
72
+ /**
73
+ * Initialize the Slack extension.
74
+ *
75
+ * Creates and initializes the `SlackAdapter`, then sets up either:
76
+ * - **HTTP mode** (default): POST webhook endpoint for Slack Events API
77
+ * - **Socket Mode**: WebSocket connection using an App-Level Token (no public URL needed)
78
+ */
79
+ Initialize(app: Application, config: ServerExtensionConfig): Promise<ExtensionInitResult>;
80
+ /**
81
+ * Shut down the Slack extension. Releases the adapter and disconnects Socket Mode.
82
+ */
83
+ Shutdown(): Promise<void>;
84
+ /**
85
+ * Health check for the Slack extension.
86
+ * Reports whether the adapter is initialized and ready.
87
+ */
88
+ HealthCheck(): Promise<ExtensionHealthResult>;
89
+ /**
90
+ * Set up HTTP webhook mode: register POST endpoints for Slack Events API
91
+ * and Slack Interactivity payloads.
92
+ */
93
+ private initializeHttpMode;
94
+ /**
95
+ * Handle an incoming Slack webhook request (HTTP mode).
96
+ *
97
+ * 1. Verify the request signature (if signing secret is configured)
98
+ * 2. Handle URL verification challenges (Slack sends these during setup)
99
+ * 3. Acknowledge immediately (Slack requires response within 3 seconds)
100
+ * 4. Process the message asynchronously via the adapter
101
+ */
102
+ private handleWebhook;
103
+ /**
104
+ * Set up Socket Mode: connect via WebSocket using an App-Level Token.
105
+ *
106
+ * Socket Mode is ideal for local development — no public URL or ngrok needed.
107
+ * Requires an App-Level Token (`xapp-...`) with `connections:write` scope.
108
+ */
109
+ private initializeSocketMode;
110
+ /**
111
+ * Handle Slack interactivity payloads (button clicks, modal submissions).
112
+ * Slack sends these as `application/x-www-form-urlencoded` with a `payload` JSON field.
113
+ */
114
+ private handleInteraction;
115
+ /**
116
+ * Handle a Slack slash command (e.g., `/research what is quantum computing?`).
117
+ *
118
+ * Slack sends slash commands as `application/x-www-form-urlencoded` with fields:
119
+ * `command`, `text`, `user_id`, `user_name`, `channel_id`, `channel_name`, `trigger_id`.
120
+ *
121
+ * Must respond within 3 seconds. We acknowledge immediately with a brief message,
122
+ * then route to the agent pipeline asynchronously (which posts results to the channel).
123
+ */
124
+ private handleSlashCommand;
125
+ /**
126
+ * Resolve a slash command string (e.g., `/research`) to an agent name.
127
+ * Tries exact match first, then strips the leading `/` and matches case-insensitively.
128
+ */
129
+ private resolveSlashCommandAgent;
130
+ /**
131
+ * Build the slash command → agent name map.
132
+ * Auto-generates a command for every loaded agent using its first word
133
+ * (e.g., "Research Agent" → `/research`). Explicit config overrides take precedence.
134
+ */
135
+ private buildSlashCommandMap;
136
+ /** Format the list of configured slash commands for display. */
137
+ private listSlashCommands;
138
+ /**
139
+ * Post a visible thread-root message for the slash command, then construct
140
+ * an IncomingMessage with that thread's `ts` so all responses appear as replies.
141
+ */
142
+ private processSlashCommandAsync;
143
+ /**
144
+ * Process a Slack event from either HTTP webhook or Socket Mode.
145
+ */
146
+ private processSlackEvent;
147
+ }
148
+ //# sourceMappingURL=SlackMessagingExtension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackMessagingExtension.d.ts","sourceRoot":"","sources":["../../src/slack/SlackMessagingExtension.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAgB,EAAE,WAAW,EAA6B,MAAM,SAAS,CAAC;AAK1E,OAAO,EACH,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACxB,MAAM,wCAAwC,CAAC;AAMhD;;;;;;;;;;;;;;GAcG;AACH,qBACa,uBAAwB,SAAQ,mBAAmB;IAC5D,qDAAqD;IACrD,OAAO,CAAC,OAAO,CAA6B;IAE5C,iEAAiE;IACjE,OAAO,CAAC,cAAc,CAA0B;IAEhD,mDAAmD;IACnD,OAAO,CAAC,aAAa,CAAc;IAEnC,sDAAsD;IACtD,OAAO,CAAC,aAAa,CAA8B;IAEnD,sEAAsE;IACtE,OAAO,CAAC,gBAAgB,CAAiC;IAEzD,uDAAuD;IACvD,OAAO,CAAC,cAAc,CAA6B;IAEnD;;;;;;OAMG;IACG,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAkC/F;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAenD;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA0C1B;;;;;;;OAOG;YACW,aAAa;IAsB3B;;;;;OAKG;YACW,oBAAoB;IAkClC;;;OAGG;YACW,iBAAiB;IAwB/B;;;;;;;;OAQG;YACW,kBAAkB;IA2BhC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAiBhC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAe5B,gEAAgE;IAChE,OAAO,CAAC,iBAAiB;IAMzB;;;OAGG;YACW,wBAAwB;IAwDtC;;OAEG;YACW,iBAAiB;CAiClC"}
@@ -0,0 +1,433 @@
1
+ /**
2
+ * @module @memberjunction/messaging-adapters
3
+ * @description Slack Server Extension — registers webhook routes and delegates to SlackAdapter.
4
+ *
5
+ * This is the entry point for Slack integration. It extends `BaseServerExtension`
6
+ * to plug into MJServer's extension framework, registering a POST webhook endpoint
7
+ * that receives Slack Events API payloads.
8
+ *
9
+ * ## Slack App Setup
10
+ *
11
+ * 1. Create a Slack App at https://api.slack.com/apps
12
+ * 2. Enable Event Subscriptions and point the Request URL to `{your-server}/webhook/slack`
13
+ * 3. Subscribe to bot events: `message.im`, `message.channels`, `message.groups`, `app_mention`
14
+ * - `message.im` — direct messages to the bot
15
+ * - `message.channels` / `message.groups` — thread replies in public/private channels
16
+ * - `app_mention` — @mentions of the bot in channels
17
+ * 4. Add OAuth scopes: `chat:write`, `channels:history`, `groups:history`,
18
+ * `im:history`, `users:read`, `users:read.email`, `app_mentions:read`
19
+ * 5. Install the app to your workspace
20
+ * 6. Copy the Bot User OAuth Token and Signing Secret to your `mj.config.cjs`
21
+ *
22
+ * ## Configuration
23
+ *
24
+ * ```javascript
25
+ * // mj.config.cjs
26
+ * serverExtensions: [{
27
+ * Enabled: true,
28
+ * DriverClass: 'SlackMessagingExtension',
29
+ * RootPath: '/webhook/slack',
30
+ * Settings: {
31
+ * DefaultAgentName: 'Sage',
32
+ * ContextUserEmail: 'bot@company.com',
33
+ * BotToken: process.env.SLACK_BOT_TOKEN,
34
+ * SigningSecret: process.env.SLACK_SIGNING_SECRET,
35
+ * ConnectionMode: 'http', // or 'socket' for Socket Mode
36
+ * MaxThreadMessages: 50,
37
+ * StreamingUpdateIntervalMs: 1500,
38
+ * }
39
+ * }]
40
+ * ```
41
+ */
42
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
43
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
44
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
45
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
46
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
47
+ };
48
+ import express, { Router } from 'express';
49
+ import { WebClient } from '@slack/web-api';
50
+ import { RegisterClass } from '@memberjunction/global';
51
+ import { LogError, LogStatus } from '@memberjunction/core';
52
+ import { SocketModeClient } from '@slack/socket-mode';
53
+ import { BaseServerExtension } from '@memberjunction/server-extensions-core';
54
+ import { SlackAdapter } from './SlackAdapter.js';
55
+ import { verifySlackSignature } from './slack-routes.js';
56
+ import { handleSlackInteraction } from './slack-interactivity.js';
57
+ /**
58
+ * Server Extension that registers Slack webhook routes and delegates
59
+ * message handling to the `SlackAdapter`.
60
+ *
61
+ * Supports two connection modes:
62
+ * - **HTTP** (default): Registers a POST endpoint for Slack Events API webhooks
63
+ * - **Socket Mode**: Uses Slack's WebSocket-based Socket Mode (no public URL needed,
64
+ * ideal for local development)
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * // Auto-discovered by MJServer when package is imported and config is present
69
+ * // No manual instantiation needed — just add to mj.config.cjs
70
+ * ```
71
+ */
72
+ let SlackMessagingExtension = class SlackMessagingExtension extends BaseServerExtension {
73
+ constructor() {
74
+ super(...arguments);
75
+ /** The Slack adapter handling message processing. */
76
+ this.adapter = null;
77
+ /** Slack WebClient for interactivity handlers (modals, etc.). */
78
+ this.interactClient = null;
79
+ /** The signing secret for webhook verification. */
80
+ this.signingSecret = '';
81
+ /** Slash command → agent name mapping from config. */
82
+ this.slashCommands = {};
83
+ /** Socket Mode client (only used when ConnectionMode is 'socket'). */
84
+ this.socketModeClient = null;
85
+ /** The active connection mode for health reporting. */
86
+ this.connectionMode = 'http';
87
+ }
88
+ /**
89
+ * Initialize the Slack extension.
90
+ *
91
+ * Creates and initializes the `SlackAdapter`, then sets up either:
92
+ * - **HTTP mode** (default): POST webhook endpoint for Slack Events API
93
+ * - **Socket Mode**: WebSocket connection using an App-Level Token (no public URL needed)
94
+ */
95
+ async Initialize(app, config) {
96
+ try {
97
+ // The Zod config pipeline may strip unknown keys from Settings, so we
98
+ // fall back to env vars for settings that may be missing.
99
+ const settings = config.Settings;
100
+ if (!settings.ExplorerBaseURL && process.env.MJ_EXPLORER_BASE_URL) {
101
+ settings.ExplorerBaseURL = process.env.MJ_EXPLORER_BASE_URL;
102
+ }
103
+ LogStatus(`[Slack] Extension settings keys: ${Object.keys(settings).join(', ')}, ExplorerBaseURL=${settings.ExplorerBaseURL ?? 'NOT SET'}`);
104
+ this.signingSecret = settings.SigningSecret ?? '';
105
+ this.connectionMode = settings.ConnectionMode ?? 'http';
106
+ // Create and initialize the Slack adapter + interactivity client
107
+ this.adapter = new SlackAdapter(settings);
108
+ this.interactClient = new WebClient(settings.BotToken);
109
+ await this.adapter.Initialize();
110
+ // Build slash command map: auto-generate from loaded agents + merge config overrides
111
+ this.slashCommands = this.buildSlashCommandMap(settings.SlashCommands);
112
+ if (this.connectionMode === 'socket') {
113
+ return await this.initializeSocketMode(settings);
114
+ }
115
+ else {
116
+ return this.initializeHttpMode(app, config, settings);
117
+ }
118
+ }
119
+ catch (error) {
120
+ const message = error instanceof Error ? error.message : String(error);
121
+ return {
122
+ Success: false,
123
+ Message: `Failed to initialize Slack extension: ${message}`
124
+ };
125
+ }
126
+ }
127
+ /**
128
+ * Shut down the Slack extension. Releases the adapter and disconnects Socket Mode.
129
+ */
130
+ async Shutdown() {
131
+ LogStatus('Shutting down Slack messaging extension');
132
+ if (this.socketModeClient) {
133
+ await this.socketModeClient.disconnect();
134
+ this.socketModeClient = null;
135
+ }
136
+ this.adapter = null;
137
+ }
138
+ /**
139
+ * Health check for the Slack extension.
140
+ * Reports whether the adapter is initialized and ready.
141
+ */
142
+ async HealthCheck() {
143
+ return {
144
+ Healthy: this.adapter !== null,
145
+ Name: 'SlackMessagingExtension',
146
+ Details: {
147
+ adapterInitialized: this.adapter !== null,
148
+ connectionMode: this.connectionMode,
149
+ signatureVerificationEnabled: this.signingSecret.length > 0,
150
+ socketModeConnected: this.socketModeClient !== null
151
+ }
152
+ };
153
+ }
154
+ // ─── HTTP Mode ───────────────────────────────────────────────────────
155
+ /**
156
+ * Set up HTTP webhook mode: register POST endpoints for Slack Events API
157
+ * and Slack Interactivity payloads.
158
+ */
159
+ initializeHttpMode(app, config, settings) {
160
+ const router = Router();
161
+ router.use(express.json({
162
+ limit: '1mb',
163
+ verify: (req, _res, buf) => {
164
+ req.rawBody = buf.toString('utf-8');
165
+ }
166
+ }));
167
+ router.post('/', this.handleWebhook.bind(this));
168
+ // Interactivity endpoint for button clicks, modal submissions, etc.
169
+ // Slack sends these as application/x-www-form-urlencoded with a `payload` JSON field
170
+ const interactRouter = Router();
171
+ interactRouter.use(express.urlencoded({ extended: true }));
172
+ interactRouter.post('/', this.handleInteraction.bind(this));
173
+ app.use(config.RootPath + '/interact', interactRouter);
174
+ // Slash command endpoint — Slack sends these as application/x-www-form-urlencoded
175
+ const slashRouter = Router();
176
+ slashRouter.use(express.urlencoded({ extended: true }));
177
+ slashRouter.post('/', this.handleSlashCommand.bind(this));
178
+ app.use(config.RootPath + '/slash', slashRouter);
179
+ app.use(config.RootPath, router);
180
+ const registeredRoutes = [
181
+ `POST ${config.RootPath}`,
182
+ `POST ${config.RootPath}/interact`,
183
+ `POST ${config.RootPath}/slash`,
184
+ ];
185
+ return {
186
+ Success: true,
187
+ Message: `Slack extension loaded (HTTP mode) for agent ${settings.DefaultAgentName}`,
188
+ RegisteredRoutes: registeredRoutes
189
+ };
190
+ }
191
+ /**
192
+ * Handle an incoming Slack webhook request (HTTP mode).
193
+ *
194
+ * 1. Verify the request signature (if signing secret is configured)
195
+ * 2. Handle URL verification challenges (Slack sends these during setup)
196
+ * 3. Acknowledge immediately (Slack requires response within 3 seconds)
197
+ * 4. Process the message asynchronously via the adapter
198
+ */
199
+ async handleWebhook(req, res) {
200
+ // 1. Verify signature
201
+ if (this.signingSecret && !verifySlackSignature(req, this.signingSecret)) {
202
+ res.status(401).send('Invalid signature');
203
+ return;
204
+ }
205
+ // 2. Handle URL verification challenge (sent during app setup)
206
+ if (req.body?.type === 'url_verification') {
207
+ res.json({ challenge: req.body.challenge });
208
+ return;
209
+ }
210
+ // 3. Acknowledge immediately (Slack requires < 3s response)
211
+ res.status(200).send();
212
+ // 4. Process asynchronously
213
+ await this.processSlackEvent(req.body?.event);
214
+ }
215
+ // ─── Socket Mode ─────────────────────────────────────────────────────
216
+ /**
217
+ * Set up Socket Mode: connect via WebSocket using an App-Level Token.
218
+ *
219
+ * Socket Mode is ideal for local development — no public URL or ngrok needed.
220
+ * Requires an App-Level Token (`xapp-...`) with `connections:write` scope.
221
+ */
222
+ async initializeSocketMode(settings) {
223
+ const appToken = settings.AppToken;
224
+ if (!appToken) {
225
+ return {
226
+ Success: false,
227
+ Message: 'Socket Mode requires an AppToken (xapp-...) in Settings'
228
+ };
229
+ }
230
+ this.socketModeClient = new SocketModeClient({ appToken });
231
+ // Listen for message and app_mention events
232
+ this.socketModeClient.on('message', async ({ event, ack }) => {
233
+ await ack();
234
+ await this.processSlackEvent(event);
235
+ });
236
+ this.socketModeClient.on('app_mention', async ({ event, ack }) => {
237
+ await ack();
238
+ await this.processSlackEvent(event);
239
+ });
240
+ await this.socketModeClient.start();
241
+ LogStatus('Slack Socket Mode connected');
242
+ return {
243
+ Success: true,
244
+ Message: `Slack extension loaded (Socket Mode) for agent ${settings.DefaultAgentName}`,
245
+ RegisteredRoutes: ['WebSocket (Socket Mode)']
246
+ };
247
+ }
248
+ // ─── Interactivity ─────────────────────────────────────────────────────
249
+ /**
250
+ * Handle Slack interactivity payloads (button clicks, modal submissions).
251
+ * Slack sends these as `application/x-www-form-urlencoded` with a `payload` JSON field.
252
+ */
253
+ async handleInteraction(req, res) {
254
+ // Acknowledge immediately
255
+ res.status(200).send();
256
+ const payloadStr = req.body?.payload;
257
+ if (!payloadStr) {
258
+ LogStatus('Slack interact: no payload in request');
259
+ return;
260
+ }
261
+ if (!this.interactClient || !this.adapter) {
262
+ LogStatus('Slack interact: extension not fully initialized');
263
+ return;
264
+ }
265
+ try {
266
+ await handleSlackInteraction(payloadStr, this.interactClient, this.adapter);
267
+ }
268
+ catch (error) {
269
+ LogError('Error handling Slack interaction:', undefined, error);
270
+ }
271
+ }
272
+ // ─── Slash Commands ─────────────────────────────────────────────────
273
+ /**
274
+ * Handle a Slack slash command (e.g., `/research what is quantum computing?`).
275
+ *
276
+ * Slack sends slash commands as `application/x-www-form-urlencoded` with fields:
277
+ * `command`, `text`, `user_id`, `user_name`, `channel_id`, `channel_name`, `trigger_id`.
278
+ *
279
+ * Must respond within 3 seconds. We acknowledge immediately with a brief message,
280
+ * then route to the agent pipeline asynchronously (which posts results to the channel).
281
+ */
282
+ async handleSlashCommand(req, res) {
283
+ const { command, text, user_id, user_name, channel_id } = req.body;
284
+ LogStatus(`Slack slash command: command=${command}, text="${text}", user=${user_id}, channel=${channel_id}`);
285
+ // Look up the agent for this command
286
+ const agentName = this.resolveSlashCommandAgent(command);
287
+ if (!agentName) {
288
+ res.json({
289
+ response_type: 'ephemeral',
290
+ text: `Unknown command \`${command}\`. Configured commands: ${this.listSlashCommands()}`
291
+ });
292
+ return;
293
+ }
294
+ // Acknowledge within 3 seconds — visible only to the user
295
+ res.json({
296
+ response_type: 'ephemeral',
297
+ text: `_Routing to *${agentName}*..._`
298
+ });
299
+ // Process asynchronously — post a thread-root message first, then route to the agent
300
+ this.processSlashCommandAsync(agentName, text ?? '', user_id, user_name, channel_id).catch(error => {
301
+ LogError(`Error processing slash command for agent '${agentName}':`, undefined, error);
302
+ });
303
+ }
304
+ /**
305
+ * Resolve a slash command string (e.g., `/research`) to an agent name.
306
+ * Tries exact match first, then strips the leading `/` and matches case-insensitively.
307
+ */
308
+ resolveSlashCommandAgent(command) {
309
+ // Exact match (e.g., `/research` → 'Research Agent')
310
+ if (this.slashCommands[command]) {
311
+ return this.slashCommands[command];
312
+ }
313
+ // Case-insensitive match
314
+ const lowerCmd = command.toLowerCase();
315
+ for (const [key, value] of Object.entries(this.slashCommands)) {
316
+ if (key.toLowerCase() === lowerCmd) {
317
+ return value;
318
+ }
319
+ }
320
+ return null;
321
+ }
322
+ /**
323
+ * Build the slash command → agent name map.
324
+ * Auto-generates a command for every loaded agent using its first word
325
+ * (e.g., "Research Agent" → `/research`). Explicit config overrides take precedence.
326
+ */
327
+ buildSlashCommandMap(configuredCommands) {
328
+ const autoCommands = {};
329
+ for (const name of (this.adapter?.AvailableAgentNames ?? [])) {
330
+ const firstWord = name.split(/\s+/)[0].toLowerCase();
331
+ const cmd = `/${firstWord}`;
332
+ if (!autoCommands[cmd]) {
333
+ autoCommands[cmd] = name;
334
+ }
335
+ }
336
+ const merged = { ...autoCommands, ...(configuredCommands ?? {}) };
337
+ LogStatus(`Slack slash commands: ${Object.keys(merged).length} available (${Object.keys(configuredCommands ?? {}).length} from config, ${Object.keys(autoCommands).length} auto-generated)`);
338
+ return merged;
339
+ }
340
+ /** Format the list of configured slash commands for display. */
341
+ listSlashCommands() {
342
+ const entries = Object.entries(this.slashCommands);
343
+ if (entries.length === 0)
344
+ return '_none configured_';
345
+ return entries.map(([cmd, agent]) => `\`${cmd}\` → ${agent}`).join(', ');
346
+ }
347
+ /**
348
+ * Post a visible thread-root message for the slash command, then construct
349
+ * an IncomingMessage with that thread's `ts` so all responses appear as replies.
350
+ */
351
+ async processSlashCommandAsync(agentName, text, userId, userName, channelId) {
352
+ const now = new Date();
353
+ // Post a visible message to serve as the thread root
354
+ let threadRootTs;
355
+ if (this.interactClient) {
356
+ try {
357
+ const displayText = text || `(invoked via slash command)`;
358
+ const result = await this.interactClient.chat.postMessage({
359
+ channel: channelId,
360
+ text: `*/${agentName.split(/\s+/)[0].toLowerCase()}* ${displayText}`,
361
+ blocks: [
362
+ {
363
+ type: 'section',
364
+ text: {
365
+ type: 'mrkdwn',
366
+ text: `<@${userId}> used \`/${agentName.split(/\s+/)[0].toLowerCase()}\`\n>${displayText}`
367
+ }
368
+ }
369
+ ]
370
+ });
371
+ threadRootTs = result.ts ?? undefined;
372
+ }
373
+ catch (error) {
374
+ LogError('Failed to post slash command thread root:', undefined, error);
375
+ }
376
+ }
377
+ const messageTs = threadRootTs ?? (now.getTime() / 1000).toFixed(6);
378
+ const incomingMessage = {
379
+ MessageID: messageTs,
380
+ Text: text || `(invoked via slash command)`,
381
+ SenderID: userId,
382
+ SenderName: userName ?? '',
383
+ ChannelID: channelId,
384
+ ThreadID: threadRootTs ?? null, // Thread under the root message if we posted one
385
+ IsDirectMessage: false,
386
+ IsBotMention: true, // Treat slash commands like @mentions so shouldRespond passes
387
+ MentionedAgentNames: [agentName],
388
+ Timestamp: now,
389
+ RawEvent: { type: 'slash_command', command: agentName, text }
390
+ };
391
+ this.adapter?.HandleMessage(incomingMessage).catch(error => {
392
+ LogError(`Error handling slash command for agent '${agentName}':`, undefined, error);
393
+ });
394
+ }
395
+ // ─── Shared event processing ─────────────────────────────────────────
396
+ /**
397
+ * Process a Slack event from either HTTP webhook or Socket Mode.
398
+ */
399
+ async processSlackEvent(event) {
400
+ if (!event) {
401
+ LogStatus('Slack webhook: no event in payload');
402
+ return;
403
+ }
404
+ const eventType = event.type;
405
+ LogStatus(`Slack event received: type=${eventType}, channel=${event.channel}, user=${event.user}`);
406
+ // Only handle message and app_mention events
407
+ if (eventType !== 'message' && eventType !== 'app_mention') {
408
+ LogStatus(`Slack: ignoring event type '${eventType}'`);
409
+ return;
410
+ }
411
+ // Skip bot messages (prevent loops) and message edits/deletes
412
+ if (event.bot_id || event.subtype) {
413
+ LogStatus(`Slack: skipping bot/subtype message (bot_id=${event.bot_id}, subtype=${event.subtype})`);
414
+ return;
415
+ }
416
+ if (!this.adapter) {
417
+ LogStatus('Slack: adapter not initialized, ignoring event');
418
+ return;
419
+ }
420
+ try {
421
+ const incomingMessage = this.adapter.MapSlackEvent(event);
422
+ await this.adapter.HandleMessage(incomingMessage);
423
+ }
424
+ catch (error) {
425
+ LogError('Error handling Slack event:', undefined, error);
426
+ }
427
+ }
428
+ };
429
+ SlackMessagingExtension = __decorate([
430
+ RegisterClass(BaseServerExtension, 'SlackMessagingExtension')
431
+ ], SlackMessagingExtension);
432
+ export { SlackMessagingExtension };
433
+ //# sourceMappingURL=SlackMessagingExtension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackMessagingExtension.js","sourceRoot":"","sources":["../../src/slack/SlackMessagingExtension.ts"],"names":[],"mappings":"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"}