@inkeep/agents-work-apps 0.51.0 → 0.53.0
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.d.ts +2 -2
- package/dist/github/mcp/index.js +120 -25
- package/dist/github/mcp/utils.d.ts +11 -1
- package/dist/github/mcp/utils.js +102 -1
- package/dist/slack/dispatcher.js +10 -1
- package/dist/slack/routes/events.js +2 -2
- package/dist/slack/routes/oauth.js +23 -4
- package/dist/slack/routes/users.js +2 -2
- package/dist/slack/services/agent-resolution.js +66 -18
- package/dist/slack/services/blocks/index.d.ts +35 -1
- package/dist/slack/services/blocks/index.js +161 -22
- package/dist/slack/services/commands/index.js +2 -2
- package/dist/slack/services/events/app-mention.js +1 -1
- package/dist/slack/services/events/block-actions.js +1 -1
- package/dist/slack/services/events/modal-submission.js +14 -7
- package/dist/slack/services/events/streaming.js +133 -8
- package/dist/slack/services/events/utils.d.ts +5 -3
- package/dist/slack/services/events/utils.js +5 -5
- package/dist/slack/services/index.d.ts +2 -2
- package/dist/slack/services/index.js +3 -3
- package/dist/slack/services/modals.d.ts +1 -0
- package/dist/slack/services/modals.js +6 -4
- package/dist/slack/services/nango.js +1 -23
- package/dist/slack/tracer.d.ts +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getLogger } from "../../logger.js";
|
|
2
2
|
import runDbClient_default from "../../db/runDbClient.js";
|
|
3
3
|
import { getWorkspaceDefaultAgentFromNango } from "./nango.js";
|
|
4
|
+
import { fetchAgentsForProject } from "./events/utils.js";
|
|
4
5
|
import { findWorkAppSlackChannelAgentConfig } from "@inkeep/agents-core";
|
|
5
6
|
|
|
6
7
|
//#region src/slack/services/agent-resolution.ts
|
|
@@ -11,6 +12,35 @@ import { findWorkAppSlackChannelAgentConfig } from "@inkeep/agents-core";
|
|
|
11
12
|
* Priority: Channel default > Workspace default (all admin-controlled)
|
|
12
13
|
*/
|
|
13
14
|
const logger = getLogger("slack-agent-resolution");
|
|
15
|
+
const AGENT_NAME_CACHE_TTL_MS = 300 * 1e3;
|
|
16
|
+
const AGENT_NAME_CACHE_MAX_SIZE = 500;
|
|
17
|
+
const agentNameCache = /* @__PURE__ */ new Map();
|
|
18
|
+
async function lookupAgentName(tenantId, projectId, agentId) {
|
|
19
|
+
const cacheKey = `${tenantId}:${projectId}:${agentId}`;
|
|
20
|
+
const cached = agentNameCache.get(cacheKey);
|
|
21
|
+
if (cached && cached.expiresAt > Date.now()) return cached.name || void 0;
|
|
22
|
+
const agents = await fetchAgentsForProject(tenantId, projectId);
|
|
23
|
+
for (const agent of agents) {
|
|
24
|
+
const key = `${tenantId}:${projectId}:${agent.id}`;
|
|
25
|
+
agentNameCache.set(key, {
|
|
26
|
+
name: agent.name || null,
|
|
27
|
+
expiresAt: Date.now() + AGENT_NAME_CACHE_TTL_MS
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (agentNameCache.size > AGENT_NAME_CACHE_MAX_SIZE) {
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
for (const [key, entry] of agentNameCache) if (entry.expiresAt <= now) agentNameCache.delete(key);
|
|
33
|
+
if (agentNameCache.size > AGENT_NAME_CACHE_MAX_SIZE) {
|
|
34
|
+
const excess = agentNameCache.size - AGENT_NAME_CACHE_MAX_SIZE;
|
|
35
|
+
const keys = agentNameCache.keys();
|
|
36
|
+
for (let i = 0; i < excess; i++) {
|
|
37
|
+
const { value } = keys.next();
|
|
38
|
+
if (value) agentNameCache.delete(value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return agents.find((a) => a.id === agentId)?.name || void 0;
|
|
43
|
+
}
|
|
14
44
|
/**
|
|
15
45
|
* Resolve the effective agent configuration.
|
|
16
46
|
* Priority: Channel default > Workspace default
|
|
@@ -25,6 +55,7 @@ async function resolveEffectiveAgent(params) {
|
|
|
25
55
|
teamId,
|
|
26
56
|
channelId
|
|
27
57
|
}, "Resolving effective agent");
|
|
58
|
+
let result = null;
|
|
28
59
|
if (channelId) {
|
|
29
60
|
const channelConfig = await findWorkAppSlackChannelAgentConfig(runDbClient_default)(tenantId, teamId, channelId);
|
|
30
61
|
if (channelConfig?.enabled) {
|
|
@@ -33,7 +64,7 @@ async function resolveEffectiveAgent(params) {
|
|
|
33
64
|
agentId: channelConfig.agentId,
|
|
34
65
|
source: "channel"
|
|
35
66
|
}, "Resolved agent from channel config");
|
|
36
|
-
|
|
67
|
+
result = {
|
|
37
68
|
projectId: channelConfig.projectId,
|
|
38
69
|
agentId: channelConfig.agentId,
|
|
39
70
|
agentName: channelConfig.agentName || void 0,
|
|
@@ -42,27 +73,39 @@ async function resolveEffectiveAgent(params) {
|
|
|
42
73
|
};
|
|
43
74
|
}
|
|
44
75
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
76
|
+
if (!result) {
|
|
77
|
+
const workspaceConfig = await getWorkspaceDefaultAgentFromNango(teamId);
|
|
78
|
+
if (workspaceConfig?.agentId && workspaceConfig.projectId) {
|
|
79
|
+
logger.info({
|
|
80
|
+
teamId,
|
|
81
|
+
agentId: workspaceConfig.agentId,
|
|
82
|
+
source: "workspace"
|
|
83
|
+
}, "Resolved agent from workspace config");
|
|
84
|
+
result = {
|
|
85
|
+
projectId: workspaceConfig.projectId,
|
|
86
|
+
agentId: workspaceConfig.agentId,
|
|
87
|
+
agentName: workspaceConfig.agentName,
|
|
88
|
+
source: "workspace",
|
|
89
|
+
grantAccessToMembers: workspaceConfig.grantAccessToMembers ?? true
|
|
90
|
+
};
|
|
91
|
+
}
|
|
59
92
|
}
|
|
60
|
-
|
|
93
|
+
if (result && (!result.agentName || result.agentName === result.agentId)) {
|
|
94
|
+
const name = await lookupAgentName(tenantId, result.projectId, result.agentId);
|
|
95
|
+
if (name) {
|
|
96
|
+
result.agentName = name;
|
|
97
|
+
logger.debug({
|
|
98
|
+
agentId: result.agentId,
|
|
99
|
+
agentName: name
|
|
100
|
+
}, "Enriched agent config with name from manage API");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!result) logger.debug({
|
|
61
104
|
tenantId,
|
|
62
105
|
teamId,
|
|
63
106
|
channelId
|
|
64
107
|
}, "No agent configuration found");
|
|
65
|
-
return
|
|
108
|
+
return result;
|
|
66
109
|
}
|
|
67
110
|
/**
|
|
68
111
|
* Get all agent configuration sources for display purposes.
|
|
@@ -92,10 +135,15 @@ async function getAgentConfigSources(params) {
|
|
|
92
135
|
source: "workspace",
|
|
93
136
|
grantAccessToMembers: wsConfig.grantAccessToMembers ?? true
|
|
94
137
|
};
|
|
138
|
+
const effective = channelConfig || workspaceConfig;
|
|
139
|
+
if (effective && (!effective.agentName || effective.agentName === effective.agentId)) {
|
|
140
|
+
const name = await lookupAgentName(tenantId, effective.projectId, effective.agentId);
|
|
141
|
+
if (name) effective.agentName = name;
|
|
142
|
+
}
|
|
95
143
|
return {
|
|
96
144
|
channelConfig,
|
|
97
145
|
workspaceConfig,
|
|
98
|
-
effective
|
|
146
|
+
effective
|
|
99
147
|
};
|
|
100
148
|
}
|
|
101
149
|
|
|
@@ -17,6 +17,7 @@ declare function createContextBlock(params: ContextBlockParams): {
|
|
|
17
17
|
interface FollowUpButtonParams {
|
|
18
18
|
conversationId: string;
|
|
19
19
|
agentId: string;
|
|
20
|
+
agentName?: string;
|
|
20
21
|
projectId: string;
|
|
21
22
|
tenantId: string;
|
|
22
23
|
teamId: string;
|
|
@@ -109,7 +110,40 @@ declare function buildToolApprovalExpiredBlocks(params: {
|
|
|
109
110
|
text: string;
|
|
110
111
|
}[];
|
|
111
112
|
}[];
|
|
113
|
+
declare function buildToolOutputErrorBlock(toolName: string, errorText: string): {
|
|
114
|
+
type: "context";
|
|
115
|
+
elements: {
|
|
116
|
+
type: "mrkdwn";
|
|
117
|
+
text: string;
|
|
118
|
+
}[];
|
|
119
|
+
};
|
|
120
|
+
declare function buildSummaryBreadcrumbBlock(labels: string[]): {
|
|
121
|
+
type: "context";
|
|
122
|
+
elements: {
|
|
123
|
+
type: "mrkdwn";
|
|
124
|
+
text: string;
|
|
125
|
+
}[];
|
|
126
|
+
};
|
|
127
|
+
declare function buildDataComponentBlocks(component: {
|
|
128
|
+
id: string;
|
|
129
|
+
data: Record<string, unknown>;
|
|
130
|
+
}): {
|
|
131
|
+
blocks: any[];
|
|
132
|
+
overflowJson?: string;
|
|
133
|
+
componentType?: string;
|
|
134
|
+
};
|
|
135
|
+
declare function buildDataArtifactBlocks(artifact: {
|
|
136
|
+
data: Record<string, unknown>;
|
|
137
|
+
}): {
|
|
138
|
+
blocks: any[];
|
|
139
|
+
overflowContent?: string;
|
|
140
|
+
artifactName?: string;
|
|
141
|
+
};
|
|
142
|
+
declare function buildCitationsBlock(citations: Array<{
|
|
143
|
+
title?: string;
|
|
144
|
+
url?: string;
|
|
145
|
+
}>): any[];
|
|
112
146
|
declare function createJwtLinkMessage(linkUrl: string, expiresInMinutes: number): Readonly<slack_block_builder0.SlackMessageDto>;
|
|
113
147
|
declare function createCreateInkeepAccountMessage(acceptUrl: string, expiresInMinutes: number): Readonly<slack_block_builder0.SlackMessageDto>;
|
|
114
148
|
//#endregion
|
|
115
|
-
export { AgentConfigSources, ContextBlockParams, FollowUpButtonParams, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, buildConversationResponseBlocks, buildFollowUpButton, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage };
|
|
149
|
+
export { AgentConfigSources, ContextBlockParams, FollowUpButtonParams, ToolApprovalButtonValue, ToolApprovalButtonValueSchema, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage };
|
|
@@ -44,10 +44,7 @@ function buildConversationResponseBlocks(params) {
|
|
|
44
44
|
}
|
|
45
45
|
}];
|
|
46
46
|
if (!isError) {
|
|
47
|
-
const contextBlock = createContextBlock({
|
|
48
|
-
agentName,
|
|
49
|
-
isPrivate: true
|
|
50
|
-
});
|
|
47
|
+
const contextBlock = createContextBlock({ agentName });
|
|
51
48
|
blocks.push(contextBlock);
|
|
52
49
|
blocks.push({
|
|
53
50
|
type: "actions",
|
|
@@ -88,31 +85,25 @@ const ToolApprovalButtonValueSchema = z.object({
|
|
|
88
85
|
function buildToolApprovalBlocks(params) {
|
|
89
86
|
const { toolName, input, buttonValue } = params;
|
|
90
87
|
const blocks = [{
|
|
91
|
-
type: "header",
|
|
92
|
-
text: {
|
|
93
|
-
type: "plain_text",
|
|
94
|
-
text: "Tool Approval Required",
|
|
95
|
-
emoji: false
|
|
96
|
-
}
|
|
97
|
-
}, {
|
|
98
88
|
type: "section",
|
|
99
89
|
text: {
|
|
100
90
|
type: "mrkdwn",
|
|
101
|
-
text:
|
|
91
|
+
text: `*Approval required - \`${toolName}\`*`
|
|
102
92
|
}
|
|
103
93
|
}];
|
|
104
94
|
if (input && Object.keys(input).length > 0) {
|
|
105
|
-
const
|
|
106
|
-
|
|
95
|
+
const fields = Object.entries(input).slice(0, 10).map(([k, v]) => {
|
|
96
|
+
const val = typeof v === "object" ? JSON.stringify(v) : String(v ?? "");
|
|
97
|
+
return {
|
|
98
|
+
type: "mrkdwn",
|
|
99
|
+
text: `*${k}:*\n${val.length > 80 ? `${val.slice(0, 80)}…` : val}`
|
|
100
|
+
};
|
|
101
|
+
});
|
|
107
102
|
blocks.push({
|
|
108
103
|
type: "section",
|
|
109
|
-
|
|
110
|
-
type: "mrkdwn",
|
|
111
|
-
text: `\`\`\`json\n${truncated}\n\`\`\``
|
|
112
|
-
}
|
|
104
|
+
fields
|
|
113
105
|
});
|
|
114
106
|
}
|
|
115
|
-
blocks.push({ type: "divider" });
|
|
116
107
|
blocks.push({
|
|
117
108
|
type: "actions",
|
|
118
109
|
elements: [{
|
|
@@ -120,7 +111,7 @@ function buildToolApprovalBlocks(params) {
|
|
|
120
111
|
text: {
|
|
121
112
|
type: "plain_text",
|
|
122
113
|
text: "Approve",
|
|
123
|
-
emoji:
|
|
114
|
+
emoji: true
|
|
124
115
|
},
|
|
125
116
|
style: "primary",
|
|
126
117
|
action_id: "tool_approval_approve",
|
|
@@ -130,7 +121,7 @@ function buildToolApprovalBlocks(params) {
|
|
|
130
121
|
text: {
|
|
131
122
|
type: "plain_text",
|
|
132
123
|
text: "Deny",
|
|
133
|
-
emoji:
|
|
124
|
+
emoji: true
|
|
134
125
|
},
|
|
135
126
|
style: "danger",
|
|
136
127
|
action_id: "tool_approval_deny",
|
|
@@ -158,6 +149,154 @@ function buildToolApprovalExpiredBlocks(params) {
|
|
|
158
149
|
}]
|
|
159
150
|
}];
|
|
160
151
|
}
|
|
152
|
+
function buildToolOutputErrorBlock(toolName, errorText) {
|
|
153
|
+
return {
|
|
154
|
+
type: "context",
|
|
155
|
+
elements: [{
|
|
156
|
+
type: "mrkdwn",
|
|
157
|
+
text: `⚠️ *${toolName}* · failed: ${errorText.length > 100 ? `${errorText.slice(0, 100)}…` : errorText}`
|
|
158
|
+
}]
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function buildSummaryBreadcrumbBlock(labels) {
|
|
162
|
+
return {
|
|
163
|
+
type: "context",
|
|
164
|
+
elements: [{
|
|
165
|
+
type: "mrkdwn",
|
|
166
|
+
text: labels.join(" → ")
|
|
167
|
+
}]
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function isFlatRecord(obj) {
|
|
171
|
+
return Object.values(obj).every((v) => v === null || [
|
|
172
|
+
"string",
|
|
173
|
+
"number",
|
|
174
|
+
"boolean"
|
|
175
|
+
].includes(typeof v));
|
|
176
|
+
}
|
|
177
|
+
function findSourcesArray(data) {
|
|
178
|
+
for (const value of Object.values(data)) if (Array.isArray(value) && value.length > 0 && typeof value[0] === "object" && value[0] !== null && ("url" in value[0] || "href" in value[0])) return value;
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
function buildDataComponentBlocks(component) {
|
|
182
|
+
const { data } = component;
|
|
183
|
+
const componentType = typeof data.type === "string" ? data.type : void 0;
|
|
184
|
+
const blocks = [{
|
|
185
|
+
type: "header",
|
|
186
|
+
text: {
|
|
187
|
+
type: "plain_text",
|
|
188
|
+
text: `📊 ${componentType || "Data Component"}`,
|
|
189
|
+
emoji: true
|
|
190
|
+
}
|
|
191
|
+
}];
|
|
192
|
+
const payload = Object.fromEntries(Object.entries(data).filter(([k]) => k !== "type"));
|
|
193
|
+
let overflowJson;
|
|
194
|
+
if (Object.keys(payload).length > 0) if (isFlatRecord(payload)) {
|
|
195
|
+
const fields = Object.entries(payload).slice(0, 10).map(([k, v]) => {
|
|
196
|
+
const val = String(v ?? "");
|
|
197
|
+
return {
|
|
198
|
+
type: "mrkdwn",
|
|
199
|
+
text: `*${k}*\n${val.length > 80 ? `${val.slice(0, 80)}…` : val}`
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
blocks.push({
|
|
203
|
+
type: "section",
|
|
204
|
+
fields
|
|
205
|
+
});
|
|
206
|
+
} else {
|
|
207
|
+
const jsonStr = JSON.stringify(payload, null, 2);
|
|
208
|
+
if (jsonStr.length > 2900) overflowJson = jsonStr;
|
|
209
|
+
else blocks.push({
|
|
210
|
+
type: "section",
|
|
211
|
+
text: {
|
|
212
|
+
type: "mrkdwn",
|
|
213
|
+
text: `\`\`\`json\n${jsonStr}\n\`\`\``
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
if (componentType) blocks.push({
|
|
218
|
+
type: "context",
|
|
219
|
+
elements: [{
|
|
220
|
+
type: "mrkdwn",
|
|
221
|
+
text: `data component · type: ${componentType}`
|
|
222
|
+
}]
|
|
223
|
+
});
|
|
224
|
+
return {
|
|
225
|
+
blocks,
|
|
226
|
+
overflowJson,
|
|
227
|
+
componentType
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function buildDataArtifactBlocks(artifact) {
|
|
231
|
+
const { data } = artifact;
|
|
232
|
+
const sourcesArray = findSourcesArray(data);
|
|
233
|
+
if (sourcesArray && sourcesArray.length > 0) {
|
|
234
|
+
const MAX_SOURCES = 10;
|
|
235
|
+
const lines = sourcesArray.slice(0, MAX_SOURCES).map((s) => {
|
|
236
|
+
const url = s.url || s.href;
|
|
237
|
+
const title = s.title || s.name || url;
|
|
238
|
+
return url ? `• <${url}|${title}>` : null;
|
|
239
|
+
}).filter((l) => l !== null);
|
|
240
|
+
if (lines.length > 0) {
|
|
241
|
+
const suffix = sourcesArray.length > MAX_SOURCES ? `\n_and ${sourcesArray.length - MAX_SOURCES} more_` : "";
|
|
242
|
+
return { blocks: [{
|
|
243
|
+
type: "section",
|
|
244
|
+
text: {
|
|
245
|
+
type: "mrkdwn",
|
|
246
|
+
text: `📚 *Sources*\n${lines.join("\n")}${suffix}`
|
|
247
|
+
}
|
|
248
|
+
}] };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const artifactType = typeof data.type === "string" ? data.type : void 0;
|
|
252
|
+
const name = typeof data.name === "string" && data.name ? data.name : artifactType || "Artifact";
|
|
253
|
+
const blocks = [{
|
|
254
|
+
type: "header",
|
|
255
|
+
text: {
|
|
256
|
+
type: "plain_text",
|
|
257
|
+
text: `📄 ${name}`,
|
|
258
|
+
emoji: true
|
|
259
|
+
}
|
|
260
|
+
}];
|
|
261
|
+
if (artifactType) blocks.push({
|
|
262
|
+
type: "context",
|
|
263
|
+
elements: [{
|
|
264
|
+
type: "mrkdwn",
|
|
265
|
+
text: `type: ${artifactType}`
|
|
266
|
+
}]
|
|
267
|
+
});
|
|
268
|
+
let overflowContent;
|
|
269
|
+
if (typeof data.description === "string" && data.description) if (data.description.length > 2900) overflowContent = data.description;
|
|
270
|
+
else blocks.push({
|
|
271
|
+
type: "section",
|
|
272
|
+
text: {
|
|
273
|
+
type: "mrkdwn",
|
|
274
|
+
text: data.description
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
return {
|
|
278
|
+
blocks,
|
|
279
|
+
overflowContent,
|
|
280
|
+
artifactName: name
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function buildCitationsBlock(citations) {
|
|
284
|
+
const MAX_CITATIONS = 10;
|
|
285
|
+
const lines = citations.slice(0, MAX_CITATIONS).map((c) => {
|
|
286
|
+
const url = c.url;
|
|
287
|
+
const title = c.title || url;
|
|
288
|
+
return url ? `• <${url}|${title}>` : null;
|
|
289
|
+
}).filter((l) => l !== null);
|
|
290
|
+
if (lines.length === 0) return [];
|
|
291
|
+
const suffix = citations.length > MAX_CITATIONS ? `\n_and ${citations.length - MAX_CITATIONS} more_` : "";
|
|
292
|
+
return [{
|
|
293
|
+
type: "section",
|
|
294
|
+
text: {
|
|
295
|
+
type: "mrkdwn",
|
|
296
|
+
text: `📚 *Sources*\n${lines.join("\n")}${suffix}`
|
|
297
|
+
}
|
|
298
|
+
}];
|
|
299
|
+
}
|
|
161
300
|
function createJwtLinkMessage(linkUrl, expiresInMinutes) {
|
|
162
301
|
return Message().blocks(Blocks.Section().text(`${Md.bold("Link your Inkeep account")}\n\nConnect your Slack and Inkeep accounts to use Inkeep agents.`), Blocks.Actions().elements(Elements.Button().text("Link Account").url(linkUrl).actionId("link_account").primary()), Blocks.Context().elements(`This link expires in ${expiresInMinutes} minutes.`)).buildToObject();
|
|
163
302
|
}
|
|
@@ -166,4 +305,4 @@ function createCreateInkeepAccountMessage(acceptUrl, expiresInMinutes) {
|
|
|
166
305
|
}
|
|
167
306
|
|
|
168
307
|
//#endregion
|
|
169
|
-
export { ToolApprovalButtonValueSchema, buildConversationResponseBlocks, buildFollowUpButton, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage };
|
|
308
|
+
export { ToolApprovalButtonValueSchema, buildCitationsBlock, buildConversationResponseBlocks, buildDataArtifactBlocks, buildDataComponentBlocks, buildFollowUpButton, buildSummaryBreadcrumbBlock, buildToolApprovalBlocks, buildToolApprovalDoneBlocks, buildToolApprovalExpiredBlocks, buildToolOutputErrorBlock, createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage };
|
|
@@ -2,11 +2,11 @@ import { env } from "../../../env.js";
|
|
|
2
2
|
import { getLogger } from "../../../logger.js";
|
|
3
3
|
import runDbClient_default from "../../../db/runDbClient.js";
|
|
4
4
|
import { findWorkspaceConnectionByTeamId } from "../nango.js";
|
|
5
|
+
import { extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, getChannelAgentConfig, sendResponseUrlMessage } from "../events/utils.js";
|
|
5
6
|
import { resolveEffectiveAgent } from "../agent-resolution.js";
|
|
6
7
|
import { SlackStrings } from "../../i18n/strings.js";
|
|
7
8
|
import { createAlreadyLinkedMessage, createContextBlock, createCreateInkeepAccountMessage, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage } from "../blocks/index.js";
|
|
8
9
|
import { getSlackClient } from "../client.js";
|
|
9
|
-
import { extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, getChannelAgentConfig, sendResponseUrlMessage } from "../events/utils.js";
|
|
10
10
|
import { buildAgentSelectorModal } from "../modals.js";
|
|
11
11
|
import { createInvitationInDb, deleteWorkAppSlackUserMapping, findWorkAppSlackUserMapping, findWorkAppSlackUserMappingBySlackUser, findWorkAppSlackWorkspaceByTeamId, flushTraces, getInProcessFetch, getOrganizationMemberByEmail, getPendingInvitationsByEmail, getWaitUntil, signSlackLinkToken, signSlackUserToken } from "@inkeep/agents-core";
|
|
12
12
|
|
|
@@ -412,7 +412,7 @@ async function executeAgentInBackground(payload, existingLink, targetAgent, ques
|
|
|
412
412
|
}, "Agent execution completed via Slack");
|
|
413
413
|
const contextBlock = createContextBlock({ agentName: targetAgent.name || targetAgent.id });
|
|
414
414
|
await sendResponseUrlMessage(payload.responseUrl, {
|
|
415
|
-
response_type: "
|
|
415
|
+
response_type: "in_channel",
|
|
416
416
|
text: assistantMessage,
|
|
417
417
|
blocks: [{
|
|
418
418
|
type: "section",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { env } from "../../../env.js";
|
|
2
2
|
import { getLogger } from "../../../logger.js";
|
|
3
3
|
import { findWorkspaceConnectionByTeamId } from "../nango.js";
|
|
4
|
+
import { checkIfBotThread, classifyError, findCachedUserMapping, formatChannelContext, generateSlackConversationId, getThreadContext, getUserFriendlyErrorMessage, timedOp } from "./utils.js";
|
|
4
5
|
import { resolveEffectiveAgent } from "../agent-resolution.js";
|
|
5
6
|
import { SlackStrings } from "../../i18n/strings.js";
|
|
6
7
|
import { getSlackChannelInfo, getSlackClient, getSlackUserInfo, postMessageInThread } from "../client.js";
|
|
7
|
-
import { checkIfBotThread, classifyError, findCachedUserMapping, formatChannelContext, generateSlackConversationId, getThreadContext, getUserFriendlyErrorMessage, timedOp } from "./utils.js";
|
|
8
8
|
import { SLACK_SPAN_KEYS, SLACK_SPAN_NAMES, setSpanWithError, tracer } from "../../tracer.js";
|
|
9
9
|
import { streamAgentResponse } from "./streaming.js";
|
|
10
10
|
import { signSlackUserToken } from "@inkeep/agents-core";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { env } from "../../../env.js";
|
|
2
2
|
import { getLogger } from "../../../logger.js";
|
|
3
3
|
import { findWorkspaceConnectionByTeamId } from "../nango.js";
|
|
4
|
+
import { fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, getChannelAgentConfig, sendResponseUrlMessage } from "./utils.js";
|
|
4
5
|
import { SlackStrings } from "../../i18n/strings.js";
|
|
5
6
|
import { ToolApprovalButtonValueSchema, buildToolApprovalDoneBlocks } from "../blocks/index.js";
|
|
6
7
|
import { getSlackClient } from "../client.js";
|
|
7
|
-
import { fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, getChannelAgentConfig, sendResponseUrlMessage } from "./utils.js";
|
|
8
8
|
import { buildAgentSelectorModal, buildFollowUpModal, buildMessageShortcutModal } from "../modals.js";
|
|
9
9
|
import { SLACK_SPAN_KEYS, SLACK_SPAN_NAMES, setSpanWithError, tracer } from "../../tracer.js";
|
|
10
10
|
import { getInProcessFetch, signSlackUserToken } from "@inkeep/agents-core";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { env } from "../../../env.js";
|
|
2
2
|
import { getLogger } from "../../../logger.js";
|
|
3
3
|
import { findWorkspaceConnectionByTeamId } from "../nango.js";
|
|
4
|
+
import { classifyError, extractApiErrorMessage, findCachedUserMapping, generateSlackConversationId, getThreadContext, getUserFriendlyErrorMessage, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
|
|
4
5
|
import { SlackStrings } from "../../i18n/strings.js";
|
|
5
6
|
import { buildConversationResponseBlocks } from "../blocks/index.js";
|
|
6
7
|
import { getSlackClient } from "../client.js";
|
|
7
|
-
import { classifyError, extractApiErrorMessage, findCachedUserMapping, generateSlackConversationId, getThreadContext, getUserFriendlyErrorMessage, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
|
|
8
8
|
import { SLACK_SPAN_KEYS, SLACK_SPAN_NAMES, setSpanWithError, tracer } from "../../tracer.js";
|
|
9
9
|
import { getInProcessFetch, signSlackUserToken } from "@inkeep/agents-core";
|
|
10
10
|
|
|
@@ -36,13 +36,16 @@ async function handleModalSubmission(view) {
|
|
|
36
36
|
const includeContext = includeContextValue?.selected_options?.some((o) => o.value === "include_context") ?? true;
|
|
37
37
|
let agentId = metadata.selectedAgentId;
|
|
38
38
|
let projectId = metadata.selectedProjectId;
|
|
39
|
+
let agentName = null;
|
|
39
40
|
if (agentSelectValue?.selected_option?.value) try {
|
|
40
41
|
const parsed = JSON.parse(agentSelectValue.selected_option.value);
|
|
41
42
|
agentId = parsed.agentId;
|
|
42
43
|
projectId = parsed.projectId;
|
|
44
|
+
agentName = parsed.agentName || null;
|
|
43
45
|
} catch {
|
|
44
46
|
logger.warn({ value: agentSelectValue.selected_option.value }, "Failed to parse agent select value");
|
|
45
47
|
}
|
|
48
|
+
const agentDisplayName = agentName || agentId || "Agent";
|
|
46
49
|
if (!agentId || !projectId) {
|
|
47
50
|
logger.error({ metadata }, "Missing agent or project ID in modal submission");
|
|
48
51
|
if (metadata.buttonResponseUrl) await sendResponseUrlMessage(metadata.buttonResponseUrl, {
|
|
@@ -112,7 +115,7 @@ async function handleModalSubmission(view) {
|
|
|
112
115
|
});
|
|
113
116
|
span.setAttribute(SLACK_SPAN_KEYS.CONVERSATION_ID, conversationId);
|
|
114
117
|
const apiBaseUrl = env.INKEEP_AGENTS_API_URL || "http://localhost:3002";
|
|
115
|
-
const thinkingText = SlackStrings.status.thinking(
|
|
118
|
+
const thinkingText = SlackStrings.status.thinking(agentDisplayName);
|
|
116
119
|
if (metadata.buttonResponseUrl) await sendResponseUrlMessage(metadata.buttonResponseUrl, {
|
|
117
120
|
text: thinkingText,
|
|
118
121
|
response_type: "ephemeral",
|
|
@@ -139,6 +142,7 @@ async function handleModalSubmission(view) {
|
|
|
139
142
|
slackClient,
|
|
140
143
|
metadata,
|
|
141
144
|
agentId,
|
|
145
|
+
agentDisplayName,
|
|
142
146
|
projectId,
|
|
143
147
|
tenantId,
|
|
144
148
|
conversationId,
|
|
@@ -194,7 +198,8 @@ async function handleFollowUpSubmission(view) {
|
|
|
194
198
|
span.end();
|
|
195
199
|
return;
|
|
196
200
|
}
|
|
197
|
-
const { conversationId, agentId, projectId, tenantId, teamId, slackUserId, channel } = metadata;
|
|
201
|
+
const { conversationId, agentId, agentName, projectId, tenantId, teamId, slackUserId, channel } = metadata;
|
|
202
|
+
const agentDisplayName = agentName || agentId || "Agent";
|
|
198
203
|
span.setAttribute(SLACK_SPAN_KEYS.TEAM_ID, teamId);
|
|
199
204
|
span.setAttribute(SLACK_SPAN_KEYS.CHANNEL_ID, channel);
|
|
200
205
|
span.setAttribute(SLACK_SPAN_KEYS.USER_ID, slackUserId);
|
|
@@ -234,7 +239,7 @@ async function handleFollowUpSubmission(view) {
|
|
|
234
239
|
await slackClient.chat.postEphemeral({
|
|
235
240
|
channel,
|
|
236
241
|
user: slackUserId,
|
|
237
|
-
text: SlackStrings.status.thinking(
|
|
242
|
+
text: SlackStrings.status.thinking(agentDisplayName)
|
|
238
243
|
});
|
|
239
244
|
const responseText = await callAgentApi({
|
|
240
245
|
apiBaseUrl,
|
|
@@ -247,11 +252,12 @@ async function handleFollowUpSubmission(view) {
|
|
|
247
252
|
const responseBlocks = buildConversationResponseBlocks({
|
|
248
253
|
userMessage: question,
|
|
249
254
|
responseText: responseText.text,
|
|
250
|
-
agentName:
|
|
255
|
+
agentName: agentDisplayName,
|
|
251
256
|
isError: responseText.isError,
|
|
252
257
|
followUpParams: {
|
|
253
258
|
conversationId,
|
|
254
259
|
agentId,
|
|
260
|
+
agentName: agentDisplayName,
|
|
255
261
|
projectId,
|
|
256
262
|
tenantId,
|
|
257
263
|
teamId,
|
|
@@ -370,15 +376,16 @@ async function callAgentApi(params) {
|
|
|
370
376
|
});
|
|
371
377
|
}
|
|
372
378
|
async function postPrivateResponse(params) {
|
|
373
|
-
const { slackClient, metadata, agentId, projectId, tenantId, conversationId, userMessage, responseText, isError } = params;
|
|
379
|
+
const { slackClient, metadata, agentId, agentDisplayName, projectId, tenantId, conversationId, userMessage, responseText, isError } = params;
|
|
374
380
|
const responseBlocks = buildConversationResponseBlocks({
|
|
375
381
|
userMessage,
|
|
376
382
|
responseText,
|
|
377
|
-
agentName:
|
|
383
|
+
agentName: agentDisplayName,
|
|
378
384
|
isError,
|
|
379
385
|
followUpParams: {
|
|
380
386
|
conversationId,
|
|
381
387
|
agentId,
|
|
388
|
+
agentName: agentDisplayName,
|
|
382
389
|
projectId,
|
|
383
390
|
tenantId,
|
|
384
391
|
teamId: metadata.teamId,
|