@inkeep/agents-work-apps 0.0.0-dev-20260204182014 → 0.0.0-dev-20260204210021

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 (68) hide show
  1. package/dist/db/index.d.ts +1 -2
  2. package/dist/db/index.js +1 -2
  3. package/dist/db/runDbClient.d.ts +2 -2
  4. package/dist/env.d.ts +2 -24
  5. package/dist/env.js +1 -12
  6. package/dist/github/routes/setup.d.ts +2 -2
  7. package/dist/github/routes/tokenExchange.d.ts +2 -2
  8. package/package.json +2 -10
  9. package/dist/db/manageDbClient.d.ts +0 -7
  10. package/dist/db/manageDbClient.js +0 -16
  11. package/dist/slack/index.d.ts +0 -19
  12. package/dist/slack/index.js +0 -29
  13. package/dist/slack/middleware/permissions.d.ts +0 -16
  14. package/dist/slack/middleware/permissions.js +0 -49
  15. package/dist/slack/routes/events.d.ts +0 -10
  16. package/dist/slack/routes/events.js +0 -319
  17. package/dist/slack/routes/index.d.ts +0 -11
  18. package/dist/slack/routes/index.js +0 -64
  19. package/dist/slack/routes/internal.d.ts +0 -10
  20. package/dist/slack/routes/internal.js +0 -107
  21. package/dist/slack/routes/oauth.d.ts +0 -12
  22. package/dist/slack/routes/oauth.js +0 -218
  23. package/dist/slack/routes/resources.d.ts +0 -10
  24. package/dist/slack/routes/resources.js +0 -163
  25. package/dist/slack/routes/users.d.ts +0 -15
  26. package/dist/slack/routes/users.js +0 -430
  27. package/dist/slack/routes/workspaces.d.ts +0 -10
  28. package/dist/slack/routes/workspaces.js +0 -828
  29. package/dist/slack/routes.d.ts +0 -7
  30. package/dist/slack/routes.js +0 -12
  31. package/dist/slack/services/agent-resolution.d.ts +0 -49
  32. package/dist/slack/services/agent-resolution.js +0 -135
  33. package/dist/slack/services/api-client.d.ts +0 -161
  34. package/dist/slack/services/api-client.js +0 -248
  35. package/dist/slack/services/auth/index.d.ts +0 -61
  36. package/dist/slack/services/auth/index.js +0 -164
  37. package/dist/slack/services/blocks/index.d.ts +0 -60
  38. package/dist/slack/services/blocks/index.js +0 -143
  39. package/dist/slack/services/client.d.ts +0 -78
  40. package/dist/slack/services/client.js +0 -152
  41. package/dist/slack/services/commands/index.d.ts +0 -15
  42. package/dist/slack/services/commands/index.js +0 -556
  43. package/dist/slack/services/events/app-mention.d.ts +0 -41
  44. package/dist/slack/services/events/app-mention.js +0 -212
  45. package/dist/slack/services/events/block-actions.d.ts +0 -47
  46. package/dist/slack/services/events/block-actions.js +0 -287
  47. package/dist/slack/services/events/index.d.ts +0 -6
  48. package/dist/slack/services/events/index.js +0 -7
  49. package/dist/slack/services/events/modal-submission.d.ts +0 -12
  50. package/dist/slack/services/events/modal-submission.js +0 -279
  51. package/dist/slack/services/events/streaming.d.ts +0 -27
  52. package/dist/slack/services/events/streaming.js +0 -285
  53. package/dist/slack/services/events/utils.d.ts +0 -129
  54. package/dist/slack/services/events/utils.js +0 -315
  55. package/dist/slack/services/index.d.ts +0 -18
  56. package/dist/slack/services/index.js +0 -18
  57. package/dist/slack/services/modals.d.ts +0 -67
  58. package/dist/slack/services/modals.js +0 -203
  59. package/dist/slack/services/nango.d.ts +0 -82
  60. package/dist/slack/services/nango.js +0 -326
  61. package/dist/slack/services/security.d.ts +0 -35
  62. package/dist/slack/services/security.js +0 -65
  63. package/dist/slack/services/types.d.ts +0 -26
  64. package/dist/slack/services/types.js +0 -1
  65. package/dist/slack/services/workspace-tokens.d.ts +0 -37
  66. package/dist/slack/services/workspace-tokens.js +0 -39
  67. package/dist/slack/types.d.ts +0 -10
  68. package/dist/slack/types.js +0 -1
@@ -1,556 +0,0 @@
1
- import { env } from "../../../env.js";
2
- import { getLogger } from "../../../logger.js";
3
- import runDbClient_default from "../../../db/runDbClient.js";
4
- import { findWorkspaceConnectionByTeamId } from "../nango.js";
5
- import { resolveEffectiveAgent } from "../agent-resolution.js";
6
- import { createAgentListMessage, createAlreadyLinkedMessage, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createSettingsMessage, createSettingsUpdatedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage } from "../blocks/index.js";
7
- import { deleteWorkAppSlackUserMapping, findWorkAppSlackUserMapping, findWorkAppSlackUserMappingBySlackUser, signSlackLinkToken, signSlackUserToken, upsertWorkAppSlackUserSettings } from "@inkeep/agents-core";
8
-
9
- //#region src/slack/services/commands/index.ts
10
- /**
11
- * Fetch all agents from the manage API.
12
- * This uses the proper ref-middleware and Dolt branch resolution.
13
- * Requires an auth token to access the manage API.
14
- */
15
- async function fetchAgentsFromManageApi(tenantId, authToken) {
16
- const apiBaseUrl = env.INKEEP_AGENTS_API_URL || "http://localhost:3002";
17
- try {
18
- const projectsResponse = await fetch(`${apiBaseUrl}/manage/tenants/${tenantId}/projects`, {
19
- method: "GET",
20
- headers: {
21
- "Content-Type": "application/json",
22
- Authorization: `Bearer ${authToken}`
23
- }
24
- });
25
- if (!projectsResponse.ok) {
26
- logger.error({
27
- status: projectsResponse.status,
28
- tenantId
29
- }, "Failed to fetch projects from manage API");
30
- return [];
31
- }
32
- const projectsData = await projectsResponse.json();
33
- const projects = projectsData.data || projectsData || [];
34
- logger.info({
35
- projectCount: projects.length,
36
- tenantId
37
- }, "Fetched projects from manage API");
38
- return (await Promise.all(projects.map(async (project) => {
39
- try {
40
- const agentsResponse = await fetch(`${apiBaseUrl}/manage/tenants/${tenantId}/projects/${project.id}/agents`, {
41
- method: "GET",
42
- headers: {
43
- "Content-Type": "application/json",
44
- Authorization: `Bearer ${authToken}`
45
- }
46
- });
47
- if (agentsResponse.ok) {
48
- const agentsData = await agentsResponse.json();
49
- return (agentsData.data || agentsData || []).map((agent) => ({
50
- id: agent.id,
51
- name: agent.name,
52
- projectId: project.id,
53
- projectName: project.name
54
- }));
55
- }
56
- return [];
57
- } catch (error) {
58
- logger.error({
59
- error,
60
- projectId: project.id
61
- }, "Failed to fetch agents for project");
62
- return [];
63
- }
64
- }))).flat();
65
- } catch (error) {
66
- logger.error({
67
- error,
68
- tenantId
69
- }, "Failed to fetch agents from manage API");
70
- return [];
71
- }
72
- }
73
- /**
74
- * Find an agent by name or ID from the manage API.
75
- */
76
- async function findAgentByIdentifier(tenantId, identifier, authToken) {
77
- return (await fetchAgentsFromManageApi(tenantId, authToken)).find((a) => a.id === identifier || a.name?.toLowerCase() === identifier.toLowerCase()) || null;
78
- }
79
- const DEFAULT_CLIENT_ID = "work-apps-slack";
80
- const LINK_CODE_TTL_MINUTES = 10;
81
- const logger = getLogger("slack-commands");
82
- /**
83
- * Parse agent name and question from command text.
84
- * Agent name must be in quotes: "agent name" question
85
- */
86
- function parseAgentAndQuestion(text) {
87
- if (!text.trim()) return {
88
- agentName: null,
89
- question: null
90
- };
91
- const quotedMatch = text.match(/^["']([^"']+)["']\s+(.+)$/);
92
- if (quotedMatch) return {
93
- agentName: quotedMatch[1].trim(),
94
- question: quotedMatch[2].trim()
95
- };
96
- return {
97
- agentName: null,
98
- question: null
99
- };
100
- }
101
- async function handleLinkCommand(payload, dashboardUrl, tenantId) {
102
- const existingLink = await findWorkAppSlackUserMapping(runDbClient_default)(tenantId, payload.userId, payload.teamId, DEFAULT_CLIENT_ID);
103
- if (existingLink) return {
104
- response_type: "ephemeral",
105
- ...createAlreadyLinkedMessage(existingLink.slackEmail || existingLink.slackUsername || "Unknown", existingLink.linkedAt, dashboardUrl)
106
- };
107
- try {
108
- const linkToken = await signSlackLinkToken({
109
- tenantId,
110
- slackTeamId: payload.teamId,
111
- slackUserId: payload.userId,
112
- slackEnterpriseId: payload.enterpriseId,
113
- slackUsername: payload.userName
114
- });
115
- const linkUrl = `${env.INKEEP_AGENTS_MANAGE_UI_URL || "http://localhost:3000"}/link?token=${encodeURIComponent(linkToken)}`;
116
- logger.info({
117
- slackUserId: payload.userId,
118
- tenantId
119
- }, "Generated JWT link token");
120
- return {
121
- response_type: "ephemeral",
122
- ...createJwtLinkMessage(linkUrl, LINK_CODE_TTL_MINUTES)
123
- };
124
- } catch (error) {
125
- logger.error({
126
- error,
127
- slackUserId: payload.userId,
128
- tenantId
129
- }, "Failed to generate link token");
130
- return {
131
- response_type: "ephemeral",
132
- ...createErrorMessage("Failed to generate link. Please try again.")
133
- };
134
- }
135
- }
136
- async function handleUnlinkCommand(payload, tenantId) {
137
- if (!await findWorkAppSlackUserMapping(runDbClient_default)(tenantId, payload.userId, payload.teamId, DEFAULT_CLIENT_ID)) return {
138
- response_type: "ephemeral",
139
- ...createNotLinkedMessage()
140
- };
141
- try {
142
- if (await deleteWorkAppSlackUserMapping(runDbClient_default)(tenantId, payload.userId, payload.teamId, DEFAULT_CLIENT_ID)) {
143
- logger.info({
144
- slackUserId: payload.userId,
145
- tenantId
146
- }, "User unlinked Slack account");
147
- return {
148
- response_type: "ephemeral",
149
- ...createUnlinkSuccessMessage()
150
- };
151
- }
152
- return {
153
- response_type: "ephemeral",
154
- ...createErrorMessage("Failed to unlink account. Please try again.")
155
- };
156
- } catch (error) {
157
- logger.error({
158
- error,
159
- slackUserId: payload.userId,
160
- tenantId
161
- }, "Failed to unlink account");
162
- return {
163
- response_type: "ephemeral",
164
- ...createErrorMessage("Failed to unlink account. Please try again.")
165
- };
166
- }
167
- }
168
- async function handleStatusCommand(payload, dashboardUrl, tenantId) {
169
- const existingLink = await findWorkAppSlackUserMapping(runDbClient_default)(tenantId, payload.userId, payload.teamId, DEFAULT_CLIENT_ID);
170
- if (existingLink) {
171
- const { getAgentConfigSources } = await import("../agent-resolution.js");
172
- const agentConfigs = await getAgentConfigSources({
173
- tenantId,
174
- teamId: payload.teamId,
175
- channelId: payload.channelId,
176
- userId: payload.userId
177
- });
178
- return {
179
- response_type: "ephemeral",
180
- ...createStatusMessage(existingLink.slackEmail || existingLink.slackUsername || payload.userName, existingLink.linkedAt, dashboardUrl, agentConfigs)
181
- };
182
- }
183
- return {
184
- response_type: "ephemeral",
185
- ...createNotLinkedMessage()
186
- };
187
- }
188
- async function handleLogoutCommand(payload, tenantId) {
189
- return handleUnlinkCommand(payload, tenantId);
190
- }
191
- async function handleHelpCommand() {
192
- return {
193
- response_type: "ephemeral",
194
- ...createUpdatedHelpMessage()
195
- };
196
- }
197
- async function generateLinkCodeWithIntent(payload, tenantId) {
198
- try {
199
- const linkToken = await signSlackLinkToken({
200
- tenantId,
201
- slackTeamId: payload.teamId,
202
- slackUserId: payload.userId,
203
- slackEnterpriseId: payload.enterpriseId,
204
- slackUsername: payload.userName
205
- });
206
- const linkUrl = `${env.INKEEP_AGENTS_MANAGE_UI_URL || "http://localhost:3000"}/link?token=${encodeURIComponent(linkToken)}`;
207
- logger.info({
208
- slackUserId: payload.userId,
209
- tenantId
210
- }, "Generated JWT link token with intent");
211
- return {
212
- response_type: "ephemeral",
213
- ...createJwtLinkMessage(linkUrl, LINK_CODE_TTL_MINUTES)
214
- };
215
- } catch (error) {
216
- logger.error({
217
- error,
218
- slackUserId: payload.userId,
219
- tenantId
220
- }, "Failed to generate link token");
221
- return {
222
- response_type: "ephemeral",
223
- ...createErrorMessage("Failed to generate link. Please try again.")
224
- };
225
- }
226
- }
227
- async function handleQuestionCommand(payload, question, _dashboardUrl, tenantId) {
228
- const existingLink = await findWorkAppSlackUserMappingBySlackUser(runDbClient_default)(payload.userId, payload.teamId, DEFAULT_CLIENT_ID);
229
- if (!existingLink) return generateLinkCodeWithIntent(payload, tenantId);
230
- const userTenantId = existingLink.tenantId;
231
- const resolvedAgent = await resolveEffectiveAgent({
232
- tenantId: userTenantId,
233
- teamId: payload.teamId,
234
- channelId: payload.channelId,
235
- userId: payload.userId
236
- });
237
- if (!resolvedAgent) return {
238
- response_type: "ephemeral",
239
- ...createErrorMessage("No default agent configured. Ask your admin to set a workspace default, or use `/inkeep settings set [agent]` to set your personal default.\n\nUse `/inkeep list` to see available agents.")
240
- };
241
- executeAgentInBackground(payload, existingLink, {
242
- id: resolvedAgent.agentId,
243
- name: resolvedAgent.agentName || null,
244
- projectId: resolvedAgent.projectId
245
- }, question, userTenantId).catch((error) => {
246
- logger.error({ error }, "Background execution promise rejected");
247
- });
248
- return {};
249
- }
250
- async function executeAgentInBackground(payload, existingLink, targetAgent, question, tenantId) {
251
- try {
252
- const slackUserToken = await signSlackUserToken({
253
- inkeepUserId: existingLink.inkeepUserId,
254
- tenantId,
255
- slackTeamId: payload.teamId,
256
- slackUserId: payload.userId,
257
- slackEnterpriseId: payload.enterpriseId
258
- });
259
- const apiBaseUrl = env.INKEEP_AGENTS_API_URL || "http://localhost:3002";
260
- const response = await fetch(`${apiBaseUrl}/run/api/chat`, {
261
- method: "POST",
262
- headers: {
263
- "Content-Type": "application/json",
264
- Authorization: `Bearer ${slackUserToken}`,
265
- "x-inkeep-project-id": targetAgent.projectId,
266
- "x-inkeep-agent-id": targetAgent.id
267
- },
268
- body: JSON.stringify({
269
- messages: [{
270
- role: "user",
271
- content: question
272
- }],
273
- stream: false
274
- })
275
- });
276
- let responsePayload;
277
- if (!response.ok) {
278
- const errorText = await response.text();
279
- logger.error({
280
- status: response.status,
281
- error: errorText,
282
- agentId: targetAgent.id,
283
- projectId: targetAgent.projectId
284
- }, "Run API call failed");
285
- responsePayload = {
286
- response_type: "ephemeral",
287
- text: `Failed to run agent: ${response.status} ${response.statusText}`
288
- };
289
- } else {
290
- const result = await response.json();
291
- const assistantMessage = result.choices?.[0]?.message?.content || result.message?.content || "No response received";
292
- logger.info({
293
- slackUserId: payload.userId,
294
- agentId: targetAgent.id,
295
- projectId: targetAgent.projectId,
296
- tenantId
297
- }, "Agent execution completed via Slack");
298
- responsePayload = {
299
- response_type: "ephemeral",
300
- blocks: [{
301
- type: "section",
302
- text: {
303
- type: "mrkdwn",
304
- text: assistantMessage
305
- }
306
- }, {
307
- type: "context",
308
- elements: [{
309
- type: "mrkdwn",
310
- text: `Powered by *${targetAgent.name || targetAgent.id}* via Inkeep`
311
- }]
312
- }]
313
- };
314
- }
315
- await fetch(payload.responseUrl, {
316
- method: "POST",
317
- headers: { "Content-Type": "application/json" },
318
- body: JSON.stringify(responsePayload)
319
- });
320
- } catch (error) {
321
- logger.error({
322
- error,
323
- slackUserId: payload.userId
324
- }, "Background agent execution failed");
325
- try {
326
- await fetch(payload.responseUrl, {
327
- method: "POST",
328
- headers: { "Content-Type": "application/json" },
329
- body: JSON.stringify({
330
- response_type: "ephemeral",
331
- text: "An error occurred while running the agent. Please try again."
332
- })
333
- });
334
- } catch {
335
- logger.error({ slackUserId: payload.userId }, "Failed to send error response to Slack");
336
- }
337
- }
338
- }
339
- async function handleRunCommand(payload, agentIdentifier, question, _dashboardUrl, tenantId) {
340
- const existingLink = await findWorkAppSlackUserMappingBySlackUser(runDbClient_default)(payload.userId, payload.teamId, DEFAULT_CLIENT_ID);
341
- if (!existingLink) return generateLinkCodeWithIntent(payload, tenantId);
342
- const userTenantId = existingLink.tenantId;
343
- try {
344
- const targetAgent = await findAgentByIdentifier(userTenantId, agentIdentifier, await signSlackUserToken({
345
- inkeepUserId: existingLink.inkeepUserId,
346
- tenantId: userTenantId,
347
- slackTeamId: payload.teamId,
348
- slackUserId: payload.userId,
349
- slackEnterpriseId: payload.enterpriseId
350
- }));
351
- if (!targetAgent) return {
352
- response_type: "ephemeral",
353
- ...createErrorMessage(`Agent "${agentIdentifier}" not found. Use \`/inkeep list\` to see available agents.`)
354
- };
355
- executeAgentInBackground(payload, existingLink, targetAgent, question, userTenantId).catch((error) => {
356
- logger.error({ error }, "Background execution promise rejected");
357
- });
358
- return {};
359
- } catch (error) {
360
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
361
- logger.error({
362
- error: errorMessage,
363
- tenantId: userTenantId
364
- }, "Failed to run agent");
365
- return {
366
- response_type: "ephemeral",
367
- ...createErrorMessage("Failed to run agent. Please try again or visit the dashboard.")
368
- };
369
- }
370
- }
371
- async function handleSettingsCommand(payload, subCommand, agentIdentifier, dashboardUrl, _tenantId) {
372
- const existingLink = await findWorkAppSlackUserMappingBySlackUser(runDbClient_default)(payload.userId, payload.teamId, DEFAULT_CLIENT_ID);
373
- if (!existingLink) return {
374
- response_type: "ephemeral",
375
- ...createNotLinkedMessage()
376
- };
377
- const userTenantId = existingLink.tenantId;
378
- if (subCommand === "set" && agentIdentifier) try {
379
- const targetAgent = await findAgentByIdentifier(userTenantId, agentIdentifier, await signSlackUserToken({
380
- inkeepUserId: existingLink.inkeepUserId,
381
- tenantId: userTenantId,
382
- slackTeamId: payload.teamId,
383
- slackUserId: payload.userId,
384
- slackEnterpriseId: payload.enterpriseId
385
- }));
386
- if (!targetAgent) return {
387
- response_type: "ephemeral",
388
- ...createErrorMessage(`Agent "${agentIdentifier}" not found. Use \`/inkeep list\` to see available agents.`)
389
- };
390
- await upsertWorkAppSlackUserSettings(runDbClient_default)({
391
- tenantId: userTenantId,
392
- slackTeamId: payload.teamId,
393
- slackUserId: payload.userId,
394
- defaultProjectId: targetAgent.projectId,
395
- defaultAgentId: targetAgent.id,
396
- defaultAgentName: targetAgent.name
397
- });
398
- logger.info({
399
- slackUserId: payload.userId,
400
- tenantId: userTenantId,
401
- agentId: targetAgent.id,
402
- agentName: targetAgent.name
403
- }, "User set personal default agent");
404
- return {
405
- response_type: "ephemeral",
406
- ...createSettingsUpdatedMessage(targetAgent.name || targetAgent.id)
407
- };
408
- } catch (error) {
409
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
410
- logger.error({
411
- error: errorMessage,
412
- tenantId: userTenantId
413
- }, "Failed to update user settings");
414
- return {
415
- response_type: "ephemeral",
416
- ...createErrorMessage("Failed to update settings. Please try again.")
417
- };
418
- }
419
- if (subCommand === "clear") try {
420
- await upsertWorkAppSlackUserSettings(runDbClient_default)({
421
- tenantId: userTenantId,
422
- slackTeamId: payload.teamId,
423
- slackUserId: payload.userId,
424
- defaultProjectId: void 0,
425
- defaultAgentId: void 0,
426
- defaultAgentName: void 0
427
- });
428
- logger.info({
429
- slackUserId: payload.userId,
430
- tenantId: userTenantId
431
- }, "User cleared personal default agent");
432
- return {
433
- response_type: "ephemeral",
434
- blocks: [{
435
- type: "section",
436
- text: {
437
- type: "mrkdwn",
438
- text: "✅ *Personal default agent cleared*\n\nYou will now use the workspace or channel default."
439
- }
440
- }]
441
- };
442
- } catch (error) {
443
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
444
- logger.error({
445
- error: errorMessage,
446
- tenantId: userTenantId
447
- }, "Failed to clear user settings");
448
- return {
449
- response_type: "ephemeral",
450
- ...createErrorMessage("Failed to clear settings. Please try again.")
451
- };
452
- }
453
- return {
454
- response_type: "ephemeral",
455
- ...createSettingsMessage(await resolveEffectiveAgent({
456
- tenantId: userTenantId,
457
- teamId: payload.teamId,
458
- channelId: payload.channelId,
459
- userId: payload.userId
460
- }), dashboardUrl)
461
- };
462
- }
463
- async function handleAgentListCommand(payload, dashboardUrl, _tenantId) {
464
- const existingLink = await findWorkAppSlackUserMappingBySlackUser(runDbClient_default)(payload.userId, payload.teamId, DEFAULT_CLIENT_ID);
465
- if (!existingLink) return {
466
- response_type: "ephemeral",
467
- ...createNotLinkedMessage()
468
- };
469
- const userTenantId = existingLink.tenantId;
470
- logger.info({
471
- slackUserId: payload.userId,
472
- existingLinkTenantId: existingLink.tenantId,
473
- existingLinkInkeepUserId: existingLink.inkeepUserId
474
- }, "Found user mapping for list command");
475
- try {
476
- const allAgents = await fetchAgentsFromManageApi(userTenantId, await signSlackUserToken({
477
- inkeepUserId: existingLink.inkeepUserId,
478
- tenantId: userTenantId,
479
- slackTeamId: payload.teamId,
480
- slackUserId: payload.userId,
481
- slackEnterpriseId: payload.enterpriseId
482
- }));
483
- logger.info({
484
- slackUserId: payload.userId,
485
- tenantId: userTenantId,
486
- agentCount: allAgents.length
487
- }, "Listed agents for linked Slack user");
488
- if (allAgents.length === 0) return {
489
- response_type: "ephemeral",
490
- ...createErrorMessage("No agents found. Create an agent in the Inkeep dashboard first.")
491
- };
492
- return {
493
- response_type: "ephemeral",
494
- ...createAgentListMessage(allAgents, dashboardUrl.replace("/work-apps/slack", ""))
495
- };
496
- } catch (error) {
497
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
498
- logger.error({
499
- error: errorMessage,
500
- tenantId: userTenantId
501
- }, "Failed to list agents");
502
- return {
503
- response_type: "ephemeral",
504
- ...createErrorMessage("Failed to list agents. Please try again or visit the dashboard.")
505
- };
506
- }
507
- }
508
- async function handleCommand(payload) {
509
- const text = payload.text.trim();
510
- const parts = text.split(/\s+/);
511
- const subcommand = parts[0]?.toLowerCase() || "";
512
- const manageUiUrl = env.INKEEP_AGENTS_MANAGE_UI_URL || "http://localhost:3000";
513
- const tenantId = (await findWorkspaceConnectionByTeamId(payload.teamId))?.tenantId || "default";
514
- const dashboardUrl = `${manageUiUrl}/${tenantId}/work-apps/slack`;
515
- logger.info({
516
- command: payload.command,
517
- subcommand,
518
- slackUserId: payload.userId,
519
- teamId: payload.teamId,
520
- tenantId
521
- }, "Slack command received");
522
- switch (subcommand) {
523
- case "link":
524
- case "connect": return handleLinkCommand(payload, dashboardUrl, tenantId);
525
- case "status": return handleStatusCommand(payload, dashboardUrl, tenantId);
526
- case "unlink":
527
- case "logout":
528
- case "disconnect": return handleUnlinkCommand(payload, tenantId);
529
- case "list": return handleAgentListCommand(payload, dashboardUrl, tenantId);
530
- case "run": {
531
- const parsed = parseAgentAndQuestion(text.slice(4).trim());
532
- if (!parsed.agentName || !parsed.question) return {
533
- response_type: "ephemeral",
534
- ...createErrorMessage("Usage: `/inkeep run \"agent name\" [question]`\n\nExample: `/inkeep run \"my agent\" What is the weather?`\n\nAgent name must be in quotes.")
535
- };
536
- return handleRunCommand(payload, parsed.agentName, parsed.question, dashboardUrl, tenantId);
537
- }
538
- case "settings": {
539
- const settingsSubcommand = parts[1]?.toLowerCase();
540
- let agentName;
541
- if (settingsSubcommand === "set") {
542
- const quotedMatch = text.match(/^settings\s+set\s+["']([^"']+)["']/i);
543
- if (quotedMatch) agentName = quotedMatch[1].trim();
544
- }
545
- return handleSettingsCommand(payload, settingsSubcommand, agentName, dashboardUrl, tenantId);
546
- }
547
- case "help":
548
- case "":
549
- if (text === "" || text === "help") return handleHelpCommand();
550
- return handleQuestionCommand(payload, text, dashboardUrl, tenantId);
551
- default: return handleQuestionCommand(payload, text, dashboardUrl, tenantId);
552
- }
553
- }
554
-
555
- //#endregion
556
- export { handleAgentListCommand, handleCommand, handleHelpCommand, handleLinkCommand, handleLogoutCommand, handleQuestionCommand, handleRunCommand, handleSettingsCommand, handleStatusCommand, handleUnlinkCommand };
@@ -1,41 +0,0 @@
1
- //#region src/slack/services/events/app-mention.d.ts
2
- /**
3
- * Handler for Slack @mention events
4
- *
5
- * Flow:
6
- * 1. Resolve agent config (channel override > workspace default)
7
- * 2. If no agent configured → prompt to set up in dashboard
8
- * 3. Check if user is linked to Inkeep
9
- * 4. If not linked → prompt to link account
10
- * 5. Handle based on context:
11
- * - Channel + no query → Show welcome/help message
12
- * - Channel + query → Execute agent with streaming response
13
- * - Thread + no query → Show modal to select agent
14
- * - Thread + query → Execute agent with thread context included
15
- */
16
- /**
17
- * Metadata passed to the agent selector modal via button value
18
- */
19
- interface InlineSelectorMetadata {
20
- channel: string;
21
- threadTs: string;
22
- messageTs: string;
23
- teamId: string;
24
- slackUserId: string;
25
- tenantId: string;
26
- threadMessageCount: number;
27
- }
28
- /**
29
- * Main handler for @mention events in Slack
30
- */
31
- declare function handleAppMention(params: {
32
- slackUserId: string;
33
- channel: string;
34
- text: string;
35
- threadTs: string;
36
- messageTs: string;
37
- teamId: string;
38
- triggerId?: string;
39
- }): Promise<void>;
40
- //#endregion
41
- export { InlineSelectorMetadata, handleAppMention };