@inkeep/agents-work-apps 0.0.0-dev-20260219045007 → 0.0.0-dev-20260219103848

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 (39) hide show
  1. package/dist/_virtual/rolldown_runtime.js +32 -0
  2. package/dist/env.d.ts +2 -0
  3. package/dist/env.js +1 -0
  4. package/dist/github/mcp/index.d.ts +2 -2
  5. package/dist/github/mcp/schemas.d.ts +1 -1
  6. package/dist/github/routes/setup.d.ts +2 -2
  7. package/dist/github/routes/tokenExchange.d.ts +2 -2
  8. package/dist/github/routes/webhooks.d.ts +2 -2
  9. package/dist/node_modules/.pnpm/@slack_logger@4.0.0/node_modules/@slack/logger/dist/index.js +89 -0
  10. package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/package.js +85 -0
  11. package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/SlackWebSocket.js +223 -0
  12. package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/SocketModeClient.js +367 -0
  13. package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/UnrecoverableSocketModeStartError.js +20 -0
  14. package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/errors.js +71 -0
  15. package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/index.js +44 -0
  16. package/dist/node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/logger.js +32 -0
  17. package/dist/node_modules/.pnpm/eventemitter3@5.0.1/node_modules/eventemitter3/index.js +241 -0
  18. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/index.js +23 -0
  19. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/buffer-util.js +107 -0
  20. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/constants.js +29 -0
  21. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/event-target.js +226 -0
  22. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/extension.js +150 -0
  23. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/limiter.js +57 -0
  24. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/permessage-deflate.js +342 -0
  25. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/receiver.js +457 -0
  26. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/sender.js +505 -0
  27. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/stream.js +123 -0
  28. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/subprotocol.js +46 -0
  29. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/validation.js +203 -0
  30. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket-server.js +385 -0
  31. package/dist/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js +985 -0
  32. package/dist/slack/dispatcher.d.ts +16 -0
  33. package/dist/slack/dispatcher.js +332 -0
  34. package/dist/slack/index.d.ts +3 -1
  35. package/dist/slack/index.js +3 -1
  36. package/dist/slack/routes/events.js +10 -328
  37. package/dist/slack/socket-mode.d.ts +4 -0
  38. package/dist/slack/socket-mode.js +130 -0
  39. package/package.json +3 -2
@@ -3,17 +3,13 @@ import { getLogger } from "../../logger.js";
3
3
  import runDbClient_default from "../../db/runDbClient.js";
4
4
  import { findWorkspaceConnectionByTeamId, getSlackIntegrationId, getSlackNango, updateConnectionMetadata } from "../services/nango.js";
5
5
  import { getSlackClient, getSlackUserInfo } from "../services/client.js";
6
- import { sendResponseUrlMessage } from "../services/events/utils.js";
7
6
  import { handleCommand } from "../services/commands/index.js";
8
7
  import { SLACK_SPAN_KEYS, SLACK_SPAN_NAMES, tracer } from "../tracer.js";
9
- import { handleAppMention } from "../services/events/app-mention.js";
10
- import { handleMessageShortcut, handleOpenAgentSelectorModal, handleOpenFollowUpModal } from "../services/events/block-actions.js";
11
- import { handleFollowUpSubmission, handleModalSubmission } from "../services/events/modal-submission.js";
12
- import "../services/events/index.js";
13
8
  import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "../services/security.js";
14
9
  import "../services/index.js";
10
+ import { dispatchSlackEvent } from "../dispatcher.js";
15
11
  import { OpenAPIHono } from "@hono/zod-openapi";
16
- import { deleteAllWorkAppSlackChannelAgentConfigsByTeam, deleteAllWorkAppSlackUserMappingsByTeam, deleteWorkAppSlackWorkspaceByNangoConnectionId, flushTraces, getWaitUntil } from "@inkeep/agents-core";
12
+ import { deleteAllWorkAppSlackChannelAgentConfigsByTeam, deleteAllWorkAppSlackUserMappingsByTeam, deleteWorkAppSlackWorkspaceByNangoConnectionId, getWaitUntil } from "@inkeep/agents-core";
17
13
  import { SpanStatusCode } from "@opentelemetry/api";
18
14
 
19
15
  //#region src/slack/routes/events.ts
@@ -122,328 +118,14 @@ app.post("/events", async (c) => {
122
118
  span.end();
123
119
  return c.text(String(eventBody.challenge));
124
120
  }
125
- if (eventType === "event_callback") {
126
- const teamId = eventBody.team_id;
127
- const event = eventBody.event;
128
- const innerEventType = event?.type || "unknown";
129
- span.setAttribute(SLACK_SPAN_KEYS.INNER_EVENT_TYPE, innerEventType);
130
- if (teamId) span.setAttribute(SLACK_SPAN_KEYS.TEAM_ID, teamId);
131
- if (event?.channel) span.setAttribute(SLACK_SPAN_KEYS.CHANNEL_ID, event.channel);
132
- if (event?.user) span.setAttribute(SLACK_SPAN_KEYS.USER_ID, event.user);
133
- span.updateName(`${SLACK_SPAN_NAMES.WEBHOOK} event_callback.${innerEventType}`);
134
- if (event?.bot_id || event?.subtype === "bot_message") {
135
- outcome = "ignored_bot_message";
136
- span.setAttribute(SLACK_SPAN_KEYS.IS_BOT_MESSAGE, true);
137
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
138
- logger.info({
139
- botId: event.bot_id,
140
- subtype: event?.subtype,
141
- teamId,
142
- innerEventType
143
- }, "Ignoring bot message");
144
- span.end();
145
- return c.json({ ok: true });
146
- }
147
- if (event?.type === "app_mention" && event.channel && event.user && teamId) {
148
- outcome = "handled";
149
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
150
- const question = (event.text || "").replace(/<@[A-Z0-9]+>/g, "").trim();
151
- span.setAttribute(SLACK_SPAN_KEYS.HAS_QUERY, question.length > 0);
152
- if (event.thread_ts) span.setAttribute(SLACK_SPAN_KEYS.THREAD_TS, event.thread_ts);
153
- if (event.ts) span.setAttribute(SLACK_SPAN_KEYS.MESSAGE_TS, event.ts);
154
- logger.info({
155
- userId: event.user,
156
- channel: event.channel,
157
- teamId,
158
- hasQuery: question.length > 0
159
- }, "Handling event: app_mention");
160
- const dispatchedAt = Date.now();
161
- const mentionWork = handleAppMention({
162
- slackUserId: event.user,
163
- channel: event.channel,
164
- text: question,
165
- threadTs: event.thread_ts || event.ts || "",
166
- messageTs: event.ts || "",
167
- teamId,
168
- dispatchedAt
169
- }).catch((err) => {
170
- const errorMessage = err instanceof Error ? err.message : String(err);
171
- const errorStack = err instanceof Error ? err.stack : void 0;
172
- logger.error({
173
- errorMessage,
174
- errorStack
175
- }, "Failed to handle app mention (outer catch)");
176
- }).finally(() => flushTraces());
177
- if (waitUntil) {
178
- waitUntil(mentionWork);
179
- logger.info({
180
- teamId,
181
- channel: event.channel,
182
- dispatchedAt
183
- }, "app_mention work registered with waitUntil");
184
- } else logger.warn({
185
- teamId,
186
- channel: event.channel,
187
- dispatchedAt
188
- }, "waitUntil unavailable — app_mention background work is untracked fire-and-forget");
189
- } else {
190
- outcome = "ignored_unknown_event";
191
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
192
- logger.info({
193
- innerEventType,
194
- teamId
195
- }, `Ignoring unhandled event_callback: ${innerEventType}`);
196
- }
197
- }
198
- if (eventType === "block_actions" || eventType === "interactive_message") {
199
- const actions = eventBody.actions;
200
- const teamId = eventBody.team?.id;
201
- const responseUrl = eventBody.response_url;
202
- const triggerId = eventBody.trigger_id;
203
- const actionIds = actions?.map((a) => a.action_id) || [];
204
- if (teamId) span.setAttribute(SLACK_SPAN_KEYS.TEAM_ID, teamId);
205
- span.setAttribute(SLACK_SPAN_KEYS.ACTION_IDS, actionIds.join(","));
206
- span.updateName(`${SLACK_SPAN_NAMES.WEBHOOK} ${eventType} [${actionIds.join(",")}]`);
207
- if (actions && teamId) {
208
- let anyHandled = false;
209
- for (const action of actions) {
210
- if (action.action_id === "open_agent_selector_modal" && action.value && triggerId) {
211
- anyHandled = true;
212
- logger.info({
213
- teamId,
214
- actionId: action.action_id
215
- }, "Handling block_action: open_agent_selector_modal");
216
- const selectorWork = handleOpenAgentSelectorModal({
217
- triggerId,
218
- actionValue: action.value,
219
- teamId,
220
- responseUrl: responseUrl || ""
221
- }).catch(async (err) => {
222
- const errorMessage = err instanceof Error ? err.message : String(err);
223
- logger.error({
224
- errorMessage,
225
- actionId: action.action_id
226
- }, "Failed to open agent selector modal");
227
- if (responseUrl) await sendResponseUrlMessage(responseUrl, {
228
- text: "Sorry, something went wrong while opening the agent selector. Please try again.",
229
- response_type: "ephemeral"
230
- }).catch((e) => logger.warn({ error: e }, "Failed to send error notification via response URL"));
231
- }).finally(() => flushTraces());
232
- if (waitUntil) waitUntil(selectorWork);
233
- }
234
- if (action.action_id === "modal_project_select") {
235
- anyHandled = true;
236
- const selectedProjectId = action.selected_option?.value;
237
- const view = eventBody.view;
238
- logger.info({
239
- teamId,
240
- actionId: action.action_id,
241
- selectedProjectId
242
- }, "Handling block_action: modal_project_select");
243
- if (selectedProjectId && view?.id) {
244
- const projectSelectWork = (async () => {
245
- try {
246
- const metadata = JSON.parse(view.private_metadata || "{}");
247
- const tenantId = metadata.tenantId;
248
- if (!tenantId) {
249
- logger.warn({ teamId }, "No tenantId in modal metadata — skipping project update");
250
- return;
251
- }
252
- const workspace = await findWorkspaceConnectionByTeamId(teamId);
253
- if (!workspace?.botToken) return;
254
- const slackClient = getSlackClient(workspace.botToken);
255
- const { fetchProjectsForTenant, fetchAgentsForProject } = await import("../services/events/utils.js");
256
- const { buildAgentSelectorModal, buildMessageShortcutModal } = await import("../services/modals.js");
257
- const projectList = await fetchProjectsForTenant(tenantId);
258
- const agentList = await fetchAgentsForProject(tenantId, selectedProjectId);
259
- const agentOptions = agentList.map((a) => ({
260
- id: a.id,
261
- name: a.name,
262
- projectId: a.projectId,
263
- projectName: a.projectName || a.projectId
264
- }));
265
- const modal = metadata.messageContext ? buildMessageShortcutModal({
266
- projects: projectList,
267
- agents: agentOptions,
268
- metadata,
269
- selectedProjectId,
270
- messageContext: metadata.messageContext
271
- }) : buildAgentSelectorModal({
272
- projects: projectList,
273
- agents: agentOptions,
274
- metadata,
275
- selectedProjectId
276
- });
277
- await slackClient.views.update({
278
- view_id: view.id,
279
- view: modal
280
- });
281
- logger.debug({
282
- selectedProjectId,
283
- agentCount: agentList.length
284
- }, "Updated modal with agents for selected project");
285
- } catch (err) {
286
- logger.error({
287
- err,
288
- selectedProjectId
289
- }, "Failed to update modal on project change");
290
- } finally {
291
- await flushTraces();
292
- }
293
- })();
294
- if (waitUntil) waitUntil(projectSelectWork);
295
- }
296
- }
297
- if (action.action_id === "open_follow_up_modal" && action.value && triggerId) {
298
- anyHandled = true;
299
- logger.info({
300
- teamId,
301
- actionId: action.action_id
302
- }, "Handling block_action: open_follow_up_modal");
303
- const followUpModalWork = handleOpenFollowUpModal({
304
- triggerId,
305
- actionValue: action.value,
306
- teamId,
307
- responseUrl: responseUrl || void 0
308
- }).catch((err) => {
309
- const errorMessage = err instanceof Error ? err.message : String(err);
310
- logger.error({
311
- errorMessage,
312
- actionId: action.action_id
313
- }, "Failed to open follow-up modal");
314
- }).finally(() => flushTraces());
315
- if (waitUntil) waitUntil(followUpModalWork);
316
- }
317
- }
318
- outcome = anyHandled ? "handled" : "ignored_no_action_match";
319
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
320
- if (!anyHandled) logger.info({
321
- teamId,
322
- actionIds,
323
- eventType
324
- }, "Ignoring block_actions: no matching action handlers");
325
- } else {
326
- outcome = "ignored_no_action_match";
327
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
328
- logger.info({
329
- teamId,
330
- eventType,
331
- hasActions: Boolean(actions)
332
- }, "Ignoring block_actions: missing actions or teamId");
333
- }
334
- }
335
- if (eventType === "message_action") {
336
- const callbackId = eventBody.callback_id;
337
- span.setAttribute(SLACK_SPAN_KEYS.CALLBACK_ID, callbackId || "unknown");
338
- span.updateName(`${SLACK_SPAN_NAMES.WEBHOOK} message_action.${callbackId || "unknown"}`);
339
- if (callbackId === "ask_agent_shortcut") {
340
- const triggerId = eventBody.trigger_id;
341
- const teamId = eventBody.team?.id;
342
- const channelId = eventBody.channel?.id;
343
- const userId = eventBody.user?.id;
344
- const message = eventBody.message;
345
- const responseUrl = eventBody.response_url;
346
- if (teamId) span.setAttribute(SLACK_SPAN_KEYS.TEAM_ID, teamId);
347
- if (channelId) span.setAttribute(SLACK_SPAN_KEYS.CHANNEL_ID, channelId);
348
- if (userId) span.setAttribute(SLACK_SPAN_KEYS.USER_ID, userId);
349
- if (triggerId && teamId && channelId && userId && message?.ts) {
350
- outcome = "handled";
351
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
352
- logger.info({
353
- teamId,
354
- channelId,
355
- userId,
356
- callbackId
357
- }, "Handling message_action: ask_agent_shortcut");
358
- const shortcutWork = handleMessageShortcut({
359
- triggerId,
360
- teamId,
361
- channelId,
362
- userId,
363
- messageTs: message.ts,
364
- messageText: message.text || "",
365
- threadTs: message.thread_ts,
366
- responseUrl
367
- }).catch((err) => {
368
- const errorMessage = err instanceof Error ? err.message : String(err);
369
- logger.error({
370
- errorMessage,
371
- callbackId
372
- }, "Failed to handle message shortcut");
373
- }).finally(() => flushTraces());
374
- if (waitUntil) waitUntil(shortcutWork);
375
- } else {
376
- outcome = "ignored_unknown_event";
377
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
378
- logger.info({
379
- teamId,
380
- channelId,
381
- userId,
382
- callbackId,
383
- hasTriggerId: Boolean(triggerId)
384
- }, "Ignoring message_action: missing required fields");
385
- }
386
- } else {
387
- outcome = "ignored_unknown_event";
388
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
389
- logger.info({ callbackId }, `Ignoring unhandled message_action: ${callbackId}`);
390
- }
391
- }
392
- if (eventType === "view_submission") {
393
- const callbackId = eventBody.view?.callback_id;
394
- span.setAttribute(SLACK_SPAN_KEYS.CALLBACK_ID, callbackId || "unknown");
395
- span.updateName(`${SLACK_SPAN_NAMES.WEBHOOK} view_submission.${callbackId || "unknown"}`);
396
- if (callbackId === "agent_selector_modal") {
397
- const view = eventBody.view;
398
- const agentSelect = view.state?.values?.agent_select_block?.agent_select;
399
- if (!agentSelect?.selected_option?.value || agentSelect.selected_option.value === "none") {
400
- outcome = "validation_error";
401
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
402
- logger.info({ callbackId }, "Rejecting view_submission: no agent selected");
403
- span.end();
404
- return c.json({
405
- response_action: "errors",
406
- errors: { agent_select_block: "Please select an agent. If none are available, add agents to this project in the dashboard." }
407
- });
408
- }
409
- outcome = "handled";
410
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
411
- logger.info({ callbackId }, "Handling view_submission: agent_selector_modal");
412
- const modalWork = handleModalSubmission(view).catch((err) => {
413
- const errorMessage = err instanceof Error ? err.message : String(err);
414
- logger.error({
415
- errorMessage,
416
- callbackId
417
- }, "Failed to handle modal submission");
418
- }).finally(() => flushTraces());
419
- if (waitUntil) waitUntil(modalWork);
420
- span.end();
421
- return new Response(null, { status: 200 });
422
- }
423
- if (callbackId === "follow_up_modal") {
424
- const view = eventBody.view;
425
- outcome = "handled";
426
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
427
- logger.info({ callbackId }, "Handling view_submission: follow_up_modal");
428
- const followUpWork = handleFollowUpSubmission(view).catch((err) => {
429
- const errorMessage = err instanceof Error ? err.message : String(err);
430
- logger.error({
431
- errorMessage,
432
- callbackId
433
- }, "Failed to handle follow-up submission");
434
- }).finally(() => flushTraces());
435
- if (waitUntil) waitUntil(followUpWork);
436
- span.end();
437
- return new Response(null, { status: 200 });
438
- }
439
- outcome = "ignored_unknown_event";
440
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
441
- logger.info({ callbackId }, `Ignoring unhandled view_submission: ${callbackId}`);
442
- }
443
- if (eventType !== "event_callback" && eventType !== "block_actions" && eventType !== "interactive_message" && eventType !== "message_action" && eventType !== "view_submission") {
444
- outcome = "ignored_unknown_event";
445
- span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
446
- logger.info({ eventType }, `Ignoring unhandled Slack event type: ${eventType}`);
121
+ const registerBackgroundWork = (work) => {
122
+ if (waitUntil) waitUntil(work);
123
+ };
124
+ const result = await dispatchSlackEvent(eventType || "", eventBody, { registerBackgroundWork }, span);
125
+ outcome = result.outcome;
126
+ if (result.response) {
127
+ span.end();
128
+ return c.json(result.response);
447
129
  }
448
130
  span.end();
449
131
  return c.json({ ok: true });
@@ -0,0 +1,4 @@
1
+ //#region src/slack/socket-mode.d.ts
2
+ declare function startSocketMode(appToken: string): Promise<void>;
3
+ //#endregion
4
+ export { startSocketMode };
@@ -0,0 +1,130 @@
1
+ import { __toESM } from "../_virtual/rolldown_runtime.js";
2
+ import { getLogger } from "../logger.js";
3
+ import { handleCommand } from "./services/commands/index.js";
4
+ import { SLACK_SPAN_KEYS, SLACK_SPAN_NAMES, tracer } from "./tracer.js";
5
+ import "./services/index.js";
6
+ import { dispatchSlackEvent } from "./dispatcher.js";
7
+ import { flushTraces } from "@inkeep/agents-core";
8
+ import { SpanStatusCode } from "@opentelemetry/api";
9
+
10
+ //#region src/slack/socket-mode.ts
11
+ const logger = getLogger("slack-socket-mode");
12
+ const GLOBAL_KEY = "__inkeep_slack_socket_mode_client__";
13
+ async function startSocketMode(appToken) {
14
+ if (globalThis[GLOBAL_KEY]) {
15
+ logger.info({}, "Socket Mode client already running (HMR reload detected), skipping");
16
+ return;
17
+ }
18
+ const { SocketModeClient } = await import("../node_modules/.pnpm/@slack_socket-mode@2.0.5/node_modules/@slack/socket-mode/dist/src/index.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
19
+ const client = new SocketModeClient({ appToken });
20
+ setupSocketModeListeners(client);
21
+ await client.start();
22
+ globalThis[GLOBAL_KEY] = client;
23
+ logger.info({}, "Slack Socket Mode client started");
24
+ }
25
+ function registerBackgroundWork(work) {
26
+ work.catch((err) => {
27
+ logger.error({ error: err }, "Background work failed in Socket Mode");
28
+ });
29
+ }
30
+ function setupSocketModeListeners(client) {
31
+ client.on("error", (...args) => {
32
+ logger.error({ error: args[0] }, "Socket Mode client error");
33
+ });
34
+ client.on("disconnected", () => {
35
+ logger.warn({}, "Socket Mode client disconnected");
36
+ });
37
+ client.on("reconnecting", () => {
38
+ logger.info({}, "Socket Mode client reconnecting...");
39
+ });
40
+ client.on("slack_event", async (...args) => {
41
+ const { ack, body, type } = args[0];
42
+ if (type !== "events_api") return;
43
+ await ack();
44
+ await tracer.startActiveSpan(SLACK_SPAN_NAMES.WEBHOOK, async (span) => {
45
+ try {
46
+ const eventType = body.event?.type ? "event_callback" : body.type || "";
47
+ span.setAttribute(SLACK_SPAN_KEYS.EVENT_TYPE, eventType);
48
+ span.updateName(`${SLACK_SPAN_NAMES.WEBHOOK} ${eventType}`);
49
+ await dispatchSlackEvent(eventType, body, { registerBackgroundWork }, span);
50
+ } catch (error) {
51
+ span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, "error");
52
+ span.setStatus({
53
+ code: SpanStatusCode.ERROR,
54
+ message: String(error)
55
+ });
56
+ if (error instanceof Error) span.recordException(error);
57
+ logger.error({ error }, "Error handling Socket Mode event");
58
+ } finally {
59
+ span.end();
60
+ await flushTraces();
61
+ }
62
+ });
63
+ });
64
+ client.on("interactive", async (...args) => {
65
+ const { ack, body } = args[0];
66
+ const eventType = body.type || "";
67
+ await ack((await tracer.startActiveSpan(`${SLACK_SPAN_NAMES.WEBHOOK} ${eventType}`, async (span) => {
68
+ try {
69
+ span.setAttribute(SLACK_SPAN_KEYS.EVENT_TYPE, eventType);
70
+ return await dispatchSlackEvent(eventType, body, { registerBackgroundWork }, span);
71
+ } catch (error) {
72
+ span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, "error");
73
+ span.setStatus({
74
+ code: SpanStatusCode.ERROR,
75
+ message: String(error)
76
+ });
77
+ if (error instanceof Error) span.recordException(error);
78
+ logger.error({ error }, "Error handling Socket Mode interactive event");
79
+ return { outcome: "error" };
80
+ } finally {
81
+ span.end();
82
+ }
83
+ })).response);
84
+ await flushTraces();
85
+ });
86
+ client.on("slash_commands", async (...args) => {
87
+ const { ack, body } = args[0];
88
+ await ack();
89
+ await tracer.startActiveSpan(`${SLACK_SPAN_NAMES.WEBHOOK} slash_command`, async (span) => {
90
+ try {
91
+ span.setAttribute(SLACK_SPAN_KEYS.EVENT_TYPE, "slash_command");
92
+ if (body.command) span.setAttribute("slack.command", body.command);
93
+ if (body.team_id) span.setAttribute(SLACK_SPAN_KEYS.TEAM_ID, body.team_id);
94
+ const commandPayload = {
95
+ command: body.command || "",
96
+ text: body.text || "",
97
+ userId: body.user_id || "",
98
+ userName: body.user_name || "",
99
+ teamId: body.team_id || "",
100
+ teamDomain: body.team_domain || "",
101
+ enterpriseId: body.enterprise_id,
102
+ channelId: body.channel_id || "",
103
+ channelName: body.channel_name || "",
104
+ responseUrl: body.response_url || "",
105
+ triggerId: body.trigger_id || ""
106
+ };
107
+ const response = await handleCommand(commandPayload);
108
+ if (Object.keys(response).length > 0 && commandPayload.responseUrl) await fetch(commandPayload.responseUrl, {
109
+ method: "POST",
110
+ headers: { "Content-Type": "application/json" },
111
+ body: JSON.stringify(response)
112
+ });
113
+ } catch (error) {
114
+ span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, "error");
115
+ span.setStatus({
116
+ code: SpanStatusCode.ERROR,
117
+ message: String(error)
118
+ });
119
+ if (error instanceof Error) span.recordException(error);
120
+ logger.error({ error }, "Error handling Socket Mode slash command");
121
+ } finally {
122
+ span.end();
123
+ await flushTraces();
124
+ }
125
+ });
126
+ });
127
+ }
128
+
129
+ //#endregion
130
+ export { startSocketMode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-work-apps",
3
- "version": "0.0.0-dev-20260219045007",
3
+ "version": "0.0.0-dev-20260219103848",
4
4
  "description": "First party integrations for Inkeep Agents",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -33,13 +33,14 @@
33
33
  "jose": "^6.1.0",
34
34
  "minimatch": "^10.1.1",
35
35
  "slack-block-builder": "^2.8.0",
36
- "@inkeep/agents-core": "0.0.0-dev-20260219045007"
36
+ "@inkeep/agents-core": "0.0.0-dev-20260219103848"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@hono/zod-openapi": "^1.1.5",
40
40
  "zod": "^4.3.6"
41
41
  },
42
42
  "devDependencies": {
43
+ "@slack/socket-mode": "^2.0.5",
43
44
  "@types/node": "^20.11.24",
44
45
  "typescript": "^5.9.2",
45
46
  "vitest": "^3.2.4"