@inkeep/agents-work-apps 0.53.0 → 0.53.2
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/dist/github/mcp/index.js +2 -1
- package/dist/github/routes/setup.d.ts +2 -2
- package/dist/github/routes/tokenExchange.d.ts +2 -2
- package/dist/github/routes/webhooks.d.ts +2 -2
- package/dist/slack/dispatcher.js +1 -0
- package/dist/slack/routes/users.js +29 -3
- package/dist/slack/services/agent-resolution.d.ts +1 -0
- package/dist/slack/services/agent-resolution.js +40 -1
- package/dist/slack/services/blocks/index.d.ts +8 -2
- package/dist/slack/services/blocks/index.js +26 -7
- package/dist/slack/services/commands/index.d.ts +1 -1
- package/dist/slack/services/commands/index.js +32 -122
- package/dist/slack/services/events/app-mention.d.ts +4 -14
- package/dist/slack/services/events/app-mention.js +40 -19
- package/dist/slack/services/events/index.d.ts +1 -1
- package/dist/slack/services/events/utils.d.ts +21 -2
- package/dist/slack/services/events/utils.js +35 -10
- package/dist/slack/services/index.d.ts +4 -4
- package/dist/slack/services/index.js +2 -2
- package/dist/slack/services/link-prompt.d.ts +27 -0
- package/dist/slack/services/link-prompt.js +142 -0
- package/dist/slack/services/resume-intent.d.ts +15 -0
- package/dist/slack/services/resume-intent.js +338 -0
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
|
|
1
2
|
import { InlineSelectorMetadata, handleAppMention } from "./app-mention.js";
|
|
2
3
|
import { handleMessageShortcut, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleToolApproval } from "./block-actions.js";
|
|
3
4
|
import { handleFollowUpSubmission, handleModalSubmission } from "./modal-submission.js";
|
|
4
|
-
import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
|
|
5
5
|
import { StreamResult, streamAgentResponse } from "./streaming.js";
|
|
6
6
|
export { type InlineSelectorMetadata, SlackErrorType, type StreamResult, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, handleAppMention, handleFollowUpSubmission, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleToolApproval, markdownToMrkdwn, sendResponseUrlMessage, streamAgentResponse };
|
|
@@ -11,9 +11,9 @@ declare function findCachedUserMapping(tenantId: string, slackUserId: string, te
|
|
|
11
11
|
id: string;
|
|
12
12
|
createdAt: string;
|
|
13
13
|
updatedAt: string;
|
|
14
|
+
slackUserId: string;
|
|
14
15
|
tenantId: string;
|
|
15
16
|
clientId: string;
|
|
16
|
-
slackUserId: string;
|
|
17
17
|
slackTeamId: string;
|
|
18
18
|
slackEnterpriseId: string | null;
|
|
19
19
|
inkeepUserId: string;
|
|
@@ -112,6 +112,24 @@ declare function checkIfBotThread(slackClient: {
|
|
|
112
112
|
}>;
|
|
113
113
|
};
|
|
114
114
|
}, channel: string, threadTs: string): Promise<boolean>;
|
|
115
|
+
interface SlackAttachment {
|
|
116
|
+
text?: string;
|
|
117
|
+
fallback?: string;
|
|
118
|
+
pretext?: string;
|
|
119
|
+
author_name?: string;
|
|
120
|
+
author_id?: string;
|
|
121
|
+
channel_name?: string;
|
|
122
|
+
channel_id?: string;
|
|
123
|
+
title?: string;
|
|
124
|
+
is_msg_unfurl?: boolean;
|
|
125
|
+
is_share?: boolean;
|
|
126
|
+
from_url?: string;
|
|
127
|
+
fields?: Array<{
|
|
128
|
+
title?: string;
|
|
129
|
+
value?: string;
|
|
130
|
+
}>;
|
|
131
|
+
}
|
|
132
|
+
declare function formatAttachments(attachments: SlackAttachment[] | undefined): string;
|
|
115
133
|
interface ThreadContextOptions {
|
|
116
134
|
includeLastMessage?: boolean;
|
|
117
135
|
resolveUserNames?: boolean;
|
|
@@ -128,6 +146,7 @@ declare function getThreadContext(slackClient: {
|
|
|
128
146
|
user?: string;
|
|
129
147
|
text?: string;
|
|
130
148
|
ts?: string;
|
|
149
|
+
attachments?: SlackAttachment[];
|
|
131
150
|
}>;
|
|
132
151
|
}>;
|
|
133
152
|
};
|
|
@@ -160,4 +179,4 @@ declare function formatChannelContext(channelInfo: {
|
|
|
160
179
|
name?: string;
|
|
161
180
|
} | null): string;
|
|
162
181
|
//#endregion
|
|
163
|
-
export { ProjectOption, SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
|
|
182
|
+
export { ProjectOption, SlackAttachment, SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatAttachments, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
|
|
@@ -34,17 +34,19 @@ async function findCachedUserMapping(tenantId, slackUserId, teamId, clientId = "
|
|
|
34
34
|
const cached = userMappingCache.get(cacheKey);
|
|
35
35
|
if (cached && cached.expiresAt > Date.now()) return cached.mapping;
|
|
36
36
|
const mapping = await findWorkAppSlackUserMapping(runDbClient_default)(tenantId, slackUserId, teamId, clientId);
|
|
37
|
-
if (
|
|
38
|
-
evictExpiredEntries();
|
|
37
|
+
if (mapping) {
|
|
39
38
|
if (userMappingCache.size >= USER_MAPPING_CACHE_MAX_SIZE) {
|
|
40
|
-
|
|
41
|
-
if (
|
|
39
|
+
evictExpiredEntries();
|
|
40
|
+
if (userMappingCache.size >= USER_MAPPING_CACHE_MAX_SIZE) {
|
|
41
|
+
const oldestKey = userMappingCache.keys().next().value;
|
|
42
|
+
if (oldestKey) userMappingCache.delete(oldestKey);
|
|
43
|
+
}
|
|
42
44
|
}
|
|
45
|
+
userMappingCache.set(cacheKey, {
|
|
46
|
+
mapping,
|
|
47
|
+
expiresAt: Date.now() + USER_MAPPING_CACHE_TTL_MS
|
|
48
|
+
});
|
|
43
49
|
}
|
|
44
|
-
userMappingCache.set(cacheKey, {
|
|
45
|
-
mapping,
|
|
46
|
-
expiresAt: Date.now() + USER_MAPPING_CACHE_TTL_MS
|
|
47
|
-
});
|
|
48
50
|
return mapping;
|
|
49
51
|
}
|
|
50
52
|
/**
|
|
@@ -328,6 +330,27 @@ async function checkIfBotThread(slackClient, channel, threadTs) {
|
|
|
328
330
|
return false;
|
|
329
331
|
}
|
|
330
332
|
}
|
|
333
|
+
function formatAttachments(attachments) {
|
|
334
|
+
if (!attachments || attachments.length === 0) return "";
|
|
335
|
+
const parts = [];
|
|
336
|
+
for (const att of attachments) {
|
|
337
|
+
const content = att.text || att.fallback;
|
|
338
|
+
if (!content) continue;
|
|
339
|
+
const isSharedMessage = att.is_msg_unfurl || att.is_share;
|
|
340
|
+
const meta = [];
|
|
341
|
+
if (att.author_name) meta.push(`from ${att.author_name}`);
|
|
342
|
+
if (att.channel_name) meta.push(`in #${att.channel_name}`);
|
|
343
|
+
else if (att.channel_id) meta.push(`in channel ${att.channel_id}`);
|
|
344
|
+
const label = isSharedMessage ? "Shared message" : "Attachment";
|
|
345
|
+
const metaSuffix = meta.length > 0 ? ` (${meta.join(", ")})` : "";
|
|
346
|
+
const sourceLine = att.from_url ? `\n[Source: ${att.from_url}]` : "";
|
|
347
|
+
parts.push(`[${label}${metaSuffix}]:\n\`\`\`\n${content}\n\`\`\`${sourceLine}`);
|
|
348
|
+
if (att.fields && att.fields.length > 0) {
|
|
349
|
+
for (const field of att.fields) if (field.title && field.value) parts.push(`${field.title}: ${field.value}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return parts.join("\n\n");
|
|
353
|
+
}
|
|
331
354
|
async function getThreadContext(slackClient, channel, threadTs, options = {}) {
|
|
332
355
|
const { includeLastMessage = false, resolveUserNames = true } = options;
|
|
333
356
|
try {
|
|
@@ -377,7 +400,9 @@ async function getThreadContext(slackClient, channel, threadTs, options = {}) {
|
|
|
377
400
|
else role = "Unknown";
|
|
378
401
|
const prefix = isParent ? "[Thread Start] " : "";
|
|
379
402
|
const messageText = msg.text || "";
|
|
380
|
-
|
|
403
|
+
const attachmentText = formatAttachments(msg.attachments);
|
|
404
|
+
const fullText = attachmentText ? `${messageText}\n${attachmentText}` : messageText;
|
|
405
|
+
return `${prefix}${role}: """${fullText}"""`;
|
|
381
406
|
}).join("\n\n")}`;
|
|
382
407
|
} catch (threadError) {
|
|
383
408
|
logger.warn({
|
|
@@ -412,4 +437,4 @@ function formatChannelContext(channelInfo) {
|
|
|
412
437
|
}
|
|
413
438
|
|
|
414
439
|
//#endregion
|
|
415
|
-
export { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
|
|
440
|
+
export { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatAttachments, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { AgentResolutionParams, ResolvedAgentConfig, getAgentConfigSources, resolveEffectiveAgent } from "./agent-resolution.js";
|
|
2
|
-
import { AgentConfigSources, ContextBlockParams, FollowUpButtonParams, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage,
|
|
2
|
+
import { AgentConfigSources, ContextBlockParams, FollowUpButtonParams, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage } from "./blocks/index.js";
|
|
3
3
|
import { checkUserIsChannelMember, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, postMessage, postMessageInThread, revokeSlackToken } from "./client.js";
|
|
4
4
|
import { DefaultAgentConfig, SlackWorkspaceConnection, WorkspaceInstallData, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, deleteWorkspaceInstallation, findWorkspaceConnectionByTeamId, getConnectionAccessToken, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, setWorkspaceDefaultAgent, storeWorkspaceInstallation, updateConnectionMetadata } from "./nango.js";
|
|
5
5
|
import { SlackCommandPayload, SlackCommandResponse } from "./types.js";
|
|
6
6
|
import { handleAgentPickerCommand, handleCommand, handleHelpCommand, handleLinkCommand, handleQuestionCommand, handleStatusCommand, handleUnlinkCommand } from "./commands/index.js";
|
|
7
|
+
import { AgentOption, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, FollowUpModalMetadata, ModalMetadata, buildAgentSelectorModal, buildFollowUpModal, buildMessageShortcutModal } from "./modals.js";
|
|
8
|
+
import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./events/utils.js";
|
|
7
9
|
import { InlineSelectorMetadata, handleAppMention } from "./events/app-mention.js";
|
|
8
10
|
import { handleMessageShortcut, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleToolApproval } from "./events/block-actions.js";
|
|
9
11
|
import { handleFollowUpSubmission, handleModalSubmission } from "./events/modal-submission.js";
|
|
10
|
-
import { AgentOption, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, FollowUpModalMetadata, ModalMetadata, buildAgentSelectorModal, buildFollowUpModal, buildMessageShortcutModal } from "./modals.js";
|
|
11
|
-
import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./events/utils.js";
|
|
12
12
|
import { StreamResult, streamAgentResponse } from "./events/streaming.js";
|
|
13
13
|
import "./events/index.js";
|
|
14
14
|
import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "./security.js";
|
|
15
15
|
import { getBotTokenForTeam, setBotTokenForTeam } from "./workspace-tokens.js";
|
|
16
|
-
export { AgentConfigSources, AgentOption, AgentResolutionParams, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, ContextBlockParams, DefaultAgentConfig, FollowUpButtonParams, FollowUpModalMetadata, InlineSelectorMetadata, ModalMetadata, ResolvedAgentConfig, SlackCommandPayload, SlackCommandResponse, SlackErrorType, SlackWorkspaceConnection, StreamResult, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, WorkspaceInstallData, buildAgentSelectorModal, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildFollowUpModal, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage,
|
|
16
|
+
export { AgentConfigSources, AgentOption, AgentResolutionParams, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, ContextBlockParams, DefaultAgentConfig, FollowUpButtonParams, FollowUpModalMetadata, InlineSelectorMetadata, ModalMetadata, ResolvedAgentConfig, SlackCommandPayload, SlackCommandResponse, SlackErrorType, SlackWorkspaceConnection, StreamResult, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, WorkspaceInstallData, buildAgentSelectorModal, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildFollowUpModal, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleFollowUpSubmission, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, markdownToMrkdwn, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, verifySlackRequest };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConnectSession, deleteWorkspaceInstallation, findWorkspaceConnectionByTeamId, getConnectionAccessToken, getSlackIntegrationId, getSlackNango, getWorkspaceDefaultAgentFromNango, listWorkspaceInstallations, setWorkspaceDefaultAgent, storeWorkspaceInstallation, updateConnectionMetadata } from "./nango.js";
|
|
2
2
|
import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./events/utils.js";
|
|
3
3
|
import { getAgentConfigSources, resolveEffectiveAgent } from "./agent-resolution.js";
|
|
4
|
-
import { ToolApprovalButtonValueSchema, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage,
|
|
4
|
+
import { ToolApprovalButtonValueSchema, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage } from "./blocks/index.js";
|
|
5
5
|
import { checkUserIsChannelMember, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, postMessage, postMessageInThread, revokeSlackToken } from "./client.js";
|
|
6
6
|
import { buildAgentSelectorModal, buildFollowUpModal, buildMessageShortcutModal } from "./modals.js";
|
|
7
7
|
import { handleAgentPickerCommand, handleCommand, handleHelpCommand, handleLinkCommand, handleQuestionCommand, handleStatusCommand, handleUnlinkCommand } from "./commands/index.js";
|
|
@@ -13,4 +13,4 @@ import "./events/index.js";
|
|
|
13
13
|
import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "./security.js";
|
|
14
14
|
import { getBotTokenForTeam, setBotTokenForTeam } from "./workspace-tokens.js";
|
|
15
15
|
|
|
16
|
-
export { SlackErrorType, ToolApprovalButtonValueSchema, buildAgentSelectorModal, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildFollowUpModal, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage,
|
|
16
|
+
export { SlackErrorType, ToolApprovalButtonValueSchema, buildAgentSelectorModal, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildFollowUpModal, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleFollowUpSubmission, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, markdownToMrkdwn, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, verifySlackRequest };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SlackLinkIntent } from "@inkeep/agents-core";
|
|
2
|
+
import * as slack_block_builder7 from "slack-block-builder";
|
|
3
|
+
|
|
4
|
+
//#region src/slack/services/link-prompt.d.ts
|
|
5
|
+
type LinkPromptResult = {
|
|
6
|
+
type: 'auto_invite';
|
|
7
|
+
url: string;
|
|
8
|
+
email: string;
|
|
9
|
+
expiresInMinutes: number;
|
|
10
|
+
} | {
|
|
11
|
+
type: 'jwt_link';
|
|
12
|
+
url: string;
|
|
13
|
+
expiresInMinutes: number;
|
|
14
|
+
};
|
|
15
|
+
interface ResolveLinkActionParams {
|
|
16
|
+
tenantId: string;
|
|
17
|
+
teamId: string;
|
|
18
|
+
slackUserId: string;
|
|
19
|
+
botToken: string;
|
|
20
|
+
slackEnterpriseId?: string;
|
|
21
|
+
slackUsername?: string;
|
|
22
|
+
intent?: SlackLinkIntent;
|
|
23
|
+
}
|
|
24
|
+
declare function resolveUnlinkedUserAction(params: ResolveLinkActionParams): Promise<LinkPromptResult>;
|
|
25
|
+
declare function buildLinkPromptMessage(result: LinkPromptResult): Readonly<slack_block_builder7.SlackMessageDto>;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { LinkPromptResult, ResolveLinkActionParams, buildLinkPromptMessage, resolveUnlinkedUserAction };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { env } from "../../env.js";
|
|
2
|
+
import { getLogger } from "../../logger.js";
|
|
3
|
+
import runDbClient_default from "../../db/runDbClient.js";
|
|
4
|
+
import { createCreateInkeepAccountMessage, createSmartLinkMessage } from "./blocks/index.js";
|
|
5
|
+
import { getSlackClient } from "./client.js";
|
|
6
|
+
import { createInvitationInDb, findWorkAppSlackWorkspaceByTeamId, getOrganizationMemberByEmail, getPendingInvitationsByEmail, signSlackLinkToken } from "@inkeep/agents-core";
|
|
7
|
+
|
|
8
|
+
//#region src/slack/services/link-prompt.ts
|
|
9
|
+
const logger = getLogger("slack-link-prompt");
|
|
10
|
+
const LINK_CODE_TTL_MINUTES = 10;
|
|
11
|
+
async function resolveUnlinkedUserAction(params) {
|
|
12
|
+
const { tenantId, teamId, slackUserId, botToken, slackEnterpriseId, slackUsername, intent } = params;
|
|
13
|
+
const manageUiUrl = env.INKEEP_AGENTS_MANAGE_UI_URL || "http://localhost:3000";
|
|
14
|
+
const autoInvite = await tryAutoInvite({
|
|
15
|
+
tenantId,
|
|
16
|
+
teamId,
|
|
17
|
+
slackUserId,
|
|
18
|
+
botToken
|
|
19
|
+
});
|
|
20
|
+
if (autoInvite) {
|
|
21
|
+
const linkToken$1 = await signSlackLinkToken({
|
|
22
|
+
tenantId,
|
|
23
|
+
slackTeamId: teamId,
|
|
24
|
+
slackUserId,
|
|
25
|
+
slackEnterpriseId,
|
|
26
|
+
slackUsername,
|
|
27
|
+
intent
|
|
28
|
+
});
|
|
29
|
+
const authMethod = autoInvite.authMethod;
|
|
30
|
+
const linkReturnUrl = `/link?token=${encodeURIComponent(linkToken$1)}`;
|
|
31
|
+
const acceptUrl = authMethod === "email-password" ? `${manageUiUrl}/accept-invitation/${autoInvite.invitationId}?email=${encodeURIComponent(autoInvite.email)}&returnUrl=${encodeURIComponent(linkReturnUrl)}` : `${manageUiUrl}/login?invitation=${encodeURIComponent(autoInvite.invitationId)}&returnUrl=${encodeURIComponent(linkReturnUrl)}&email=${encodeURIComponent(autoInvite.email)}&authMethod=${encodeURIComponent(authMethod)}`;
|
|
32
|
+
logger.info({
|
|
33
|
+
invitationId: autoInvite.invitationId,
|
|
34
|
+
email: autoInvite.email,
|
|
35
|
+
hasIntent: !!intent
|
|
36
|
+
}, "Directing unlinked user to accept-invitation page");
|
|
37
|
+
return {
|
|
38
|
+
type: "auto_invite",
|
|
39
|
+
url: acceptUrl,
|
|
40
|
+
email: autoInvite.email,
|
|
41
|
+
expiresInMinutes: LINK_CODE_TTL_MINUTES
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const linkToken = await signSlackLinkToken({
|
|
45
|
+
tenantId,
|
|
46
|
+
slackTeamId: teamId,
|
|
47
|
+
slackUserId,
|
|
48
|
+
slackEnterpriseId,
|
|
49
|
+
slackUsername,
|
|
50
|
+
intent
|
|
51
|
+
});
|
|
52
|
+
const linkUrl = `${manageUiUrl}/link?token=${encodeURIComponent(linkToken)}`;
|
|
53
|
+
logger.info({
|
|
54
|
+
slackUserId,
|
|
55
|
+
tenantId,
|
|
56
|
+
hasIntent: !!intent
|
|
57
|
+
}, "Generated JWT link token for unlinked user");
|
|
58
|
+
return {
|
|
59
|
+
type: "jwt_link",
|
|
60
|
+
url: linkUrl,
|
|
61
|
+
expiresInMinutes: LINK_CODE_TTL_MINUTES
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function buildLinkPromptMessage(result) {
|
|
65
|
+
if (result.type === "auto_invite") return createCreateInkeepAccountMessage(result.url, result.expiresInMinutes);
|
|
66
|
+
return createSmartLinkMessage(result.url);
|
|
67
|
+
}
|
|
68
|
+
async function tryAutoInvite(params) {
|
|
69
|
+
const { tenantId, teamId, slackUserId, botToken } = params;
|
|
70
|
+
if (!botToken) return null;
|
|
71
|
+
try {
|
|
72
|
+
if (!(await findWorkAppSlackWorkspaceByTeamId(runDbClient_default)(tenantId, teamId))?.shouldAllowJoinFromWorkspace) {
|
|
73
|
+
logger.warn({
|
|
74
|
+
userId: slackUserId,
|
|
75
|
+
tenantId,
|
|
76
|
+
teamId
|
|
77
|
+
}, "Workspace should not allow join from workspace");
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const slackClient = getSlackClient(botToken);
|
|
81
|
+
let userEmail;
|
|
82
|
+
try {
|
|
83
|
+
userEmail = (await slackClient.users.info({ user: slackUserId })).user?.profile?.email;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
logger.warn({
|
|
86
|
+
error,
|
|
87
|
+
userId: slackUserId
|
|
88
|
+
}, "Failed to get user info from Slack");
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
if (!userEmail) {
|
|
92
|
+
logger.warn({ userId: slackUserId }, "No email found in Slack user profile");
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
if (await getOrganizationMemberByEmail(runDbClient_default)(tenantId, userEmail)) {
|
|
96
|
+
logger.debug({
|
|
97
|
+
userId: slackUserId,
|
|
98
|
+
email: userEmail
|
|
99
|
+
}, "User already has Inkeep account, skipping auto-invite");
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const existingInvitation = (await getPendingInvitationsByEmail(runDbClient_default)(userEmail)).find((inv) => inv.organizationId === tenantId);
|
|
103
|
+
if (existingInvitation) {
|
|
104
|
+
logger.info({
|
|
105
|
+
userId: slackUserId,
|
|
106
|
+
tenantId,
|
|
107
|
+
invitationId: existingInvitation.id,
|
|
108
|
+
email: userEmail
|
|
109
|
+
}, "Reusing existing pending invitation for Slack user");
|
|
110
|
+
return {
|
|
111
|
+
invitationId: existingInvitation.id,
|
|
112
|
+
email: userEmail,
|
|
113
|
+
authMethod: existingInvitation.authMethod ?? "email-password"
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const invitation = await createInvitationInDb(runDbClient_default)({
|
|
117
|
+
organizationId: tenantId,
|
|
118
|
+
email: userEmail
|
|
119
|
+
});
|
|
120
|
+
logger.info({
|
|
121
|
+
userId: slackUserId,
|
|
122
|
+
tenantId,
|
|
123
|
+
invitationId: invitation.id,
|
|
124
|
+
email: userEmail
|
|
125
|
+
}, "Invitation created for Slack user without Inkeep account");
|
|
126
|
+
return {
|
|
127
|
+
invitationId: invitation.id,
|
|
128
|
+
email: userEmail,
|
|
129
|
+
authMethod: invitation.authMethod
|
|
130
|
+
};
|
|
131
|
+
} catch (error) {
|
|
132
|
+
logger.warn({
|
|
133
|
+
error,
|
|
134
|
+
userId: slackUserId,
|
|
135
|
+
tenantId
|
|
136
|
+
}, "Auto-invite attempt failed");
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
//#endregion
|
|
142
|
+
export { buildLinkPromptMessage, resolveUnlinkedUserAction };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SlackLinkIntent } from "@inkeep/agents-core";
|
|
2
|
+
|
|
3
|
+
//#region src/slack/services/resume-intent.d.ts
|
|
4
|
+
interface ResumeSmartLinkIntentParams {
|
|
5
|
+
intent: SlackLinkIntent;
|
|
6
|
+
teamId: string;
|
|
7
|
+
slackUserId: string;
|
|
8
|
+
inkeepUserId: string;
|
|
9
|
+
tenantId: string;
|
|
10
|
+
slackEnterpriseId?: string;
|
|
11
|
+
slackUsername?: string;
|
|
12
|
+
}
|
|
13
|
+
declare function resumeSmartLinkIntent(params: ResumeSmartLinkIntentParams): Promise<void>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ResumeSmartLinkIntentParams, resumeSmartLinkIntent };
|