@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.
- package/dist/db/index.d.ts +1 -2
- package/dist/db/index.js +1 -2
- package/dist/db/runDbClient.d.ts +2 -2
- package/dist/env.d.ts +2 -24
- package/dist/env.js +1 -12
- package/dist/github/routes/setup.d.ts +2 -2
- package/dist/github/routes/tokenExchange.d.ts +2 -2
- package/package.json +2 -10
- package/dist/db/manageDbClient.d.ts +0 -7
- package/dist/db/manageDbClient.js +0 -16
- package/dist/slack/index.d.ts +0 -19
- package/dist/slack/index.js +0 -29
- package/dist/slack/middleware/permissions.d.ts +0 -16
- package/dist/slack/middleware/permissions.js +0 -49
- package/dist/slack/routes/events.d.ts +0 -10
- package/dist/slack/routes/events.js +0 -319
- package/dist/slack/routes/index.d.ts +0 -11
- package/dist/slack/routes/index.js +0 -64
- package/dist/slack/routes/internal.d.ts +0 -10
- package/dist/slack/routes/internal.js +0 -107
- package/dist/slack/routes/oauth.d.ts +0 -12
- package/dist/slack/routes/oauth.js +0 -218
- package/dist/slack/routes/resources.d.ts +0 -10
- package/dist/slack/routes/resources.js +0 -163
- package/dist/slack/routes/users.d.ts +0 -15
- package/dist/slack/routes/users.js +0 -430
- package/dist/slack/routes/workspaces.d.ts +0 -10
- package/dist/slack/routes/workspaces.js +0 -828
- package/dist/slack/routes.d.ts +0 -7
- package/dist/slack/routes.js +0 -12
- package/dist/slack/services/agent-resolution.d.ts +0 -49
- package/dist/slack/services/agent-resolution.js +0 -135
- package/dist/slack/services/api-client.d.ts +0 -161
- package/dist/slack/services/api-client.js +0 -248
- package/dist/slack/services/auth/index.d.ts +0 -61
- package/dist/slack/services/auth/index.js +0 -164
- package/dist/slack/services/blocks/index.d.ts +0 -60
- package/dist/slack/services/blocks/index.js +0 -143
- package/dist/slack/services/client.d.ts +0 -78
- package/dist/slack/services/client.js +0 -152
- package/dist/slack/services/commands/index.d.ts +0 -15
- package/dist/slack/services/commands/index.js +0 -556
- package/dist/slack/services/events/app-mention.d.ts +0 -41
- package/dist/slack/services/events/app-mention.js +0 -212
- package/dist/slack/services/events/block-actions.d.ts +0 -47
- package/dist/slack/services/events/block-actions.js +0 -287
- package/dist/slack/services/events/index.d.ts +0 -6
- package/dist/slack/services/events/index.js +0 -7
- package/dist/slack/services/events/modal-submission.d.ts +0 -12
- package/dist/slack/services/events/modal-submission.js +0 -279
- package/dist/slack/services/events/streaming.d.ts +0 -27
- package/dist/slack/services/events/streaming.js +0 -285
- package/dist/slack/services/events/utils.d.ts +0 -129
- package/dist/slack/services/events/utils.js +0 -315
- package/dist/slack/services/index.d.ts +0 -18
- package/dist/slack/services/index.js +0 -18
- package/dist/slack/services/modals.d.ts +0 -67
- package/dist/slack/services/modals.js +0 -203
- package/dist/slack/services/nango.d.ts +0 -82
- package/dist/slack/services/nango.js +0 -326
- package/dist/slack/services/security.d.ts +0 -35
- package/dist/slack/services/security.js +0 -65
- package/dist/slack/services/types.d.ts +0 -26
- package/dist/slack/services/types.js +0 -1
- package/dist/slack/services/workspace-tokens.d.ts +0 -37
- package/dist/slack/services/workspace-tokens.js +0 -39
- package/dist/slack/types.d.ts +0 -10
- package/dist/slack/types.js +0 -1
package/dist/slack/routes.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { getChannelAgentConfig, getWorkspaceDefaultAgent } from "./services/events/utils.js";
|
|
2
|
-
import "./services/events/index.js";
|
|
3
|
-
import { getBotTokenForTeam, setBotTokenForTeam } from "./services/workspace-tokens.js";
|
|
4
|
-
import "./routes/oauth.js";
|
|
5
|
-
import { pendingSessionTokens } from "./routes/users.js";
|
|
6
|
-
import app from "./routes/index.js";
|
|
7
|
-
export { app as default, getBotTokenForTeam, getChannelAgentConfig, getWorkspaceDefaultAgent, pendingSessionTokens, setBotTokenForTeam };
|
package/dist/slack/routes.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { getBotTokenForTeam, setBotTokenForTeam } from "./services/workspace-tokens.js";
|
|
2
|
-
import { getChannelAgentConfig, getWorkspaceDefaultAgent } from "./services/events/utils.js";
|
|
3
|
-
import "./services/events/index.js";
|
|
4
|
-
import "./routes/oauth.js";
|
|
5
|
-
import { pendingSessionTokens } from "./routes/users.js";
|
|
6
|
-
import routes_default$1 from "./routes/index.js";
|
|
7
|
-
|
|
8
|
-
//#region src/slack/routes.ts
|
|
9
|
-
var routes_default = routes_default$1;
|
|
10
|
-
|
|
11
|
-
//#endregion
|
|
12
|
-
export { routes_default as default, getBotTokenForTeam, getChannelAgentConfig, getWorkspaceDefaultAgent, pendingSessionTokens, setBotTokenForTeam };
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
//#region src/slack/services/agent-resolution.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Slack Agent Resolution Service
|
|
4
|
-
*
|
|
5
|
-
* Determines which agent to use for a given Slack interaction.
|
|
6
|
-
*
|
|
7
|
-
* For @mentions (bot interactions):
|
|
8
|
-
* - Uses Channel > Workspace defaults (admin-controlled)
|
|
9
|
-
*
|
|
10
|
-
* For /slash commands (user interactions):
|
|
11
|
-
* - User personal default > Channel > Workspace
|
|
12
|
-
* - Users can set their own default via /inkeep settings
|
|
13
|
-
*/
|
|
14
|
-
/** Configuration for a resolved agent */
|
|
15
|
-
interface ResolvedAgentConfig {
|
|
16
|
-
projectId: string;
|
|
17
|
-
agentId: string;
|
|
18
|
-
agentName?: string;
|
|
19
|
-
source: 'channel' | 'workspace' | 'user' | 'none';
|
|
20
|
-
}
|
|
21
|
-
interface AgentResolutionParams {
|
|
22
|
-
tenantId: string;
|
|
23
|
-
teamId: string;
|
|
24
|
-
channelId?: string;
|
|
25
|
-
userId?: string;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Resolve the effective agent configuration for a Slack slash command.
|
|
29
|
-
* Priority: User personal default > Channel override > Workspace default
|
|
30
|
-
*
|
|
31
|
-
* @param params - Resolution parameters including tenant, team, channel, and user IDs
|
|
32
|
-
* @returns The resolved agent configuration, or null if no agent is configured
|
|
33
|
-
*/
|
|
34
|
-
declare function resolveEffectiveAgent(params: AgentResolutionParams): Promise<ResolvedAgentConfig | null>;
|
|
35
|
-
/**
|
|
36
|
-
* Get all agent configuration sources for debugging and display purposes.
|
|
37
|
-
* Returns each level of configuration and the effective result.
|
|
38
|
-
*
|
|
39
|
-
* @param params - Resolution parameters
|
|
40
|
-
* @returns Object containing channel, workspace, user configs, and the effective choice
|
|
41
|
-
*/
|
|
42
|
-
declare function getAgentConfigSources(params: AgentResolutionParams): Promise<{
|
|
43
|
-
channelConfig: ResolvedAgentConfig | null;
|
|
44
|
-
workspaceConfig: ResolvedAgentConfig | null;
|
|
45
|
-
userConfig: ResolvedAgentConfig | null;
|
|
46
|
-
effective: ResolvedAgentConfig | null;
|
|
47
|
-
}>;
|
|
48
|
-
//#endregion
|
|
49
|
-
export { AgentResolutionParams, ResolvedAgentConfig, getAgentConfigSources, resolveEffectiveAgent };
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { getLogger } from "../../logger.js";
|
|
2
|
-
import runDbClient_default from "../../db/runDbClient.js";
|
|
3
|
-
import { getWorkspaceDefaultAgentFromNango } from "./nango.js";
|
|
4
|
-
import { findWorkAppSlackChannelAgentConfig, findWorkAppSlackUserSettings } from "@inkeep/agents-core";
|
|
5
|
-
|
|
6
|
-
//#region src/slack/services/agent-resolution.ts
|
|
7
|
-
/**
|
|
8
|
-
* Slack Agent Resolution Service
|
|
9
|
-
*
|
|
10
|
-
* Determines which agent to use for a given Slack interaction.
|
|
11
|
-
*
|
|
12
|
-
* For @mentions (bot interactions):
|
|
13
|
-
* - Uses Channel > Workspace defaults (admin-controlled)
|
|
14
|
-
*
|
|
15
|
-
* For /slash commands (user interactions):
|
|
16
|
-
* - User personal default > Channel > Workspace
|
|
17
|
-
* - Users can set their own default via /inkeep settings
|
|
18
|
-
*/
|
|
19
|
-
const logger = getLogger("slack-agent-resolution");
|
|
20
|
-
/**
|
|
21
|
-
* Resolve the effective agent configuration for a Slack slash command.
|
|
22
|
-
* Priority: User personal default > Channel override > Workspace default
|
|
23
|
-
*
|
|
24
|
-
* @param params - Resolution parameters including tenant, team, channel, and user IDs
|
|
25
|
-
* @returns The resolved agent configuration, or null if no agent is configured
|
|
26
|
-
*/
|
|
27
|
-
async function resolveEffectiveAgent(params) {
|
|
28
|
-
const { tenantId, teamId, channelId, userId } = params;
|
|
29
|
-
logger.debug({
|
|
30
|
-
tenantId,
|
|
31
|
-
teamId,
|
|
32
|
-
channelId,
|
|
33
|
-
userId
|
|
34
|
-
}, "Resolving effective agent");
|
|
35
|
-
if (userId) {
|
|
36
|
-
const userSettings = await findWorkAppSlackUserSettings(runDbClient_default)(tenantId, teamId, userId);
|
|
37
|
-
if (userSettings?.defaultAgentId && userSettings.defaultProjectId) {
|
|
38
|
-
logger.info({
|
|
39
|
-
userId,
|
|
40
|
-
agentId: userSettings.defaultAgentId,
|
|
41
|
-
source: "user"
|
|
42
|
-
}, "Resolved agent from user settings");
|
|
43
|
-
return {
|
|
44
|
-
projectId: userSettings.defaultProjectId,
|
|
45
|
-
agentId: userSettings.defaultAgentId,
|
|
46
|
-
agentName: userSettings.defaultAgentName || void 0,
|
|
47
|
-
source: "user"
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (channelId) {
|
|
52
|
-
const channelConfig = await findWorkAppSlackChannelAgentConfig(runDbClient_default)(tenantId, teamId, channelId);
|
|
53
|
-
if (channelConfig?.enabled) {
|
|
54
|
-
logger.info({
|
|
55
|
-
channelId,
|
|
56
|
-
agentId: channelConfig.agentId,
|
|
57
|
-
source: "channel"
|
|
58
|
-
}, "Resolved agent from channel config");
|
|
59
|
-
return {
|
|
60
|
-
projectId: channelConfig.projectId,
|
|
61
|
-
agentId: channelConfig.agentId,
|
|
62
|
-
agentName: channelConfig.agentName || void 0,
|
|
63
|
-
source: "channel"
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const workspaceConfig = await getWorkspaceDefaultAgentFromNango(teamId);
|
|
68
|
-
if (workspaceConfig?.agentId && workspaceConfig.projectId) {
|
|
69
|
-
logger.info({
|
|
70
|
-
teamId,
|
|
71
|
-
agentId: workspaceConfig.agentId,
|
|
72
|
-
source: "workspace"
|
|
73
|
-
}, "Resolved agent from workspace config");
|
|
74
|
-
return {
|
|
75
|
-
projectId: workspaceConfig.projectId,
|
|
76
|
-
agentId: workspaceConfig.agentId,
|
|
77
|
-
agentName: workspaceConfig.agentName,
|
|
78
|
-
source: "workspace"
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
logger.debug({
|
|
82
|
-
tenantId,
|
|
83
|
-
teamId,
|
|
84
|
-
channelId,
|
|
85
|
-
userId
|
|
86
|
-
}, "No agent configuration found");
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Get all agent configuration sources for debugging and display purposes.
|
|
91
|
-
* Returns each level of configuration and the effective result.
|
|
92
|
-
*
|
|
93
|
-
* @param params - Resolution parameters
|
|
94
|
-
* @returns Object containing channel, workspace, user configs, and the effective choice
|
|
95
|
-
*/
|
|
96
|
-
async function getAgentConfigSources(params) {
|
|
97
|
-
const { tenantId, teamId, channelId, userId } = params;
|
|
98
|
-
let channelConfig = null;
|
|
99
|
-
let workspaceConfig = null;
|
|
100
|
-
let userConfig = null;
|
|
101
|
-
if (channelId) {
|
|
102
|
-
const config = await findWorkAppSlackChannelAgentConfig(runDbClient_default)(tenantId, teamId, channelId);
|
|
103
|
-
if (config?.enabled) channelConfig = {
|
|
104
|
-
projectId: config.projectId,
|
|
105
|
-
agentId: config.agentId,
|
|
106
|
-
agentName: config.agentName || void 0,
|
|
107
|
-
source: "channel"
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
const wsConfig = await getWorkspaceDefaultAgentFromNango(teamId);
|
|
111
|
-
if (wsConfig?.agentId && wsConfig.projectId) workspaceConfig = {
|
|
112
|
-
projectId: wsConfig.projectId,
|
|
113
|
-
agentId: wsConfig.agentId,
|
|
114
|
-
agentName: wsConfig.agentName,
|
|
115
|
-
source: "workspace"
|
|
116
|
-
};
|
|
117
|
-
if (userId) {
|
|
118
|
-
const settings = await findWorkAppSlackUserSettings(runDbClient_default)(tenantId, teamId, userId);
|
|
119
|
-
if (settings?.defaultAgentId && settings.defaultProjectId) userConfig = {
|
|
120
|
-
projectId: settings.defaultProjectId,
|
|
121
|
-
agentId: settings.defaultAgentId,
|
|
122
|
-
agentName: settings.defaultAgentName || void 0,
|
|
123
|
-
source: "user"
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
return {
|
|
127
|
-
channelConfig,
|
|
128
|
-
workspaceConfig,
|
|
129
|
-
userConfig,
|
|
130
|
-
effective: userConfig || channelConfig || workspaceConfig
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
//#endregion
|
|
135
|
-
export { getAgentConfigSources, resolveEffectiveAgent };
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
//#region src/slack/services/api-client.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Slack API Client
|
|
4
|
-
*
|
|
5
|
-
* A reusable client for making authenticated API calls from Slack commands.
|
|
6
|
-
* Uses the user's session token stored in Nango to authenticate requests.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* ```typescript
|
|
10
|
-
* const client = new SlackApiClient({
|
|
11
|
-
* sessionToken: connection.inkeepSessionToken,
|
|
12
|
-
* tenantId: connection.tenantId,
|
|
13
|
-
* });
|
|
14
|
-
*
|
|
15
|
-
* const projects = await client.listProjects();
|
|
16
|
-
* const agents = await client.listAgents(projectId);
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
declare class SlackApiError extends Error {
|
|
20
|
-
readonly statusCode: number;
|
|
21
|
-
readonly responseBody?: string | undefined;
|
|
22
|
-
constructor(message: string, statusCode: number, responseBody?: string | undefined);
|
|
23
|
-
get isUnauthorized(): boolean;
|
|
24
|
-
get isForbidden(): boolean;
|
|
25
|
-
get isNotFound(): boolean;
|
|
26
|
-
}
|
|
27
|
-
interface SlackApiClientConfig {
|
|
28
|
-
sessionToken: string;
|
|
29
|
-
tenantId: string;
|
|
30
|
-
apiUrl?: string;
|
|
31
|
-
}
|
|
32
|
-
interface PaginatedResponse<T> {
|
|
33
|
-
data: T[];
|
|
34
|
-
pagination: {
|
|
35
|
-
page: number;
|
|
36
|
-
limit: number;
|
|
37
|
-
total: number;
|
|
38
|
-
pages: number;
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
interface Project {
|
|
42
|
-
id: string;
|
|
43
|
-
name: string | null;
|
|
44
|
-
description: string | null;
|
|
45
|
-
tenantId: string;
|
|
46
|
-
createdAt: string;
|
|
47
|
-
updatedAt: string;
|
|
48
|
-
}
|
|
49
|
-
interface Agent {
|
|
50
|
-
id: string;
|
|
51
|
-
name: string | null;
|
|
52
|
-
description: string | null;
|
|
53
|
-
projectId: string;
|
|
54
|
-
createdAt: string;
|
|
55
|
-
updatedAt: string;
|
|
56
|
-
}
|
|
57
|
-
interface ApiKey {
|
|
58
|
-
id: string;
|
|
59
|
-
name: string;
|
|
60
|
-
agentId: string;
|
|
61
|
-
keyPrefix: string;
|
|
62
|
-
expiresAt: string | null;
|
|
63
|
-
createdAt: string;
|
|
64
|
-
}
|
|
65
|
-
interface ApiKeyCreationResponse {
|
|
66
|
-
apiKey: ApiKey;
|
|
67
|
-
key: string;
|
|
68
|
-
}
|
|
69
|
-
interface AgentWithProject extends Agent {
|
|
70
|
-
projectName: string | null;
|
|
71
|
-
}
|
|
72
|
-
interface ChatMessage {
|
|
73
|
-
role: 'user' | 'assistant' | 'system';
|
|
74
|
-
content: string;
|
|
75
|
-
}
|
|
76
|
-
interface ChatCompletionResponse {
|
|
77
|
-
id: string;
|
|
78
|
-
object: string;
|
|
79
|
-
created: number;
|
|
80
|
-
model: string;
|
|
81
|
-
choices: Array<{
|
|
82
|
-
index: number;
|
|
83
|
-
message: {
|
|
84
|
-
role: string;
|
|
85
|
-
content: string;
|
|
86
|
-
};
|
|
87
|
-
finish_reason: string;
|
|
88
|
-
}>;
|
|
89
|
-
}
|
|
90
|
-
declare class SlackApiClient {
|
|
91
|
-
private readonly sessionToken;
|
|
92
|
-
private readonly tenantId;
|
|
93
|
-
private readonly apiUrl;
|
|
94
|
-
constructor(config: SlackApiClientConfig);
|
|
95
|
-
private get headers();
|
|
96
|
-
private buildUrl;
|
|
97
|
-
private request;
|
|
98
|
-
listProjects(options?: {
|
|
99
|
-
page?: number;
|
|
100
|
-
limit?: number;
|
|
101
|
-
}): Promise<PaginatedResponse<Project>>;
|
|
102
|
-
getProject(projectId: string): Promise<{
|
|
103
|
-
data: Project;
|
|
104
|
-
}>;
|
|
105
|
-
listAgents(projectId: string, options?: {
|
|
106
|
-
page?: number;
|
|
107
|
-
limit?: number;
|
|
108
|
-
}): Promise<PaginatedResponse<Agent>>;
|
|
109
|
-
getAgent(projectId: string, agentId: string): Promise<{
|
|
110
|
-
data: Agent;
|
|
111
|
-
}>;
|
|
112
|
-
listAllAgents(): Promise<AgentWithProject[]>;
|
|
113
|
-
findAgentByName(agentName: string): Promise<AgentWithProject | null>;
|
|
114
|
-
/**
|
|
115
|
-
* Trigger an agent and get a response.
|
|
116
|
-
* Uses the session token for auth via the sub-agent chat completions endpoint.
|
|
117
|
-
*/
|
|
118
|
-
triggerAgent(params: {
|
|
119
|
-
projectId: string;
|
|
120
|
-
agentId: string;
|
|
121
|
-
subAgentId: string;
|
|
122
|
-
question: string;
|
|
123
|
-
conversationId?: string;
|
|
124
|
-
}): Promise<{
|
|
125
|
-
content: string;
|
|
126
|
-
conversationId?: string;
|
|
127
|
-
}>;
|
|
128
|
-
listApiKeys(projectId: string, agentId?: string): Promise<PaginatedResponse<ApiKey>>;
|
|
129
|
-
createApiKey(projectId: string, agentId: string, name: string): Promise<{
|
|
130
|
-
data: ApiKeyCreationResponse;
|
|
131
|
-
}>;
|
|
132
|
-
deleteApiKey(projectId: string, apiKeyId: string): Promise<void>;
|
|
133
|
-
getOrCreateAgentApiKey(projectId: string, agentId: string): Promise<string>;
|
|
134
|
-
getTenantId(): string;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Factory function to create a SlackApiClient from a Nango connection
|
|
138
|
-
*/
|
|
139
|
-
declare function createSlackApiClient(connection: {
|
|
140
|
-
inkeepSessionToken?: string;
|
|
141
|
-
inkeepSessionExpiresAt?: string;
|
|
142
|
-
tenantId?: string;
|
|
143
|
-
}): SlackApiClient;
|
|
144
|
-
/**
|
|
145
|
-
* Send a deferred response to Slack via response_url
|
|
146
|
-
*
|
|
147
|
-
* Slack slash commands have a 3-second timeout. For long-running operations
|
|
148
|
-
* like agent execution, we need to:
|
|
149
|
-
* 1. Respond immediately with a "thinking" message
|
|
150
|
-
* 2. Process the request asynchronously
|
|
151
|
-
* 3. Send the actual response via response_url
|
|
152
|
-
*/
|
|
153
|
-
declare function sendDeferredResponse(responseUrl: string, message: {
|
|
154
|
-
response_type?: 'ephemeral' | 'in_channel';
|
|
155
|
-
text?: string;
|
|
156
|
-
blocks?: unknown[];
|
|
157
|
-
replace_original?: boolean;
|
|
158
|
-
delete_original?: boolean;
|
|
159
|
-
}): Promise<void>;
|
|
160
|
-
//#endregion
|
|
161
|
-
export { Agent, AgentWithProject, ApiKey, ApiKeyCreationResponse, ChatCompletionResponse, ChatMessage, PaginatedResponse, Project, SlackApiClient, SlackApiClientConfig, SlackApiError, createSlackApiClient, sendDeferredResponse };
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import { env } from "../../env.js";
|
|
2
|
-
import { getLogger } from "../../logger.js";
|
|
3
|
-
|
|
4
|
-
//#region src/slack/services/api-client.ts
|
|
5
|
-
/**
|
|
6
|
-
* Slack API Client
|
|
7
|
-
*
|
|
8
|
-
* A reusable client for making authenticated API calls from Slack commands.
|
|
9
|
-
* Uses the user's session token stored in Nango to authenticate requests.
|
|
10
|
-
*
|
|
11
|
-
* Usage:
|
|
12
|
-
* ```typescript
|
|
13
|
-
* const client = new SlackApiClient({
|
|
14
|
-
* sessionToken: connection.inkeepSessionToken,
|
|
15
|
-
* tenantId: connection.tenantId,
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* const projects = await client.listProjects();
|
|
19
|
-
* const agents = await client.listAgents(projectId);
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
const logger = getLogger("slack-api-client");
|
|
23
|
-
var SlackApiError = class extends Error {
|
|
24
|
-
constructor(message, statusCode, responseBody) {
|
|
25
|
-
super(message);
|
|
26
|
-
this.statusCode = statusCode;
|
|
27
|
-
this.responseBody = responseBody;
|
|
28
|
-
this.name = "SlackApiError";
|
|
29
|
-
}
|
|
30
|
-
get isUnauthorized() {
|
|
31
|
-
return this.statusCode === 401;
|
|
32
|
-
}
|
|
33
|
-
get isForbidden() {
|
|
34
|
-
return this.statusCode === 403;
|
|
35
|
-
}
|
|
36
|
-
get isNotFound() {
|
|
37
|
-
return this.statusCode === 404;
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
var SlackApiClient = class {
|
|
41
|
-
sessionToken;
|
|
42
|
-
tenantId;
|
|
43
|
-
apiUrl;
|
|
44
|
-
constructor(config) {
|
|
45
|
-
this.sessionToken = config.sessionToken;
|
|
46
|
-
this.tenantId = config.tenantId;
|
|
47
|
-
this.apiUrl = config.apiUrl || env.INKEEP_AGENTS_API_URL || "http://localhost:3002";
|
|
48
|
-
}
|
|
49
|
-
get headers() {
|
|
50
|
-
return {
|
|
51
|
-
"Content-Type": "application/json",
|
|
52
|
-
Authorization: `Bearer ${this.sessionToken}`
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
buildUrl(path, params) {
|
|
56
|
-
const normalizedBase = this.apiUrl.replace(/\/$/, "");
|
|
57
|
-
const url = new URL(`${normalizedBase}${path}`);
|
|
58
|
-
if (params) {
|
|
59
|
-
for (const [key, value] of Object.entries(params)) if (value !== void 0) url.searchParams.set(key, String(value));
|
|
60
|
-
}
|
|
61
|
-
return url.toString();
|
|
62
|
-
}
|
|
63
|
-
async request(method, path, options) {
|
|
64
|
-
const url = this.buildUrl(path, options?.params);
|
|
65
|
-
logger.debug({
|
|
66
|
-
method,
|
|
67
|
-
path,
|
|
68
|
-
tenantId: this.tenantId
|
|
69
|
-
}, "Making API request");
|
|
70
|
-
const response = await fetch(url, {
|
|
71
|
-
method,
|
|
72
|
-
headers: this.headers,
|
|
73
|
-
body: options?.body ? JSON.stringify(options.body) : void 0
|
|
74
|
-
});
|
|
75
|
-
if (!response.ok) {
|
|
76
|
-
const errorBody = await response.text().catch(() => "Unknown error");
|
|
77
|
-
logger.error({
|
|
78
|
-
status: response.status,
|
|
79
|
-
path,
|
|
80
|
-
tenantId: this.tenantId
|
|
81
|
-
}, "API request failed");
|
|
82
|
-
if (response.status === 401) throw new SlackApiError("Session expired. Please re-link your account from the dashboard.", response.status, errorBody);
|
|
83
|
-
throw new SlackApiError(`API error: ${response.status} ${response.statusText}`, response.status, errorBody);
|
|
84
|
-
}
|
|
85
|
-
if (response.status === 204 || options?.expectNoContent) return;
|
|
86
|
-
return response.json();
|
|
87
|
-
}
|
|
88
|
-
async listProjects(options) {
|
|
89
|
-
return this.request("GET", `/manage/tenants/${this.tenantId}/projects`, { params: {
|
|
90
|
-
page: options?.page || 1,
|
|
91
|
-
limit: options?.limit || 100
|
|
92
|
-
} });
|
|
93
|
-
}
|
|
94
|
-
async getProject(projectId) {
|
|
95
|
-
return this.request("GET", `/manage/tenants/${this.tenantId}/projects/${projectId}`);
|
|
96
|
-
}
|
|
97
|
-
async listAgents(projectId, options) {
|
|
98
|
-
return this.request("GET", `/manage/tenants/${this.tenantId}/projects/${projectId}/agents`, { params: {
|
|
99
|
-
page: options?.page || 1,
|
|
100
|
-
limit: options?.limit || 100
|
|
101
|
-
} });
|
|
102
|
-
}
|
|
103
|
-
async getAgent(projectId, agentId) {
|
|
104
|
-
return this.request("GET", `/manage/tenants/${this.tenantId}/projects/${projectId}/agents/${agentId}`);
|
|
105
|
-
}
|
|
106
|
-
async listAllAgents() {
|
|
107
|
-
const projectsResult = await this.listProjects({ limit: 100 });
|
|
108
|
-
return (await Promise.all(projectsResult.data.map(async (project) => {
|
|
109
|
-
try {
|
|
110
|
-
return (await this.listAgents(project.id, { limit: 100 })).data.map((agent) => ({
|
|
111
|
-
...agent,
|
|
112
|
-
projectName: project.name
|
|
113
|
-
}));
|
|
114
|
-
} catch (error) {
|
|
115
|
-
logger.warn({
|
|
116
|
-
projectId: project.id,
|
|
117
|
-
error
|
|
118
|
-
}, "Failed to list agents for project");
|
|
119
|
-
return [];
|
|
120
|
-
}
|
|
121
|
-
}))).flat();
|
|
122
|
-
}
|
|
123
|
-
async findAgentByName(agentName) {
|
|
124
|
-
const agents = await this.listAllAgents();
|
|
125
|
-
const normalizedSearch = agentName.toLowerCase().trim();
|
|
126
|
-
const exactMatch = agents.find((a) => a.name?.toLowerCase() === normalizedSearch || a.id.toLowerCase() === normalizedSearch);
|
|
127
|
-
if (exactMatch) return exactMatch;
|
|
128
|
-
return agents.find((a) => a.name?.toLowerCase().includes(normalizedSearch) || a.id.toLowerCase().includes(normalizedSearch)) || null;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Trigger an agent and get a response.
|
|
132
|
-
* Uses the session token for auth via the sub-agent chat completions endpoint.
|
|
133
|
-
*/
|
|
134
|
-
async triggerAgent(params) {
|
|
135
|
-
const { projectId, agentId, subAgentId, question, conversationId } = params;
|
|
136
|
-
logger.info({
|
|
137
|
-
projectId,
|
|
138
|
-
agentId,
|
|
139
|
-
subAgentId,
|
|
140
|
-
tenantId: this.tenantId
|
|
141
|
-
}, "Triggering agent from Slack");
|
|
142
|
-
const url = this.buildUrl(`/run/tenants/${this.tenantId}/projects/${projectId}/agents/${agentId}/sub-agents/${subAgentId}/chat/completions`);
|
|
143
|
-
const response = await fetch(url, {
|
|
144
|
-
method: "POST",
|
|
145
|
-
headers: this.headers,
|
|
146
|
-
body: JSON.stringify({
|
|
147
|
-
model: subAgentId,
|
|
148
|
-
messages: [{
|
|
149
|
-
role: "user",
|
|
150
|
-
content: question
|
|
151
|
-
}],
|
|
152
|
-
stream: false,
|
|
153
|
-
...conversationId ? { conversationId } : {}
|
|
154
|
-
})
|
|
155
|
-
});
|
|
156
|
-
if (!response.ok) {
|
|
157
|
-
const errorBody = await response.text().catch(() => "Unknown error");
|
|
158
|
-
logger.error({
|
|
159
|
-
status: response.status,
|
|
160
|
-
projectId,
|
|
161
|
-
agentId,
|
|
162
|
-
subAgentId
|
|
163
|
-
}, "Agent trigger failed");
|
|
164
|
-
if (response.status === 401) throw new SlackApiError("Session expired. Please re-link your account from the dashboard.", response.status, errorBody);
|
|
165
|
-
throw new SlackApiError(`Failed to trigger agent: ${response.status}`, response.status, errorBody);
|
|
166
|
-
}
|
|
167
|
-
const result = await response.json();
|
|
168
|
-
return {
|
|
169
|
-
content: result.choices?.[0]?.message?.content || result.content || "No response from agent",
|
|
170
|
-
conversationId: result.conversationId
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
async listApiKeys(projectId, agentId) {
|
|
174
|
-
const params = { limit: 100 };
|
|
175
|
-
if (agentId) params.agentId = agentId;
|
|
176
|
-
return this.request("GET", `/manage/tenants/${this.tenantId}/projects/${projectId}/api-keys`, { params });
|
|
177
|
-
}
|
|
178
|
-
async createApiKey(projectId, agentId, name) {
|
|
179
|
-
return this.request("POST", `/manage/tenants/${this.tenantId}/projects/${projectId}/api-keys`, { body: {
|
|
180
|
-
agentId,
|
|
181
|
-
name
|
|
182
|
-
} });
|
|
183
|
-
}
|
|
184
|
-
async deleteApiKey(projectId, apiKeyId) {
|
|
185
|
-
await this.request("DELETE", `/manage/tenants/${this.tenantId}/projects/${projectId}/api-keys/${apiKeyId}`, { expectNoContent: true });
|
|
186
|
-
}
|
|
187
|
-
async getOrCreateAgentApiKey(projectId, agentId) {
|
|
188
|
-
const slackKey = (await this.listApiKeys(projectId, agentId)).data.find((k) => k.name === "slack-integration");
|
|
189
|
-
if (slackKey) {
|
|
190
|
-
logger.debug({
|
|
191
|
-
apiKeyId: slackKey.id,
|
|
192
|
-
agentId
|
|
193
|
-
}, "Deleting existing slack-integration key to create fresh one");
|
|
194
|
-
await this.deleteApiKey(projectId, slackKey.id);
|
|
195
|
-
}
|
|
196
|
-
return (await this.createApiKey(projectId, agentId, "slack-integration")).data.key;
|
|
197
|
-
}
|
|
198
|
-
getTenantId() {
|
|
199
|
-
return this.tenantId;
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
/**
|
|
203
|
-
* Factory function to create a SlackApiClient from a Nango connection
|
|
204
|
-
*/
|
|
205
|
-
function createSlackApiClient(connection) {
|
|
206
|
-
if (!connection.inkeepSessionToken) throw new SlackApiError("Session expired. Please re-link your account from the dashboard.", 401);
|
|
207
|
-
if (connection.inkeepSessionExpiresAt) {
|
|
208
|
-
if (new Date(connection.inkeepSessionExpiresAt) < /* @__PURE__ */ new Date()) throw new SlackApiError("Session expired. Please re-link your account from the dashboard.", 401);
|
|
209
|
-
}
|
|
210
|
-
return new SlackApiClient({
|
|
211
|
-
sessionToken: connection.inkeepSessionToken,
|
|
212
|
-
tenantId: connection.tenantId || "default"
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Send a deferred response to Slack via response_url
|
|
217
|
-
*
|
|
218
|
-
* Slack slash commands have a 3-second timeout. For long-running operations
|
|
219
|
-
* like agent execution, we need to:
|
|
220
|
-
* 1. Respond immediately with a "thinking" message
|
|
221
|
-
* 2. Process the request asynchronously
|
|
222
|
-
* 3. Send the actual response via response_url
|
|
223
|
-
*/
|
|
224
|
-
async function sendDeferredResponse(responseUrl, message) {
|
|
225
|
-
try {
|
|
226
|
-
const response = await fetch(responseUrl, {
|
|
227
|
-
method: "POST",
|
|
228
|
-
headers: { "Content-Type": "application/json" },
|
|
229
|
-
body: JSON.stringify({
|
|
230
|
-
response_type: message.response_type || "ephemeral",
|
|
231
|
-
replace_original: message.replace_original ?? true,
|
|
232
|
-
...message
|
|
233
|
-
})
|
|
234
|
-
});
|
|
235
|
-
if (!response.ok) {
|
|
236
|
-
const errorBody = await response.text().catch(() => "Unknown error");
|
|
237
|
-
logger.error({
|
|
238
|
-
status: response.status,
|
|
239
|
-
errorBody
|
|
240
|
-
}, "Failed to send deferred Slack response");
|
|
241
|
-
} else logger.debug({}, "Deferred Slack response sent successfully");
|
|
242
|
-
} catch (error) {
|
|
243
|
-
logger.error({ error }, "Error sending deferred Slack response");
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
//#endregion
|
|
248
|
-
export { SlackApiClient, SlackApiError, createSlackApiClient, sendDeferredResponse };
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { SlackAccessTokenPayload } from "@inkeep/agents-core";
|
|
2
|
-
|
|
3
|
-
//#region src/slack/services/auth/index.d.ts
|
|
4
|
-
|
|
5
|
-
interface SlackUserContext {
|
|
6
|
-
slackUserId: string;
|
|
7
|
-
slackTeamId: string;
|
|
8
|
-
slackEnterpriseId?: string;
|
|
9
|
-
}
|
|
10
|
-
interface SlackJwtResult {
|
|
11
|
-
token: string;
|
|
12
|
-
inkeepUserId: string;
|
|
13
|
-
tenantId: string;
|
|
14
|
-
}
|
|
15
|
-
declare class SlackJwtAuthError extends Error {
|
|
16
|
-
readonly code: 'NOT_LINKED' | 'TOKEN_EXPIRED' | 'TOKEN_INVALID' | 'EXECUTION_FAILED';
|
|
17
|
-
constructor(message: string, code: 'NOT_LINKED' | 'TOKEN_EXPIRED' | 'TOKEN_INVALID' | 'EXECUTION_FAILED');
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Get a JWT token for a Slack user to call Inkeep APIs.
|
|
21
|
-
*
|
|
22
|
-
* Looks up the user's linked Inkeep account and generates a short-lived JWT.
|
|
23
|
-
*/
|
|
24
|
-
declare function getSlackUserJwt(context: SlackUserContext, tenantId: string): Promise<SlackJwtResult>;
|
|
25
|
-
/**
|
|
26
|
-
* Verify a Slack JWT token and extract the payload.
|
|
27
|
-
*/
|
|
28
|
-
declare function verifySlackJwt(token: string): Promise<SlackAccessTokenPayload>;
|
|
29
|
-
interface ChatCompletionOptions {
|
|
30
|
-
conversationId?: string;
|
|
31
|
-
stream?: boolean;
|
|
32
|
-
}
|
|
33
|
-
interface ChatCompletionResult {
|
|
34
|
-
content: string;
|
|
35
|
-
conversationId?: string;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Execute an agent using Slack JWT authentication.
|
|
39
|
-
*
|
|
40
|
-
* This is the unified way to call agents from Slack - uses JWT, not API keys.
|
|
41
|
-
*/
|
|
42
|
-
declare function executeAgentWithSlackJwt(params: {
|
|
43
|
-
jwt: string;
|
|
44
|
-
projectId: string;
|
|
45
|
-
agentId: string;
|
|
46
|
-
message: string;
|
|
47
|
-
options?: ChatCompletionOptions;
|
|
48
|
-
}): Promise<ChatCompletionResult>;
|
|
49
|
-
/**
|
|
50
|
-
* Stream agent response with Slack JWT authentication.
|
|
51
|
-
*
|
|
52
|
-
* Returns a readable stream of SSE events for real-time streaming to Slack.
|
|
53
|
-
*/
|
|
54
|
-
declare function streamAgentWithSlackJwt(params: {
|
|
55
|
-
jwt: string;
|
|
56
|
-
projectId: string;
|
|
57
|
-
agentId: string;
|
|
58
|
-
message: string;
|
|
59
|
-
}): Promise<Response>;
|
|
60
|
-
//#endregion
|
|
61
|
-
export { ChatCompletionOptions, ChatCompletionResult, type SlackAccessTokenPayload, SlackJwtAuthError, SlackJwtResult, SlackUserContext, executeAgentWithSlackJwt, getSlackUserJwt, streamAgentWithSlackJwt, verifySlackJwt };
|