@inkeep/agents-work-apps 0.65.0 → 0.65.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/index.d.ts +3 -3
- package/dist/github/mcp/auth.d.ts +2 -2
- package/dist/github/mcp/index.d.ts +2 -2
- 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 +50 -0
- package/dist/slack/mcp/auth.d.ts +2 -2
- package/dist/slack/mcp/index.d.ts +2 -2
- package/dist/slack/middleware/permissions.d.ts +3 -3
- package/dist/slack/routes/workspaces.js +11 -36
- package/dist/slack/services/events/utils.d.ts +1 -1
- package/dist/slack/services/index.d.ts +2 -1
- package/dist/slack/services/index.js +2 -1
- package/dist/slack/services/link-prompt.d.ts +2 -2
- package/dist/slack/services/workspace-cleanup.d.ts +17 -0
- package/dist/slack/services/workspace-cleanup.js +82 -0
- package/dist/slack/slack-app-manifest.js +1 -5
- package/package.json +2 -2
package/dist/github/index.d.ts
CHANGED
|
@@ -4,10 +4,10 @@ import "./routes/setup.js";
|
|
|
4
4
|
import "./routes/tokenExchange.js";
|
|
5
5
|
import { WebhookVerificationResult, verifyWebhookSignature } from "./routes/webhooks.js";
|
|
6
6
|
import { Hono } from "hono";
|
|
7
|
-
import * as
|
|
7
|
+
import * as hono_types6 from "hono/types";
|
|
8
8
|
|
|
9
9
|
//#region src/github/index.d.ts
|
|
10
|
-
declare function createGithubRoutes(): Hono<
|
|
11
|
-
declare const githubRoutes: Hono<
|
|
10
|
+
declare function createGithubRoutes(): Hono<hono_types6.BlankEnv, hono_types6.BlankSchema, "/">;
|
|
11
|
+
declare const githubRoutes: Hono<hono_types6.BlankEnv, hono_types6.BlankSchema, "/">;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { GenerateInstallationAccessTokenResult, GenerateTokenError, GenerateTokenResult, GitHubAppConfig, InstallationAccessToken, InstallationInfo, LookupInstallationError, LookupInstallationForRepoResult, LookupInstallationResult, WebhookVerificationResult, clearConfigCache, createAppJwt, createGithubRoutes, determineStatus, fetchInstallationDetails, fetchInstallationRepositories, generateInstallationAccessToken, getGitHubAppConfig, getGitHubAppName, getStateSigningSecret, getWebhookSecret, githubRoutes, isGitHubAppConfigured, isGitHubAppNameConfigured, isStateSigningConfigured, isWebhookConfigured, lookupInstallationForRepo, validateGitHubAppConfigOnStartup, validateGitHubInstallFlowConfigOnStartup, validateGitHubWebhookConfigOnStartup, verifyWebhookSignature };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as hono2 from "hono";
|
|
2
2
|
|
|
3
3
|
//#region src/github/mcp/auth.d.ts
|
|
4
|
-
declare const githubMcpAuth: () =>
|
|
4
|
+
declare const githubMcpAuth: () => hono2.MiddlewareHandler<{
|
|
5
5
|
Variables: {
|
|
6
6
|
toolId: string;
|
|
7
7
|
tenantId: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types10 from "hono/types";
|
|
3
3
|
|
|
4
4
|
//#region src/github/mcp/index.d.ts
|
|
5
5
|
declare const app: Hono<{
|
|
@@ -8,6 +8,6 @@ declare const app: Hono<{
|
|
|
8
8
|
tenantId: string;
|
|
9
9
|
projectId: string;
|
|
10
10
|
};
|
|
11
|
-
},
|
|
11
|
+
}, hono_types10.BlankSchema, "/">;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { app as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types0 from "hono/types";
|
|
3
3
|
|
|
4
4
|
//#region src/github/routes/setup.d.ts
|
|
5
|
-
declare const app: Hono<
|
|
5
|
+
declare const app: Hono<hono_types0.BlankEnv, hono_types0.BlankSchema, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { app as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types3 from "hono/types";
|
|
3
3
|
|
|
4
4
|
//#region src/github/routes/tokenExchange.d.ts
|
|
5
|
-
declare const app: Hono<
|
|
5
|
+
declare const app: Hono<hono_types3.BlankEnv, hono_types3.BlankSchema, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { app as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types1 from "hono/types";
|
|
3
3
|
|
|
4
4
|
//#region src/github/routes/webhooks.d.ts
|
|
5
5
|
interface WebhookVerificationResult {
|
|
@@ -7,6 +7,6 @@ interface WebhookVerificationResult {
|
|
|
7
7
|
error?: string;
|
|
8
8
|
}
|
|
9
9
|
declare function verifyWebhookSignature(payload: string, signature: string | undefined, secret: string): WebhookVerificationResult;
|
|
10
|
-
declare const app: Hono<
|
|
10
|
+
declare const app: Hono<hono_types1.BlankEnv, hono_types1.BlankSchema, "/">;
|
|
11
11
|
//#endregion
|
|
12
12
|
export { WebhookVerificationResult, app as default, verifyWebhookSignature };
|
package/dist/slack/dispatcher.js
CHANGED
|
@@ -8,6 +8,7 @@ import { handleMessageShortcut, handleOpenAgentSelectorModal, handleToolApproval
|
|
|
8
8
|
import { handleDirectMessage } from "./services/events/direct-message.js";
|
|
9
9
|
import { handleModalSubmission } from "./services/events/modal-submission.js";
|
|
10
10
|
import "./services/events/index.js";
|
|
11
|
+
import { cleanupWorkspaceInstallation } from "./services/workspace-cleanup.js";
|
|
11
12
|
import "./services/index.js";
|
|
12
13
|
import { flushTraces } from "@inkeep/agents-core";
|
|
13
14
|
|
|
@@ -131,6 +132,55 @@ async function dispatchSlackEvent(eventType, payload, options, span) {
|
|
|
131
132
|
errorStack
|
|
132
133
|
}, "Failed to handle direct message (outer catch)");
|
|
133
134
|
}).finally(() => flushTraces()));
|
|
135
|
+
} else if (innerEventType === "app_uninstalled" && teamId) {
|
|
136
|
+
outcome = "handled";
|
|
137
|
+
span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
|
|
138
|
+
span.updateName("slack.webhook app_uninstalled");
|
|
139
|
+
logger.info({ teamId }, "Handling event: app_uninstalled");
|
|
140
|
+
registerBackgroundWork(cleanupWorkspaceInstallation({
|
|
141
|
+
teamId,
|
|
142
|
+
skipTokenRevocation: true
|
|
143
|
+
}).then((result) => {
|
|
144
|
+
logger.info({
|
|
145
|
+
teamId,
|
|
146
|
+
success: result.success,
|
|
147
|
+
dbCleaned: result.dbCleaned
|
|
148
|
+
}, "app_uninstalled cleanup completed");
|
|
149
|
+
}).catch((err) => {
|
|
150
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
151
|
+
logger.error({
|
|
152
|
+
errorMessage,
|
|
153
|
+
teamId
|
|
154
|
+
}, "Failed to handle app_uninstalled");
|
|
155
|
+
}).finally(() => flushTraces()));
|
|
156
|
+
} else if (innerEventType === "tokens_revoked" && teamId) {
|
|
157
|
+
outcome = "handled";
|
|
158
|
+
span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
|
|
159
|
+
span.updateName("slack.webhook tokens_revoked");
|
|
160
|
+
const tokensEvent = payload.event;
|
|
161
|
+
const revokedBotTokens = tokensEvent?.tokens?.bot ?? [];
|
|
162
|
+
const revokedOauthTokens = tokensEvent?.tokens?.oauth ?? [];
|
|
163
|
+
logger.info({
|
|
164
|
+
teamId,
|
|
165
|
+
revokedBotCount: revokedBotTokens.length,
|
|
166
|
+
revokedOauthCount: revokedOauthTokens.length
|
|
167
|
+
}, "Handling event: tokens_revoked");
|
|
168
|
+
if (revokedBotTokens.length > 0) registerBackgroundWork(cleanupWorkspaceInstallation({
|
|
169
|
+
teamId,
|
|
170
|
+
skipTokenRevocation: true
|
|
171
|
+
}).then((result) => {
|
|
172
|
+
logger.info({
|
|
173
|
+
teamId,
|
|
174
|
+
success: result.success,
|
|
175
|
+
dbCleaned: result.dbCleaned
|
|
176
|
+
}, "tokens_revoked (bot) cleanup completed");
|
|
177
|
+
}).catch((err) => {
|
|
178
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
179
|
+
logger.error({
|
|
180
|
+
errorMessage,
|
|
181
|
+
teamId
|
|
182
|
+
}, "Failed to handle tokens_revoked (bot)");
|
|
183
|
+
}).finally(() => flushTraces()));
|
|
134
184
|
} else {
|
|
135
185
|
outcome = "ignored_unknown_event";
|
|
136
186
|
span.setAttribute(SLACK_SPAN_KEYS.OUTCOME, outcome);
|
package/dist/slack/mcp/auth.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as hono1 from "hono";
|
|
2
2
|
|
|
3
3
|
//#region src/slack/mcp/auth.d.ts
|
|
4
|
-
declare const slackMcpAuth: () =>
|
|
4
|
+
declare const slackMcpAuth: () => hono1.MiddlewareHandler<{
|
|
5
5
|
Variables: {
|
|
6
6
|
toolId: string;
|
|
7
7
|
tenantId: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types5 from "hono/types";
|
|
3
3
|
|
|
4
4
|
//#region src/slack/mcp/index.d.ts
|
|
5
5
|
interface ChannelInfo {
|
|
@@ -18,6 +18,6 @@ declare const app: Hono<{
|
|
|
18
18
|
tenantId: string;
|
|
19
19
|
projectId: string;
|
|
20
20
|
};
|
|
21
|
-
},
|
|
21
|
+
}, hono_types5.BlankSchema, "/">;
|
|
22
22
|
//#endregion
|
|
23
23
|
export { ChannelInfo, app as default, pruneStaleChannelIds };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ManageAppVariables } from "../types.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono0 from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/slack/middleware/permissions.d.ts
|
|
5
5
|
/**
|
|
@@ -14,7 +14,7 @@ declare const requireWorkspaceAdmin: <Env extends {
|
|
|
14
14
|
Variables: ManageAppVariables;
|
|
15
15
|
} = {
|
|
16
16
|
Variables: ManageAppVariables;
|
|
17
|
-
}>() =>
|
|
17
|
+
}>() => hono0.MiddlewareHandler<Env, string, {}, Response>;
|
|
18
18
|
/**
|
|
19
19
|
* Middleware that requires either:
|
|
20
20
|
* 1. Org admin/owner role (can modify any channel), OR
|
|
@@ -26,6 +26,6 @@ declare const requireChannelMemberOrAdmin: <Env extends {
|
|
|
26
26
|
Variables: ManageAppVariables;
|
|
27
27
|
} = {
|
|
28
28
|
Variables: ManageAppVariables;
|
|
29
|
-
}>() =>
|
|
29
|
+
}>() => hono0.MiddlewareHandler<Env, string, {}, Response>;
|
|
30
30
|
//#endregion
|
|
31
31
|
export { isOrgAdmin, requireChannelMemberOrAdmin, requireWorkspaceAdmin };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { getLogger } from "../../logger.js";
|
|
2
2
|
import runDbClient_default from "../../db/runDbClient.js";
|
|
3
|
-
import {
|
|
3
|
+
import { findWorkspaceConnectionByTeamId, listWorkspaceInstallations, setWorkspaceDefaultAgent } from "../services/nango.js";
|
|
4
4
|
import { lookupAgentName } from "../services/agent-resolution.js";
|
|
5
|
-
import { getBotMemberChannels, getSlackChannels, getSlackClient
|
|
5
|
+
import { getBotMemberChannels, getSlackChannels, getSlackClient } from "../services/client.js";
|
|
6
|
+
import { cleanupWorkspaceInstallation } from "../services/workspace-cleanup.js";
|
|
6
7
|
import "../services/index.js";
|
|
7
8
|
import { requireChannelMemberOrAdmin, requireWorkspaceAdmin } from "../middleware/permissions.js";
|
|
8
9
|
import { OpenAPIHono, z } from "@hono/zod-openapi";
|
|
9
|
-
import { WorkAppSlackAgentConfigRequestSchema,
|
|
10
|
+
import { WorkAppSlackAgentConfigRequestSchema, deleteWorkAppSlackChannelAgentConfig, findWorkAppSlackChannelAgentConfig, findWorkAppSlackWorkspaceByTeamId, listWorkAppSlackChannelAgentConfigsByTeam, listWorkAppSlackUserMappingsByTeam, updateWorkAppSlackWorkspace, upsertWorkAppSlackChannelAgentConfig } from "@inkeep/agents-core";
|
|
10
11
|
import { createProtectedRoute, inheritedWorkAppsAuth } from "@inkeep/agents-core/middleware";
|
|
11
12
|
|
|
12
13
|
//#region src/slack/routes/workspaces.ts
|
|
@@ -347,47 +348,21 @@ app.openapi(createProtectedRoute({
|
|
|
347
348
|
}), async (c) => {
|
|
348
349
|
const { teamId: workspaceIdentifier } = c.req.valid("param");
|
|
349
350
|
let teamId;
|
|
350
|
-
let connectionId;
|
|
351
351
|
try {
|
|
352
352
|
if (workspaceIdentifier.includes(":")) {
|
|
353
|
-
connectionId = workspaceIdentifier;
|
|
354
353
|
const teamMatch = workspaceIdentifier.match(/T:([A-Z0-9]+)/);
|
|
355
354
|
if (!teamMatch) return c.json({ error: "Invalid connectionId format" }, 400);
|
|
356
355
|
teamId = teamMatch[1];
|
|
357
|
-
} else
|
|
358
|
-
teamId = workspaceIdentifier;
|
|
359
|
-
connectionId = computeWorkspaceConnectionId({
|
|
360
|
-
teamId,
|
|
361
|
-
enterpriseId: void 0
|
|
362
|
-
});
|
|
363
|
-
}
|
|
356
|
+
} else teamId = workspaceIdentifier;
|
|
364
357
|
const workspace = await findWorkspaceConnectionByTeamId(teamId);
|
|
365
358
|
if (!workspace) return c.json({ error: "Workspace not found" }, 404);
|
|
366
|
-
if (
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const deletedChannelConfigs = await deleteAllWorkAppSlackChannelAgentConfigsByTeam(runDbClient_default)(tenantId, teamId);
|
|
370
|
-
if (deletedChannelConfigs > 0) logger.info({
|
|
371
|
-
teamId,
|
|
372
|
-
deletedChannelConfigs
|
|
373
|
-
}, "Deleted channel configs for uninstalled workspace");
|
|
374
|
-
const deletedMappings = await deleteAllWorkAppSlackUserMappingsByTeam(runDbClient_default)(tenantId, teamId);
|
|
375
|
-
if (deletedMappings > 0) logger.info({
|
|
359
|
+
if (!verifyTenantOwnership(c, workspace.tenantId)) return c.json({ error: "Access denied" }, 403);
|
|
360
|
+
const result = await cleanupWorkspaceInstallation({ teamId });
|
|
361
|
+
if (!result.success) logger.error({
|
|
376
362
|
teamId,
|
|
377
|
-
|
|
378
|
-
}, "
|
|
379
|
-
|
|
380
|
-
if (deletedMcpConfigs > 0) logger.info({
|
|
381
|
-
teamId,
|
|
382
|
-
deletedMcpConfigs
|
|
383
|
-
}, "Deleted MCP tool access configs for uninstalled workspace");
|
|
384
|
-
if (await deleteWorkAppSlackWorkspaceByNangoConnectionId(runDbClient_default)(connectionId)) logger.info({ connectionId }, "Deleted workspace from database");
|
|
385
|
-
if (!await deleteWorkspaceInstallation(connectionId)) logger.error({ connectionId }, "deleteWorkspaceInstallation returned false (DB already cleaned up)");
|
|
386
|
-
clearWorkspaceConnectionCache(teamId);
|
|
387
|
-
logger.info({
|
|
388
|
-
connectionId,
|
|
389
|
-
teamId
|
|
390
|
-
}, "Deleted workspace installation and cleared cache");
|
|
363
|
+
result
|
|
364
|
+
}, "Workspace uninstall partially failed");
|
|
365
|
+
logger.info({ teamId }, "Workspace uninstalled via API");
|
|
391
366
|
return c.json({ success: true });
|
|
392
367
|
} catch (error) {
|
|
393
368
|
logger.error({
|
|
@@ -10,9 +10,9 @@ import { AgentOption } from "../modals.js";
|
|
|
10
10
|
*/
|
|
11
11
|
declare function findCachedUserMapping(tenantId: string, slackUserId: string, teamId: string, clientId?: string): Promise<{
|
|
12
12
|
slackUserId: string;
|
|
13
|
+
id: string;
|
|
13
14
|
createdAt: string;
|
|
14
15
|
updatedAt: string;
|
|
15
|
-
id: string;
|
|
16
16
|
tenantId: string;
|
|
17
17
|
clientId: string;
|
|
18
18
|
slackTeamId: string;
|
|
@@ -14,5 +14,6 @@ import { PublicExecutionParams, executeAgentPublicly } from "./events/execution.
|
|
|
14
14
|
import { handleModalSubmission } from "./events/modal-submission.js";
|
|
15
15
|
import "./events/index.js";
|
|
16
16
|
import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "./security.js";
|
|
17
|
+
import { WorkspaceCleanupResult, cleanupWorkspaceInstallation } from "./workspace-cleanup.js";
|
|
17
18
|
import { getBotTokenForTeam, setBotTokenForTeam } from "./workspace-tokens.js";
|
|
18
|
-
export { AgentConfigSources, AgentOption, AgentResolutionParams, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, ContextBlockParams, DefaultAgentConfig, InlineSelectorMetadata, ModalMetadata, PublicExecutionParams, ResolvedAgentConfig, SlackCommandPayload, SlackCommandResponse, SlackErrorType, SlackWorkspaceConnection, StreamResult, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, WorkspaceInstallData, buildAgentSelectorModal, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, executeAgentPublicly, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotMemberChannels, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserByEmail, getSlackUserInfo, getSlackUsers, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleDirectMessage, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, lookupAgentName, lookupProjectName, markdownToMrkdwn, openDmConversation, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, validateBotChannelMembership, verifySlackRequest };
|
|
19
|
+
export { AgentConfigSources, AgentOption, AgentResolutionParams, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, ContextBlockParams, DefaultAgentConfig, InlineSelectorMetadata, ModalMetadata, PublicExecutionParams, ResolvedAgentConfig, SlackCommandPayload, SlackCommandResponse, SlackErrorType, SlackWorkspaceConnection, StreamResult, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, WorkspaceCleanupResult, WorkspaceInstallData, buildAgentSelectorModal, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, cleanupWorkspaceInstallation, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, executeAgentPublicly, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotMemberChannels, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserByEmail, getSlackUserInfo, getSlackUsers, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleDirectMessage, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, lookupAgentName, lookupProjectName, markdownToMrkdwn, openDmConversation, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, validateBotChannelMembership, verifySlackRequest };
|
|
@@ -13,6 +13,7 @@ import { handleDirectMessage } from "./events/direct-message.js";
|
|
|
13
13
|
import { handleModalSubmission } from "./events/modal-submission.js";
|
|
14
14
|
import "./events/index.js";
|
|
15
15
|
import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "./security.js";
|
|
16
|
+
import { cleanupWorkspaceInstallation } from "./workspace-cleanup.js";
|
|
16
17
|
import { getBotTokenForTeam, setBotTokenForTeam } from "./workspace-tokens.js";
|
|
17
18
|
|
|
18
|
-
export { SlackErrorType, ToolApprovalButtonValueSchema, buildAgentSelectorModal, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, executeAgentPublicly, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotMemberChannels, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserByEmail, getSlackUserInfo, getSlackUsers, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleDirectMessage, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, lookupAgentName, lookupProjectName, markdownToMrkdwn, openDmConversation, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, validateBotChannelMembership, verifySlackRequest };
|
|
19
|
+
export { SlackErrorType, ToolApprovalButtonValueSchema, buildAgentSelectorModal, buildCitationsBlock, buildDataArtifactBlocks, buildDataComponentBlocks, buildMessageShortcutModal, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, checkIfBotThread, checkUserIsChannelMember, classifyError, cleanupWorkspaceInstallation, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createContextBlockFromText, createCreateInkeepAccountMessage, createErrorMessage, createNotLinkedMessage, createSmartLinkMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, executeAgentPublicly, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotMemberChannels, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserByEmail, getSlackUserInfo, getSlackUsers, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleDirectMessage, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleQuestionCommand, handleStatusCommand, handleToolApproval, handleUnlinkCommand, listWorkspaceInstallations, lookupAgentName, lookupProjectName, markdownToMrkdwn, openDmConversation, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, validateBotChannelMembership, verifySlackRequest };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SlackLinkIntent } from "@inkeep/agents-core";
|
|
2
|
-
import * as
|
|
2
|
+
import * as slack_block_builder7 from "slack-block-builder";
|
|
3
3
|
|
|
4
4
|
//#region src/slack/services/link-prompt.d.ts
|
|
5
5
|
type LinkPromptResult = {
|
|
@@ -22,6 +22,6 @@ interface ResolveLinkActionParams {
|
|
|
22
22
|
intent?: SlackLinkIntent;
|
|
23
23
|
}
|
|
24
24
|
declare function resolveUnlinkedUserAction(params: ResolveLinkActionParams): Promise<LinkPromptResult>;
|
|
25
|
-
declare function buildLinkPromptMessage(result: LinkPromptResult): Readonly<
|
|
25
|
+
declare function buildLinkPromptMessage(result: LinkPromptResult): Readonly<slack_block_builder7.SlackMessageDto>;
|
|
26
26
|
//#endregion
|
|
27
27
|
export { LinkPromptResult, ResolveLinkActionParams, buildLinkPromptMessage, resolveUnlinkedUserAction };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/slack/services/workspace-cleanup.d.ts
|
|
2
|
+
interface WorkspaceCleanupResult {
|
|
3
|
+
success: boolean;
|
|
4
|
+
teamId: string;
|
|
5
|
+
tokenRevoked: boolean;
|
|
6
|
+
dbCleaned: boolean;
|
|
7
|
+
nangoCleaned: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare function cleanupWorkspaceInstallation({
|
|
10
|
+
teamId,
|
|
11
|
+
skipTokenRevocation
|
|
12
|
+
}: {
|
|
13
|
+
teamId: string;
|
|
14
|
+
skipTokenRevocation?: boolean;
|
|
15
|
+
}): Promise<WorkspaceCleanupResult>;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { WorkspaceCleanupResult, cleanupWorkspaceInstallation };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { getLogger } from "../../logger.js";
|
|
2
|
+
import runDbClient_default from "../../db/runDbClient.js";
|
|
3
|
+
import { clearWorkspaceConnectionCache, deleteWorkspaceInstallation, findWorkspaceConnectionByTeamId } from "./nango.js";
|
|
4
|
+
import { revokeSlackToken } from "./client.js";
|
|
5
|
+
import "./index.js";
|
|
6
|
+
import { deleteAllSlackMcpToolAccessConfigsByTenant, deleteAllWorkAppSlackChannelAgentConfigsByTeam, deleteAllWorkAppSlackUserMappingsByTeam, deleteWorkAppSlackWorkspaceByNangoConnectionId } from "@inkeep/agents-core";
|
|
7
|
+
|
|
8
|
+
//#region src/slack/services/workspace-cleanup.ts
|
|
9
|
+
const logger = getLogger("slack-workspace-cleanup");
|
|
10
|
+
async function cleanupWorkspaceInstallation({ teamId, skipTokenRevocation = false }) {
|
|
11
|
+
const result = {
|
|
12
|
+
success: false,
|
|
13
|
+
teamId,
|
|
14
|
+
tokenRevoked: false,
|
|
15
|
+
dbCleaned: false,
|
|
16
|
+
nangoCleaned: false
|
|
17
|
+
};
|
|
18
|
+
const workspace = await findWorkspaceConnectionByTeamId(teamId);
|
|
19
|
+
if (!workspace) {
|
|
20
|
+
logger.warn({ teamId }, "No workspace found for cleanup");
|
|
21
|
+
clearWorkspaceConnectionCache(teamId);
|
|
22
|
+
result.success = true;
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
const { tenantId, botToken, connectionId } = workspace;
|
|
26
|
+
if (!skipTokenRevocation && botToken) {
|
|
27
|
+
result.tokenRevoked = await revokeSlackToken(botToken);
|
|
28
|
+
if (result.tokenRevoked) logger.info({ teamId }, "Revoked Slack bot token during cleanup");
|
|
29
|
+
else logger.warn({ teamId }, "Failed to revoke Slack bot token, continuing with cleanup");
|
|
30
|
+
}
|
|
31
|
+
const steps = [
|
|
32
|
+
{
|
|
33
|
+
name: "channel_configs",
|
|
34
|
+
run: () => deleteAllWorkAppSlackChannelAgentConfigsByTeam(runDbClient_default)(tenantId, teamId)
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "user_mappings",
|
|
38
|
+
run: () => deleteAllWorkAppSlackUserMappingsByTeam(runDbClient_default)(tenantId, teamId)
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "mcp_configs",
|
|
42
|
+
run: () => deleteAllSlackMcpToolAccessConfigsByTenant(runDbClient_default)(tenantId)
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "workspace_row",
|
|
46
|
+
run: () => deleteWorkAppSlackWorkspaceByNangoConnectionId(runDbClient_default)(connectionId)
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "nango_connection",
|
|
50
|
+
run: () => deleteWorkspaceInstallation(connectionId)
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
const failures = [];
|
|
54
|
+
for (const step of steps) try {
|
|
55
|
+
await step.run();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
failures.push(step.name);
|
|
58
|
+
logger.error({
|
|
59
|
+
error,
|
|
60
|
+
teamId,
|
|
61
|
+
connectionId,
|
|
62
|
+
step: step.name
|
|
63
|
+
}, "Cleanup step failed");
|
|
64
|
+
}
|
|
65
|
+
result.dbCleaned = !failures.some((f) => f !== "nango_connection");
|
|
66
|
+
result.nangoCleaned = !failures.includes("nango_connection");
|
|
67
|
+
clearWorkspaceConnectionCache(teamId);
|
|
68
|
+
result.success = failures.length === 0;
|
|
69
|
+
if (failures.length > 0) logger.error({
|
|
70
|
+
teamId,
|
|
71
|
+
connectionId,
|
|
72
|
+
failures
|
|
73
|
+
}, "Workspace cleanup completed with failures");
|
|
74
|
+
else logger.info({
|
|
75
|
+
teamId,
|
|
76
|
+
connectionId
|
|
77
|
+
}, "Workspace cleanup completed");
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
export { cleanupWorkspaceInstallation };
|
|
@@ -7,7 +7,6 @@ var oauth_config = {
|
|
|
7
7
|
"app_mentions:read",
|
|
8
8
|
"channels:history",
|
|
9
9
|
"channels:read",
|
|
10
|
-
"channels:join",
|
|
11
10
|
"chat:write",
|
|
12
11
|
"chat:write.public",
|
|
13
12
|
"commands",
|
|
@@ -23,10 +22,7 @@ var oauth_config = {
|
|
|
23
22
|
"mpim:write",
|
|
24
23
|
"team:read",
|
|
25
24
|
"users:read",
|
|
26
|
-
"users:read.email"
|
|
27
|
-
"search:read.public",
|
|
28
|
-
"search:read.files",
|
|
29
|
-
"search:read.users"
|
|
25
|
+
"users:read.email"
|
|
30
26
|
]
|
|
31
27
|
}
|
|
32
28
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkeep/agents-work-apps",
|
|
3
|
-
"version": "0.65.
|
|
3
|
+
"version": "0.65.2",
|
|
4
4
|
"description": "First party integrations for Inkeep Agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"minimatch": "^10.2.1",
|
|
36
36
|
"oxfmt": "^0.42.0",
|
|
37
37
|
"slack-block-builder": "^2.8.0",
|
|
38
|
-
"@inkeep/agents-core": "0.65.
|
|
38
|
+
"@inkeep/agents-core": "0.65.2"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@hono/zod-openapi": "^1.1.5",
|