@inkeep/agents-work-apps 0.0.0-dev-20260225215837 → 0.0.0-dev-20260225221013
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/routes/setup.d.ts +2 -2
- package/dist/github/routes/setup.js +1 -1
- package/dist/github/routes/tokenExchange.d.ts +2 -2
- package/dist/github/routes/tokenExchange.js +1 -1
- package/dist/github/routes/webhooks.d.ts +2 -2
- package/dist/github/routes/webhooks.js +1 -1
- package/dist/slack/services/blocks/index.js +20 -14
- package/dist/slack/services/events/streaming.js +8 -4
- package/dist/slack/services/events/utils.d.ts +15 -3
- package/dist/slack/services/events/utils.js +18 -2
- package/package.json +2 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types5 from "hono/types";
|
|
3
3
|
|
|
4
4
|
//#region src/github/mcp/index.d.ts
|
|
5
5
|
declare const app: Hono<{
|
|
6
6
|
Variables: {
|
|
7
7
|
toolId: string;
|
|
8
8
|
};
|
|
9
|
-
},
|
|
9
|
+
}, hono_types5.BlankSchema, "/">;
|
|
10
10
|
//#endregion
|
|
11
11
|
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/setup.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,7 +1,7 @@
|
|
|
1
1
|
import { env } from "../../env.js";
|
|
2
2
|
import { getLogger } from "../../logger.js";
|
|
3
|
-
import runDbClient_default from "../../db/runDbClient.js";
|
|
4
3
|
import { getStateSigningSecret, isStateSigningConfigured } from "../config.js";
|
|
4
|
+
import runDbClient_default from "../../db/runDbClient.js";
|
|
5
5
|
import { createAppJwt, determineStatus, fetchInstallationDetails, fetchInstallationRepositories } from "../installation.js";
|
|
6
6
|
import { createInstallation, generateId, getInstallationByGitHubId, listProjectsMetadata, setProjectAccessMode, syncRepositories, updateInstallationStatusByGitHubId } from "@inkeep/agents-core";
|
|
7
7
|
import { Hono } from "hono";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types6 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_types6.BlankEnv, hono_types6.BlankSchema, "/">;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { app as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getLogger } from "../../logger.js";
|
|
2
|
-
import runDbClient_default from "../../db/runDbClient.js";
|
|
3
2
|
import { isGitHubAppConfigured } from "../config.js";
|
|
3
|
+
import runDbClient_default from "../../db/runDbClient.js";
|
|
4
4
|
import { generateInstallationAccessToken, lookupInstallationForRepo } from "../installation.js";
|
|
5
5
|
import { validateOidcToken } from "../oidcToken.js";
|
|
6
6
|
import { checkProjectRepositoryAccess, getInstallationByGitHubId } from "@inkeep/agents-core";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import * as
|
|
2
|
+
import * as hono_types8 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_types8.BlankEnv, hono_types8.BlankSchema, "/">;
|
|
11
11
|
//#endregion
|
|
12
12
|
export { WebhookVerificationResult, app as default, verifyWebhookSignature };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getLogger } from "../../logger.js";
|
|
2
|
-
import runDbClient_default from "../../db/runDbClient.js";
|
|
3
2
|
import { getWebhookSecret, isWebhookConfigured } from "../config.js";
|
|
3
|
+
import runDbClient_default from "../../db/runDbClient.js";
|
|
4
4
|
import { addRepositories, deleteInstallation, getInstallationByGitHubId, removeRepositories, updateInstallationStatusByGitHubId } from "@inkeep/agents-core";
|
|
5
5
|
import { Hono } from "hono";
|
|
6
6
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { escapeSlackLinkText, escapeSlackMrkdwn } from "../events/utils.js";
|
|
1
2
|
import { SlackStrings } from "../../i18n/strings.js";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
import { Blocks, Elements, Md, Message } from "slack-block-builder";
|
|
@@ -12,7 +13,7 @@ function createContextBlock(params) {
|
|
|
12
13
|
type: "context",
|
|
13
14
|
elements: [{
|
|
14
15
|
type: "mrkdwn",
|
|
15
|
-
text: SlackStrings.context.poweredBy(agentName)
|
|
16
|
+
text: SlackStrings.context.poweredBy(escapeSlackMrkdwn(agentName))
|
|
16
17
|
}]
|
|
17
18
|
};
|
|
18
19
|
}
|
|
@@ -73,15 +74,16 @@ function buildToolApprovalBlocks(params) {
|
|
|
73
74
|
type: "section",
|
|
74
75
|
text: {
|
|
75
76
|
type: "mrkdwn",
|
|
76
|
-
text: `*Approval required - \`${toolName}\`*`
|
|
77
|
+
text: `*Approval required - \`${escapeSlackMrkdwn(toolName)}\`*`
|
|
77
78
|
}
|
|
78
79
|
}];
|
|
79
80
|
if (input && Object.keys(input).length > 0) {
|
|
80
81
|
const fields = Object.entries(input).slice(0, 10).map(([k, v]) => {
|
|
81
82
|
const val = typeof v === "object" ? JSON.stringify(v) : String(v ?? "");
|
|
83
|
+
const truncated = val.length > 80 ? `${val.slice(0, 80)}…` : val;
|
|
82
84
|
return {
|
|
83
85
|
type: "mrkdwn",
|
|
84
|
-
text: `*${k}:*\n${
|
|
86
|
+
text: `*${escapeSlackMrkdwn(k)}:*\n${escapeSlackMrkdwn(truncated)}`
|
|
85
87
|
};
|
|
86
88
|
});
|
|
87
89
|
blocks.push({
|
|
@@ -121,7 +123,7 @@ function buildToolApprovalDoneBlocks(params) {
|
|
|
121
123
|
type: "context",
|
|
122
124
|
elements: [{
|
|
123
125
|
type: "mrkdwn",
|
|
124
|
-
text: approved ? `✅ Approved \`${toolName}\` · <@${actorUserId}>` : `❌ Denied \`${toolName}\` · <@${actorUserId}>`
|
|
126
|
+
text: approved ? `✅ Approved \`${escapeSlackMrkdwn(toolName)}\` · <@${actorUserId}>` : `❌ Denied \`${escapeSlackMrkdwn(toolName)}\` · <@${actorUserId}>`
|
|
125
127
|
}]
|
|
126
128
|
}];
|
|
127
129
|
}
|
|
@@ -130,16 +132,17 @@ function buildToolApprovalExpiredBlocks(params) {
|
|
|
130
132
|
type: "context",
|
|
131
133
|
elements: [{
|
|
132
134
|
type: "mrkdwn",
|
|
133
|
-
text: `⏱️ Expired · \`${params.toolName}\``
|
|
135
|
+
text: `⏱️ Expired · \`${escapeSlackMrkdwn(params.toolName)}\``
|
|
134
136
|
}]
|
|
135
137
|
}];
|
|
136
138
|
}
|
|
137
139
|
function buildToolOutputErrorBlock(toolName, errorText) {
|
|
140
|
+
const truncated = errorText.length > 100 ? `${errorText.slice(0, 100)}…` : errorText;
|
|
138
141
|
return {
|
|
139
142
|
type: "context",
|
|
140
143
|
elements: [{
|
|
141
144
|
type: "mrkdwn",
|
|
142
|
-
text: `⚠️ *${toolName}* · failed: ${
|
|
145
|
+
text: `⚠️ *${escapeSlackMrkdwn(toolName)}* · failed: ${escapeSlackMrkdwn(truncated)}`
|
|
143
146
|
}]
|
|
144
147
|
};
|
|
145
148
|
}
|
|
@@ -148,7 +151,7 @@ function buildSummaryBreadcrumbBlock(labels) {
|
|
|
148
151
|
type: "context",
|
|
149
152
|
elements: [{
|
|
150
153
|
type: "mrkdwn",
|
|
151
|
-
text: labels.join(" → ")
|
|
154
|
+
text: labels.map(escapeSlackMrkdwn).join(" → ")
|
|
152
155
|
}]
|
|
153
156
|
};
|
|
154
157
|
}
|
|
@@ -179,9 +182,10 @@ function buildDataComponentBlocks(component) {
|
|
|
179
182
|
if (Object.keys(payload).length > 0) if (isFlatRecord(payload)) {
|
|
180
183
|
const fields = Object.entries(payload).slice(0, 10).map(([k, v]) => {
|
|
181
184
|
const val = String(v ?? "");
|
|
185
|
+
const truncated = val.length > 80 ? `${val.slice(0, 80)}…` : val;
|
|
182
186
|
return {
|
|
183
187
|
type: "mrkdwn",
|
|
184
|
-
text: `*${k}*\n${
|
|
188
|
+
text: `*${escapeSlackMrkdwn(k)}*\n${escapeSlackMrkdwn(truncated)}`
|
|
185
189
|
};
|
|
186
190
|
});
|
|
187
191
|
blocks.push({
|
|
@@ -203,7 +207,7 @@ function buildDataComponentBlocks(component) {
|
|
|
203
207
|
type: "context",
|
|
204
208
|
elements: [{
|
|
205
209
|
type: "mrkdwn",
|
|
206
|
-
text: `data component · type: ${componentType}`
|
|
210
|
+
text: `data component · type: ${escapeSlackMrkdwn(componentType)}`
|
|
207
211
|
}]
|
|
208
212
|
});
|
|
209
213
|
return {
|
|
@@ -219,7 +223,8 @@ function buildDataArtifactBlocks(artifact) {
|
|
|
219
223
|
const MAX_SOURCES = 10;
|
|
220
224
|
const lines = sourcesArray.slice(0, MAX_SOURCES).map((s) => {
|
|
221
225
|
const url = s.url || s.href;
|
|
222
|
-
const
|
|
226
|
+
const rawTitle = s.title || s.name || url;
|
|
227
|
+
const title = rawTitle ? escapeSlackLinkText(rawTitle) : rawTitle;
|
|
223
228
|
return url ? `• <${url}|${title}>` : null;
|
|
224
229
|
}).filter((l) => l !== null);
|
|
225
230
|
if (lines.length > 0) {
|
|
@@ -247,7 +252,7 @@ function buildDataArtifactBlocks(artifact) {
|
|
|
247
252
|
type: "context",
|
|
248
253
|
elements: [{
|
|
249
254
|
type: "mrkdwn",
|
|
250
|
-
text: `type: ${artifactType}`
|
|
255
|
+
text: `type: ${escapeSlackMrkdwn(artifactType)}`
|
|
251
256
|
}]
|
|
252
257
|
});
|
|
253
258
|
let overflowContent;
|
|
@@ -267,10 +272,11 @@ function buildDataArtifactBlocks(artifact) {
|
|
|
267
272
|
}
|
|
268
273
|
function buildCitationsBlock(citations) {
|
|
269
274
|
const MAX_CITATIONS = 10;
|
|
270
|
-
const lines = citations.slice(0, MAX_CITATIONS).map((c) => {
|
|
275
|
+
const lines = citations.slice(0, MAX_CITATIONS).map((c, i) => {
|
|
271
276
|
const url = c.url;
|
|
272
|
-
const
|
|
273
|
-
|
|
277
|
+
const rawTitle = c.title || url;
|
|
278
|
+
const title = rawTitle ? escapeSlackLinkText(rawTitle) : rawTitle;
|
|
279
|
+
return url ? `<${url}|[${i + 1}] ${title}>` : null;
|
|
274
280
|
}).filter((l) => l !== null);
|
|
275
281
|
if (lines.length === 0) return [];
|
|
276
282
|
const suffix = citations.length > MAX_CITATIONS ? `\n_and ${citations.length - MAX_CITATIONS} more_` : "";
|
|
@@ -349,10 +349,14 @@ async function streamAgentResponse(params) {
|
|
|
349
349
|
const artifactData = data.data;
|
|
350
350
|
if (typeof artifactData.type === "string" && artifactData.type.toLowerCase() === "citation") {
|
|
351
351
|
const summary = artifactData.artifactSummary;
|
|
352
|
-
if (summary?.url && !citations.some((c) => c.url === summary.url))
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
352
|
+
if (summary?.url && !citations.some((c) => c.url === summary.url)) {
|
|
353
|
+
citations.push({
|
|
354
|
+
title: summary.title,
|
|
355
|
+
url: summary.url
|
|
356
|
+
});
|
|
357
|
+
const citationIndex = citations.length;
|
|
358
|
+
if (fullText.length > 0) await withTimeout(streamer.append({ markdown_text: `<${summary.url}|[${citationIndex}]>` }), CHATSTREAM_OP_TIMEOUT_MS, "streamer.append").catch((e) => logger.warn({ error: e }, "Failed to append inline citation"));
|
|
359
|
+
}
|
|
356
360
|
} else if (richMessageCount < MAX_RICH_MESSAGES) {
|
|
357
361
|
const { blocks, overflowContent, artifactName } = buildDataArtifactBlocks({ data: artifactData });
|
|
358
362
|
if (overflowContent) {
|
|
@@ -8,12 +8,12 @@ import { AgentOption } from "../modals.js";
|
|
|
8
8
|
* Called on every @mention and /inkeep command — caching avoids redundant DB queries.
|
|
9
9
|
*/
|
|
10
10
|
declare function findCachedUserMapping(tenantId: string, slackUserId: string, teamId: string, clientId?: string): Promise<{
|
|
11
|
-
slackUserId: string;
|
|
12
|
-
id: string;
|
|
13
11
|
createdAt: string;
|
|
14
12
|
updatedAt: string;
|
|
13
|
+
id: string;
|
|
15
14
|
tenantId: string;
|
|
16
15
|
clientId: string;
|
|
16
|
+
slackUserId: string;
|
|
17
17
|
slackTeamId: string;
|
|
18
18
|
slackEnterpriseId: string | null;
|
|
19
19
|
inkeepUserId: string;
|
|
@@ -22,6 +22,18 @@ declare function findCachedUserMapping(tenantId: string, slackUserId: string, te
|
|
|
22
22
|
linkedAt: string;
|
|
23
23
|
lastUsedAt: string | null;
|
|
24
24
|
} | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Escape special characters in Slack mrkdwn link display text.
|
|
27
|
+
* In Slack's <url|text> format, `>` terminates the link, `<` opens a new one,
|
|
28
|
+
* and `&` begins an HTML entity — all must be escaped.
|
|
29
|
+
*/
|
|
30
|
+
declare function escapeSlackLinkText(text: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Escape special characters in Slack mrkdwn text.
|
|
33
|
+
* In Slack's mrkdwn, `&`, `<`, and `>` are treated as HTML entities/tags
|
|
34
|
+
* and must be escaped in all dynamic mrkdwn text fields.
|
|
35
|
+
*/
|
|
36
|
+
declare function escapeSlackMrkdwn(text: string): string;
|
|
25
37
|
/**
|
|
26
38
|
* Convert standard Markdown to Slack's mrkdwn format
|
|
27
39
|
*
|
|
@@ -167,4 +179,4 @@ declare function formatChannelContext(channelInfo: {
|
|
|
167
179
|
name?: string;
|
|
168
180
|
} | null): string;
|
|
169
181
|
//#endregion
|
|
170
|
-
export { ProjectOption, SlackAttachment, SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatAttachments, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
|
|
182
|
+
export { ProjectOption, SlackAttachment, SlackErrorType, checkIfBotThread, classifyError, escapeSlackLinkText, escapeSlackMrkdwn, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatAttachments, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
|
|
@@ -50,6 +50,22 @@ async function findCachedUserMapping(tenantId, slackUserId, teamId, clientId = "
|
|
|
50
50
|
return mapping;
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
|
+
* Escape special characters in Slack mrkdwn link display text.
|
|
54
|
+
* In Slack's <url|text> format, `>` terminates the link, `<` opens a new one,
|
|
55
|
+
* and `&` begins an HTML entity — all must be escaped.
|
|
56
|
+
*/
|
|
57
|
+
function escapeSlackLinkText(text) {
|
|
58
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Escape special characters in Slack mrkdwn text.
|
|
62
|
+
* In Slack's mrkdwn, `&`, `<`, and `>` are treated as HTML entities/tags
|
|
63
|
+
* and must be escaped in all dynamic mrkdwn text fields.
|
|
64
|
+
*/
|
|
65
|
+
function escapeSlackMrkdwn(text) {
|
|
66
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
53
69
|
* Convert standard Markdown to Slack's mrkdwn format
|
|
54
70
|
*
|
|
55
71
|
* Key differences:
|
|
@@ -63,7 +79,7 @@ function markdownToMrkdwn(markdown) {
|
|
|
63
79
|
if (!markdown) return markdown;
|
|
64
80
|
let result = markdown;
|
|
65
81
|
result = result.replace(/^#{1,6}\s+(.+)$/gm, "*$1*");
|
|
66
|
-
result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g,
|
|
82
|
+
result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => `<${url}|${escapeSlackLinkText(text)}>`);
|
|
67
83
|
result = result.replace(/\*\*([^*]+)\*\*/g, "*$1*");
|
|
68
84
|
result = result.replace(/__([^_]+)__/g, "*$1*");
|
|
69
85
|
result = result.replace(/~~([^~]+)~~/g, "~$1~");
|
|
@@ -426,4 +442,4 @@ function formatChannelContext(channelInfo) {
|
|
|
426
442
|
}
|
|
427
443
|
|
|
428
444
|
//#endregion
|
|
429
|
-
export { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatAttachments, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
|
|
445
|
+
export { SlackErrorType, checkIfBotThread, classifyError, escapeSlackLinkText, escapeSlackMrkdwn, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatAttachments, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkeep/agents-work-apps",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-20260225221013",
|
|
4
4
|
"description": "First party integrations for Inkeep Agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"jose": "^6.1.0",
|
|
34
34
|
"minimatch": "^10.1.1",
|
|
35
35
|
"slack-block-builder": "^2.8.0",
|
|
36
|
-
"@inkeep/agents-core": "0.0.0-dev-
|
|
36
|
+
"@inkeep/agents-core": "0.0.0-dev-20260225221013"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@hono/zod-openapi": "^1.1.5",
|