@cuylabs/channel-slack-agent-core 0.5.1 → 0.6.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/README.md +14 -40
- package/dist/{adapter.d.ts → adapter/index.d.ts} +4 -5
- package/dist/adapter/index.js +9 -0
- package/dist/app-surface.js +5 -7
- package/dist/app.d.ts +2 -1
- package/dist/app.js +6 -9
- package/dist/{assistant.d.ts → assistant/index.d.ts} +4 -4
- package/dist/{assistant.js → assistant/index.js} +3 -5
- package/dist/{chunk-JMLB7A2V.js → chunk-5NQYLOAW.js} +5 -5
- package/dist/{chunk-NIPAN4KA.js → chunk-A2PLAVW6.js} +2 -3
- package/dist/chunk-C7VSW4ZM.js +548 -0
- package/dist/chunk-ELR6MQD7.js +12 -0
- package/dist/{chunk-CYEBGC6G.js → chunk-FNT4TXNQ.js} +5 -5
- package/dist/{chunk-DHPD4XH5.js → chunk-NOVWLAVP.js} +1 -9
- package/dist/{chunk-M64Z6TYL.js → chunk-P7KK5GQG.js} +7 -6
- package/dist/chunk-P7PFQ3SQ.js +396 -0
- package/dist/{chunk-IWUYIAY5.js → chunk-QEJ7TAZJ.js} +5 -7
- package/dist/{chunk-FDRQOG7Q.js → chunk-TIQGJ52F.js} +13 -14
- package/dist/{chunk-WO4BJMF3.js → chunk-VCXPNQRB.js} +5 -5
- package/dist/{chunk-BFUPAJON.js → chunk-ZDVD46RT.js} +37 -37
- package/dist/context-fragments-CQEDcjYR.d.ts +30 -0
- package/dist/express-assistant.d.ts +2 -1
- package/dist/express-assistant.js +4 -7
- package/dist/express.d.ts +2 -1
- package/dist/express.js +3 -6
- package/dist/feedback/index.d.ts +1 -0
- package/dist/feedback/index.js +10 -0
- package/dist/history/index.d.ts +57 -0
- package/dist/history/index.js +8 -0
- package/dist/index.d.ts +14 -13
- package/dist/index.js +63 -160
- package/dist/{interactive.d.ts → interactive/index.d.ts} +3 -3
- package/dist/{interactive.js → interactive/index.js} +1 -2
- package/dist/mcp.js +0 -1
- package/dist/{shared.d.ts → shared/index.d.ts} +7 -33
- package/dist/{shared.js → shared/index.js} +2 -6
- package/dist/socket.d.ts +2 -1
- package/dist/socket.js +6 -9
- package/dist/source/index.d.ts +154 -0
- package/dist/source/index.js +38 -0
- package/docs/README.md +11 -0
- package/docs/reference/boundary.md +22 -0
- package/docs/reference/exports.md +24 -0
- package/package.json +27 -51
- package/dist/adapter.js +0 -13
- package/dist/bolt.d.ts +0 -8
- package/dist/bolt.js +0 -10
- package/dist/chunk-2SUAW6MV.js +0 -12
- package/dist/chunk-645NNJIM.js +0 -12
- package/dist/chunk-ANIZ5NT4.js +0 -12
- package/dist/chunk-GNXWTKQ6.js +0 -48
- package/dist/chunk-HFT2FXJP.js +0 -12
- package/dist/chunk-I2KLQ2HA.js +0 -22
- package/dist/chunk-K2E6A377.js +0 -12
- package/dist/chunk-NDVXBI7Z.js +0 -12
- package/dist/chunk-PX4RGO3N.js +0 -12
- package/dist/chunk-VHGV66M7.js +0 -12
- package/dist/diagnostics.d.ts +0 -1
- package/dist/diagnostics.js +0 -10
- package/dist/feedback.d.ts +0 -1
- package/dist/feedback.js +0 -10
- package/dist/history.d.ts +0 -1
- package/dist/history.js +0 -10
- package/dist/policy.d.ts +0 -1
- package/dist/policy.js +0 -10
- package/dist/setup.d.ts +0 -1
- package/dist/setup.js +0 -10
- package/dist/targets.d.ts +0 -1
- package/dist/targets.js +0 -10
- package/dist/users.d.ts +0 -1
- package/dist/users.js +0 -10
- /package/dist/{chunk-IXY3BXU5.js → chunk-J6CW2RGO.js} +0 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
// src/history/turn-context.ts
|
|
2
|
+
import {
|
|
3
|
+
createSlackSupplementalHistoryVisibilityPolicy,
|
|
4
|
+
loadSlackTurnHistoryContext
|
|
5
|
+
} from "@cuylabs/channel-slack/history";
|
|
6
|
+
import { enrichSlackUserMentions } from "@cuylabs/channel-slack/users";
|
|
7
|
+
import { WebClient } from "@slack/web-api";
|
|
8
|
+
async function loadSlackAgentTurnHistoryContext({
|
|
9
|
+
history,
|
|
10
|
+
logger,
|
|
11
|
+
originChannelId: providedOriginChannelId,
|
|
12
|
+
profileResolver,
|
|
13
|
+
request
|
|
14
|
+
}) {
|
|
15
|
+
const originChannelId = providedOriginChannelId ?? resolveOriginChannelId(request);
|
|
16
|
+
const client = resolveSlackHistoryClient(request);
|
|
17
|
+
if (!history.enabled) {
|
|
18
|
+
logger?.debug?.("Slack context history disabled", {
|
|
19
|
+
channelId: request.slackActivity.channelId,
|
|
20
|
+
threadTs: request.slackActivity.threadTs
|
|
21
|
+
});
|
|
22
|
+
return emptySlackAgentTurnHistoryContextResult();
|
|
23
|
+
}
|
|
24
|
+
if (!client) {
|
|
25
|
+
logger?.warn?.("Slack context history enabled without a Slack WebClient", {
|
|
26
|
+
channelId: request.slackActivity.channelId,
|
|
27
|
+
threadTs: request.slackActivity.threadTs
|
|
28
|
+
});
|
|
29
|
+
return emptySlackAgentTurnHistoryContextResult();
|
|
30
|
+
}
|
|
31
|
+
const teamId = request.slackActivity.teamId ?? request.user.teamId ?? request.auth?.teamId;
|
|
32
|
+
const threadTs = request.slackActivity.threadTs ?? request.slackActivity.messageTs;
|
|
33
|
+
const resolveAuthor = profileResolver ? createSlackAgentHistoryAuthorResolver({
|
|
34
|
+
botToken: request.auth?.botToken,
|
|
35
|
+
logger,
|
|
36
|
+
profileResolver,
|
|
37
|
+
teamId
|
|
38
|
+
}) : void 0;
|
|
39
|
+
const loaded = await loadSlackTurnHistoryContext({
|
|
40
|
+
activity: request.slackActivity,
|
|
41
|
+
botUserId: request.auth?.botUserId,
|
|
42
|
+
client,
|
|
43
|
+
includeTopLevelChannelFallback: request.slackActivity.channelType !== "dm",
|
|
44
|
+
limit: history.limit,
|
|
45
|
+
maxCharacters: history.maxCharacters,
|
|
46
|
+
token: request.auth?.botToken,
|
|
47
|
+
...teamId ? { teamId } : {},
|
|
48
|
+
...originChannelId ? { originChannelId } : {},
|
|
49
|
+
visibilityPolicy: createSlackSupplementalHistoryVisibilityPolicy({
|
|
50
|
+
allowedUserIds: history.visibilityAllowedUserIds ?? [],
|
|
51
|
+
mode: history.visibilityMode ?? "all"
|
|
52
|
+
}),
|
|
53
|
+
onVisibilityPolicyError: ({ channelId, error, source, teamId: teamId2 }) => {
|
|
54
|
+
logger?.warn?.("Slack supplemental history visibility policy failed", {
|
|
55
|
+
channelId,
|
|
56
|
+
source,
|
|
57
|
+
...teamId2 ? { teamId: teamId2 } : {},
|
|
58
|
+
error: formatHistoryError(error)
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
...request.assistant ? {
|
|
62
|
+
assistantSurfaceThreadRootUser: {
|
|
63
|
+
userId: request.slackActivity.userId
|
|
64
|
+
},
|
|
65
|
+
onAssistantSurfaceThreadRootNormalized: ({
|
|
66
|
+
action,
|
|
67
|
+
channelId,
|
|
68
|
+
teamId: normalizedTeamId,
|
|
69
|
+
threadTs: threadTs2,
|
|
70
|
+
userId
|
|
71
|
+
}) => {
|
|
72
|
+
logger?.debug?.(
|
|
73
|
+
action === "removed-duplicate" ? "Slack assistant surface duplicate thread root removed" : "Slack assistant surface thread root author corrected",
|
|
74
|
+
{
|
|
75
|
+
channelId,
|
|
76
|
+
...normalizedTeamId ? { teamId: normalizedTeamId } : {},
|
|
77
|
+
threadTs: threadTs2,
|
|
78
|
+
userId
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
} : {},
|
|
83
|
+
headers: {
|
|
84
|
+
channel: "Recent Slack channel history before the current message:",
|
|
85
|
+
...originChannelId ? {
|
|
86
|
+
originChannel: `Recent Slack channel context from ${originChannelId}:`
|
|
87
|
+
} : {},
|
|
88
|
+
thread: "Recent Slack thread history before the current message:"
|
|
89
|
+
},
|
|
90
|
+
...resolveAuthor ? { resolveAuthor } : {},
|
|
91
|
+
...resolveAuthor ? {
|
|
92
|
+
onResolveAuthorError: ({
|
|
93
|
+
channelId,
|
|
94
|
+
error,
|
|
95
|
+
source,
|
|
96
|
+
teamId: errorTeamId,
|
|
97
|
+
userId
|
|
98
|
+
}) => {
|
|
99
|
+
logger?.debug?.("Slack history author attribution failed", {
|
|
100
|
+
channelId,
|
|
101
|
+
source,
|
|
102
|
+
...errorTeamId ? { teamId: errorTeamId } : {},
|
|
103
|
+
...userId ? { userId } : {},
|
|
104
|
+
error: formatHistoryError(error)
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
} : {}
|
|
108
|
+
});
|
|
109
|
+
const unavailableReasons = summarizeUnavailable(loaded.unavailable);
|
|
110
|
+
for (const issue of loaded.unavailable) {
|
|
111
|
+
logSlackAgentHistoryUnavailable(logger, issue);
|
|
112
|
+
}
|
|
113
|
+
const loadedPrompt = await enrichSlackAgentHistoryMentions({
|
|
114
|
+
botToken: request.auth?.botToken,
|
|
115
|
+
logger,
|
|
116
|
+
profileResolver,
|
|
117
|
+
prompt: loaded.prompt,
|
|
118
|
+
teamId
|
|
119
|
+
});
|
|
120
|
+
const prompt = truncateHistoryPrompt(
|
|
121
|
+
[
|
|
122
|
+
loadedPrompt,
|
|
123
|
+
...loaded.unavailable.map(
|
|
124
|
+
(issue) => (history.unavailableNoteFormatter ?? formatSlackAgentHistoryUnavailableNote)(issue)
|
|
125
|
+
)
|
|
126
|
+
].filter(Boolean).join("\n\n"),
|
|
127
|
+
history
|
|
128
|
+
);
|
|
129
|
+
const fragment = prompt ? createSlackAgentHistoryFragment({
|
|
130
|
+
history,
|
|
131
|
+
loadedFragment: loaded.fragment,
|
|
132
|
+
prompt,
|
|
133
|
+
unavailableReasons
|
|
134
|
+
}) : void 0;
|
|
135
|
+
logger?.debug?.("Slack context history loaded", {
|
|
136
|
+
channelId: request.slackActivity.channelId,
|
|
137
|
+
included: Boolean(prompt),
|
|
138
|
+
maxCharacters: history.maxCharacters,
|
|
139
|
+
maxMessages: history.limit,
|
|
140
|
+
originChannelId,
|
|
141
|
+
originChannelMessageCount: loaded.originChannelMessageCount,
|
|
142
|
+
originChannelUnavailableReason: unavailableReasons.originChannelUnavailableReason,
|
|
143
|
+
promptChars: prompt?.length ?? 0,
|
|
144
|
+
threadMessageCount: loaded.threadMessageCount,
|
|
145
|
+
threadTs,
|
|
146
|
+
threadUnavailableReason: unavailableReasons.threadUnavailableReason,
|
|
147
|
+
topLevelChannelMessageCount: loaded.topLevelChannelMessageCount,
|
|
148
|
+
topLevelChannelUnavailableReason: unavailableReasons.topLevelChannelUnavailableReason
|
|
149
|
+
});
|
|
150
|
+
return {
|
|
151
|
+
...fragment ? { fragment } : {},
|
|
152
|
+
...prompt ? { prompt } : {},
|
|
153
|
+
originChannelMessageCount: loaded.originChannelMessageCount,
|
|
154
|
+
originChannelVisibilityOmittedMessageCount: loaded.originChannelVisibilityOmittedMessageCount,
|
|
155
|
+
threadMessageCount: loaded.threadMessageCount,
|
|
156
|
+
threadVisibilityOmittedMessageCount: loaded.threadVisibilityOmittedMessageCount,
|
|
157
|
+
topLevelChannelMessageCount: loaded.topLevelChannelMessageCount,
|
|
158
|
+
topLevelChannelVisibilityOmittedMessageCount: loaded.topLevelChannelVisibilityOmittedMessageCount,
|
|
159
|
+
visibilityOmittedMessageCount: loaded.visibilityOmittedMessageCount,
|
|
160
|
+
...unavailableReasons.originChannelUnavailableReason ? {
|
|
161
|
+
originChannelUnavailableReason: unavailableReasons.originChannelUnavailableReason
|
|
162
|
+
} : {},
|
|
163
|
+
...unavailableReasons.threadUnavailableReason ? { threadUnavailableReason: unavailableReasons.threadUnavailableReason } : {},
|
|
164
|
+
...unavailableReasons.topLevelChannelUnavailableReason ? {
|
|
165
|
+
topLevelChannelUnavailableReason: unavailableReasons.topLevelChannelUnavailableReason
|
|
166
|
+
} : {}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function emptySlackAgentTurnHistoryContextResult() {
|
|
170
|
+
return {
|
|
171
|
+
originChannelMessageCount: 0,
|
|
172
|
+
originChannelVisibilityOmittedMessageCount: 0,
|
|
173
|
+
threadMessageCount: 0,
|
|
174
|
+
threadVisibilityOmittedMessageCount: 0,
|
|
175
|
+
topLevelChannelMessageCount: 0,
|
|
176
|
+
topLevelChannelVisibilityOmittedMessageCount: 0,
|
|
177
|
+
visibilityOmittedMessageCount: 0
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async function enrichSlackAgentHistoryMentions({
|
|
181
|
+
botToken,
|
|
182
|
+
logger,
|
|
183
|
+
profileResolver,
|
|
184
|
+
prompt,
|
|
185
|
+
teamId
|
|
186
|
+
}) {
|
|
187
|
+
if (!prompt || !profileResolver) {
|
|
188
|
+
return prompt;
|
|
189
|
+
}
|
|
190
|
+
const result = await enrichSlackUserMentions(
|
|
191
|
+
{
|
|
192
|
+
text: prompt,
|
|
193
|
+
...botToken ? { botToken } : {},
|
|
194
|
+
...teamId ? { teamId } : {}
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
concurrency: 4,
|
|
198
|
+
formatLabel: ({ mention, profile }) => profile.displayName ? `${mention} (${profile.displayName})` : void 0,
|
|
199
|
+
maxLookups: 20,
|
|
200
|
+
onResolveError: ({ error, teamId: errorTeamId, userId }) => {
|
|
201
|
+
logger?.debug?.("Slack history mention enrichment failed", {
|
|
202
|
+
...errorTeamId ? { teamId: errorTeamId } : {},
|
|
203
|
+
error: formatHistoryError(error),
|
|
204
|
+
userId
|
|
205
|
+
});
|
|
206
|
+
},
|
|
207
|
+
profileResolver: {
|
|
208
|
+
resolve: async (input) => ({
|
|
209
|
+
userId: input.userId,
|
|
210
|
+
...await profileResolver.resolve({
|
|
211
|
+
botToken: input.botToken,
|
|
212
|
+
teamId: input.teamId,
|
|
213
|
+
userId: input.userId
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
return result.text;
|
|
220
|
+
}
|
|
221
|
+
function createSlackAgentHistoryAuthorResolver({
|
|
222
|
+
botToken,
|
|
223
|
+
logger,
|
|
224
|
+
profileResolver,
|
|
225
|
+
teamId
|
|
226
|
+
}) {
|
|
227
|
+
return async (message, context) => {
|
|
228
|
+
if (message.role === "assistant") {
|
|
229
|
+
return "Assistant";
|
|
230
|
+
}
|
|
231
|
+
if (message.role === "bot") {
|
|
232
|
+
return "Bot";
|
|
233
|
+
}
|
|
234
|
+
if (!message.userId) {
|
|
235
|
+
return void 0;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
const profile = await profileResolver.resolve({
|
|
239
|
+
botToken,
|
|
240
|
+
teamId: context.teamId ?? teamId,
|
|
241
|
+
userId: message.userId
|
|
242
|
+
});
|
|
243
|
+
return formatSlackHistoryUserAuthor(message.userId, profile.displayName);
|
|
244
|
+
} catch (error) {
|
|
245
|
+
logger?.debug?.("Slack history profile lookup failed", {
|
|
246
|
+
channelId: context.channelId,
|
|
247
|
+
error: formatHistoryError(error),
|
|
248
|
+
source: context.source,
|
|
249
|
+
teamId: context.teamId ?? teamId,
|
|
250
|
+
userId: message.userId
|
|
251
|
+
});
|
|
252
|
+
return formatSlackHistoryUserAuthor(message.userId);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function formatSlackHistoryUserAuthor(userId, displayName) {
|
|
257
|
+
return displayName ? `${displayName} (${userId})` : `Slack user ${userId}`;
|
|
258
|
+
}
|
|
259
|
+
function createSlackAgentHistoryFragment({
|
|
260
|
+
history,
|
|
261
|
+
loadedFragment,
|
|
262
|
+
prompt,
|
|
263
|
+
unavailableReasons
|
|
264
|
+
}) {
|
|
265
|
+
return {
|
|
266
|
+
...loadedFragment,
|
|
267
|
+
budgetBehavior: loadedFragment?.budgetBehavior ?? "droppable",
|
|
268
|
+
content: prompt,
|
|
269
|
+
kind: loadedFragment?.kind ?? "slack-context",
|
|
270
|
+
lifetime: loadedFragment?.lifetime ?? "turn",
|
|
271
|
+
maxChars: loadedFragment?.maxChars ?? history.maxCharacters,
|
|
272
|
+
metadata: {
|
|
273
|
+
...loadedFragment?.metadata,
|
|
274
|
+
...unavailableReasons.originChannelUnavailableReason ? {
|
|
275
|
+
originChannelUnavailableReason: unavailableReasons.originChannelUnavailableReason
|
|
276
|
+
} : {},
|
|
277
|
+
...unavailableReasons.threadUnavailableReason ? {
|
|
278
|
+
threadUnavailableReason: unavailableReasons.threadUnavailableReason
|
|
279
|
+
} : {},
|
|
280
|
+
...unavailableReasons.topLevelChannelUnavailableReason ? {
|
|
281
|
+
topLevelChannelUnavailableReason: unavailableReasons.topLevelChannelUnavailableReason
|
|
282
|
+
} : {}
|
|
283
|
+
},
|
|
284
|
+
placement: loadedFragment?.placement ?? "after-latest-user",
|
|
285
|
+
role: loadedFragment?.role ?? "user",
|
|
286
|
+
source: loadedFragment?.source ?? "slack",
|
|
287
|
+
title: loadedFragment?.title ?? "Slack Conversation History"
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function logSlackAgentHistoryUnavailable(logger, issue) {
|
|
291
|
+
const fields = {
|
|
292
|
+
channelId: issue.channelId,
|
|
293
|
+
error: issue.message,
|
|
294
|
+
expected: issue.expected,
|
|
295
|
+
...normalizedHistoryHint(issue) ? { hint: normalizedHistoryHint(issue) } : {},
|
|
296
|
+
method: issue.method,
|
|
297
|
+
slackError: normalizedHistoryErrorCode(issue) ?? "unknown",
|
|
298
|
+
source: issue.source
|
|
299
|
+
};
|
|
300
|
+
if (issue.expected) {
|
|
301
|
+
logger?.info?.("Slack context history unavailable", fields);
|
|
302
|
+
} else {
|
|
303
|
+
logger?.warn?.("Slack context history unavailable", fields);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function formatSlackAgentHistoryUnavailableNote(issue) {
|
|
307
|
+
const reason = normalizedHistoryErrorCode(issue) ?? "unknown_error";
|
|
308
|
+
const hint = normalizedHistoryHint(issue);
|
|
309
|
+
return [
|
|
310
|
+
`${historyScopeLabel(issue)} context is unavailable to the app for this turn (${reason}).`,
|
|
311
|
+
`If the user asks about that Slack context, say that you cannot read it yet and explain the needed access.${hint ? ` ${normalizeHistoryHint(hint)}` : ""}`
|
|
312
|
+
].join(" ");
|
|
313
|
+
}
|
|
314
|
+
function historyScopeLabel(issue) {
|
|
315
|
+
switch (issue.source) {
|
|
316
|
+
case "thread":
|
|
317
|
+
return "current assistant thread";
|
|
318
|
+
case "channel":
|
|
319
|
+
return `current Slack channel ${issue.channelId}`;
|
|
320
|
+
case "origin-channel":
|
|
321
|
+
return `origin Slack channel ${issue.channelId}`;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function normalizeHistoryHint(hint) {
|
|
325
|
+
return hint.endsWith(".") ? hint : `${hint}.`;
|
|
326
|
+
}
|
|
327
|
+
function summarizeUnavailable(unavailable) {
|
|
328
|
+
return {
|
|
329
|
+
originChannelUnavailableReason: unavailableReason(
|
|
330
|
+
unavailable,
|
|
331
|
+
"origin-channel"
|
|
332
|
+
),
|
|
333
|
+
threadUnavailableReason: unavailableReason(unavailable, "thread"),
|
|
334
|
+
topLevelChannelUnavailableReason: unavailableReason(unavailable, "channel")
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function unavailableReason(unavailable, source) {
|
|
338
|
+
const issue = unavailable.find((entry) => entry.source === source);
|
|
339
|
+
return issue ? normalizedHistoryErrorCode(issue) ?? issue.message : void 0;
|
|
340
|
+
}
|
|
341
|
+
function normalizedHistoryErrorCode(issue) {
|
|
342
|
+
if (issue.errorCode) {
|
|
343
|
+
return issue.errorCode;
|
|
344
|
+
}
|
|
345
|
+
const failedMatch = issue.message.match(/failed:\s*([a-z_]+)/i);
|
|
346
|
+
if (failedMatch?.[1]) {
|
|
347
|
+
return failedMatch[1];
|
|
348
|
+
}
|
|
349
|
+
const apiMatch = issue.message.match(/API error occurred:\s*([a-z_]+)/i);
|
|
350
|
+
return apiMatch?.[1];
|
|
351
|
+
}
|
|
352
|
+
function normalizedHistoryHint(issue) {
|
|
353
|
+
if (issue.hint) {
|
|
354
|
+
return issue.hint;
|
|
355
|
+
}
|
|
356
|
+
switch (normalizedHistoryErrorCode(issue)) {
|
|
357
|
+
case "not_in_channel":
|
|
358
|
+
return "Invite the app to the channel, then retry.";
|
|
359
|
+
case "channel_not_found":
|
|
360
|
+
return "Slack did not expose a readable channel for this bot token.";
|
|
361
|
+
case "no_permission":
|
|
362
|
+
case "access_denied":
|
|
363
|
+
return "The bot token cannot read this conversation.";
|
|
364
|
+
case "missing_scope":
|
|
365
|
+
return "Add the matching Slack history scope and reinstall the app.";
|
|
366
|
+
default:
|
|
367
|
+
return void 0;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function resolveSlackHistoryClient(request) {
|
|
371
|
+
if (request.client) {
|
|
372
|
+
return request.client;
|
|
373
|
+
}
|
|
374
|
+
return request.auth?.botToken ? new WebClient(request.auth.botToken) : void 0;
|
|
375
|
+
}
|
|
376
|
+
function resolveOriginChannelId(request) {
|
|
377
|
+
return request.threadContext?.channel_id && request.threadContext.channel_id !== request.slackActivity.channelId ? request.threadContext.channel_id : void 0;
|
|
378
|
+
}
|
|
379
|
+
function truncateHistoryPrompt(value, history) {
|
|
380
|
+
const trimmed = value.trim();
|
|
381
|
+
if (!trimmed) {
|
|
382
|
+
return void 0;
|
|
383
|
+
}
|
|
384
|
+
if (trimmed.length <= history.maxCharacters) {
|
|
385
|
+
return trimmed;
|
|
386
|
+
}
|
|
387
|
+
return trimmed.slice(0, history.maxCharacters).trimEnd();
|
|
388
|
+
}
|
|
389
|
+
function formatHistoryError(error) {
|
|
390
|
+
return error instanceof Error ? error.stack ?? error.message : String(error);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export {
|
|
394
|
+
loadSlackAgentTurnHistoryContext,
|
|
395
|
+
emptySlackAgentTurnHistoryContextResult
|
|
396
|
+
};
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
installSlackAgentAppSurface
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-P7KK5GQG.js";
|
|
4
4
|
import {
|
|
5
5
|
createSlackAssistantBridge
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
bolt_exports
|
|
9
|
-
} from "./chunk-ANIZ5NT4.js";
|
|
6
|
+
} from "./chunk-ZDVD46RT.js";
|
|
10
7
|
|
|
11
8
|
// src/socket.ts
|
|
9
|
+
import { createSlackSocketBoltApp } from "@cuylabs/channel-slack/transports/socket";
|
|
12
10
|
async function mountSlackAssistantAgentSocket(options) {
|
|
13
11
|
const {
|
|
14
12
|
appToken: appTokenOption,
|
|
@@ -21,7 +19,7 @@ async function mountSlackAssistantAgentSocket(options) {
|
|
|
21
19
|
start,
|
|
22
20
|
...bridgeOptions
|
|
23
21
|
} = options;
|
|
24
|
-
const { boltApp, authMode } = await
|
|
22
|
+
const { boltApp, authMode } = await createSlackSocketBoltApp({
|
|
25
23
|
appToken: appTokenOption,
|
|
26
24
|
botToken: botTokenOption,
|
|
27
25
|
auth,
|
|
@@ -49,7 +47,7 @@ async function mountSlackAgentAppSocket(options) {
|
|
|
49
47
|
start,
|
|
50
48
|
...surfaceOptions
|
|
51
49
|
} = options;
|
|
52
|
-
const { boltApp, authMode } = await
|
|
50
|
+
const { boltApp, authMode } = await createSlackSocketBoltApp({
|
|
53
51
|
appToken: appTokenOption,
|
|
54
52
|
botToken: botTokenOption,
|
|
55
53
|
auth,
|
|
@@ -1,22 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UnsupportedSlackInteractiveRequestError,
|
|
3
|
+
bridgeAgentEventsToSlack,
|
|
4
|
+
resolveSlackEventBridgeOptions
|
|
5
|
+
} from "./chunk-NOVWLAVP.js";
|
|
6
|
+
|
|
7
|
+
// src/adapter/adapter.ts
|
|
8
|
+
import { withinScope } from "@cuylabs/agent-core";
|
|
1
9
|
import {
|
|
2
10
|
extractSlackAuthContext,
|
|
3
11
|
extractSlackUserIdentity,
|
|
4
12
|
isProcessableMessage,
|
|
5
13
|
parseSlackMentionActivity,
|
|
6
14
|
parseSlackMessageActivity,
|
|
7
|
-
resolveSlackMessageFormatter
|
|
8
|
-
} from "./chunk-GNXWTKQ6.js";
|
|
9
|
-
import {
|
|
10
|
-
UnsupportedSlackInteractiveRequestError,
|
|
11
|
-
bridgeAgentEventsToSlack,
|
|
12
|
-
resolveSlackEventBridgeOptions,
|
|
15
|
+
resolveSlackMessageFormatter,
|
|
13
16
|
runWithSlackTurnContext
|
|
14
|
-
} from "
|
|
15
|
-
|
|
16
|
-
// src/shared/session.ts
|
|
17
|
-
import { resolveThreadAwareSlackSessionId } from "@cuylabs/channel-slack/core";
|
|
17
|
+
} from "@cuylabs/channel-slack/core";
|
|
18
18
|
|
|
19
19
|
// src/adapter/session-map.ts
|
|
20
|
+
import {
|
|
21
|
+
resolveThreadAwareSlackSessionId
|
|
22
|
+
} from "@cuylabs/channel-slack/core";
|
|
20
23
|
function createSlackSessionMap(options) {
|
|
21
24
|
const strategy = options.sessionStrategy ?? "thread-aware";
|
|
22
25
|
if (strategy === "custom") {
|
|
@@ -61,9 +64,6 @@ function createSlackSessionMap(options) {
|
|
|
61
64
|
};
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
// src/adapter/adapter.ts
|
|
65
|
-
import { withinScope } from "@cuylabs/agent-core";
|
|
66
|
-
|
|
67
67
|
// src/adapter/sink.ts
|
|
68
68
|
function buildThreadPayload(info, respondInThread) {
|
|
69
69
|
if (!respondInThread || info.channelType === "dm") return {};
|
|
@@ -465,7 +465,6 @@ function formatErrorForLog(error) {
|
|
|
465
465
|
}
|
|
466
466
|
|
|
467
467
|
export {
|
|
468
|
-
resolveThreadAwareSlackSessionId,
|
|
469
468
|
createSlackSessionMap,
|
|
470
469
|
createSlackChannelAdapter
|
|
471
470
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSlackChannelAdapter
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import {
|
|
5
|
-
bolt_exports
|
|
6
|
-
} from "./chunk-ANIZ5NT4.js";
|
|
3
|
+
} from "./chunk-TIQGJ52F.js";
|
|
7
4
|
|
|
8
5
|
// src/express.ts
|
|
6
|
+
import {
|
|
7
|
+
createSlackBoltApp
|
|
8
|
+
} from "@cuylabs/channel-slack/transports/http";
|
|
9
9
|
async function mountSlackAgent(source, options = {}) {
|
|
10
10
|
const {
|
|
11
11
|
botToken: providedToken,
|
|
@@ -27,7 +27,7 @@ async function mountSlackAgent(source, options = {}) {
|
|
|
27
27
|
app: expressApp,
|
|
28
28
|
authMode,
|
|
29
29
|
routePath
|
|
30
|
-
} = await
|
|
30
|
+
} = await createSlackBoltApp({
|
|
31
31
|
signingSecret,
|
|
32
32
|
path,
|
|
33
33
|
botToken: providedToken,
|
|
@@ -1,38 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
resolveSlackMessageFormatter
|
|
7
|
-
} from "./chunk-GNXWTKQ6.js";
|
|
2
|
+
SLACK_FEEDBACK_ACTION_ID,
|
|
3
|
+
createSlackFeedbackBlock,
|
|
4
|
+
registerSlackFeedbackAction
|
|
5
|
+
} from "./chunk-ELR6MQD7.js";
|
|
8
6
|
import {
|
|
9
7
|
UnsupportedSlackInteractiveRequestError,
|
|
10
8
|
bridgeAgentEventsToSlack,
|
|
11
|
-
resolveSlackEventBridgeOptions
|
|
12
|
-
|
|
13
|
-
} from "./chunk-DHPD4XH5.js";
|
|
14
|
-
|
|
15
|
-
// src/assistant/message-parser.ts
|
|
16
|
-
import {
|
|
17
|
-
parseSlackMessageActivityFromMessageEvent
|
|
18
|
-
} from "@cuylabs/channel-slack/assistant";
|
|
19
|
-
|
|
20
|
-
// src/assistant/session.ts
|
|
21
|
-
function resolveAssistantSessionId(message, strategy) {
|
|
22
|
-
switch (strategy) {
|
|
23
|
-
case "channel-id":
|
|
24
|
-
return message.channel;
|
|
25
|
-
case "user-per-thread":
|
|
26
|
-
return `${message.channel}:${message.threadTs}:${message.userId}`;
|
|
27
|
-
default:
|
|
28
|
-
return `${message.channel}:${message.threadTs}`;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// src/assistant/thread-context-store.ts
|
|
33
|
-
import {
|
|
34
|
-
createSlackAssistantThreadContextStore
|
|
35
|
-
} from "@cuylabs/channel-slack/assistant";
|
|
9
|
+
resolveSlackEventBridgeOptions
|
|
10
|
+
} from "./chunk-NOVWLAVP.js";
|
|
36
11
|
|
|
37
12
|
// src/assistant/bridge.ts
|
|
38
13
|
import { Assistant } from "@slack/bolt";
|
|
@@ -190,6 +165,24 @@ function createThreadContextChangedHandler() {
|
|
|
190
165
|
import {
|
|
191
166
|
withinScope
|
|
192
167
|
} from "@cuylabs/agent-core";
|
|
168
|
+
import {
|
|
169
|
+
extractSlackAuthContext,
|
|
170
|
+
resolveSlackMessageFormatter,
|
|
171
|
+
runWithSlackTurnContext
|
|
172
|
+
} from "@cuylabs/channel-slack/core";
|
|
173
|
+
import { parseSlackMessageActivityFromMessageEvent } from "@cuylabs/channel-slack/assistant";
|
|
174
|
+
|
|
175
|
+
// src/assistant/session.ts
|
|
176
|
+
function resolveAssistantSessionId(message, strategy) {
|
|
177
|
+
switch (strategy) {
|
|
178
|
+
case "channel-id":
|
|
179
|
+
return message.channel;
|
|
180
|
+
case "user-per-thread":
|
|
181
|
+
return `${message.channel}:${message.threadTs}:${message.userId}`;
|
|
182
|
+
default:
|
|
183
|
+
return `${message.channel}:${message.threadTs}`;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
193
186
|
|
|
194
187
|
// src/assistant/scope-attributes.ts
|
|
195
188
|
function buildAssistantScopeAttributes(message, auth, threadContext, prep) {
|
|
@@ -603,6 +596,7 @@ ${formatStreamError(translatedError)}`
|
|
|
603
596
|
}
|
|
604
597
|
|
|
605
598
|
// src/assistant/bridge.ts
|
|
599
|
+
import { createSlackAssistantThreadContextStore } from "@cuylabs/channel-slack/assistant";
|
|
606
600
|
function createSlackAssistantBridge(options) {
|
|
607
601
|
if (!options.source || typeof options.source.chat !== "function") {
|
|
608
602
|
throw new Error(
|
|
@@ -616,8 +610,8 @@ function createSlackAssistantBridge(options) {
|
|
|
616
610
|
}
|
|
617
611
|
const sessionStrategy = options.sessionStrategy ?? "thread-aware";
|
|
618
612
|
const feedbackConfig = options.feedback === false ? void 0 : options.feedback ?? {};
|
|
619
|
-
const feedbackBlock = feedbackConfig ?
|
|
620
|
-
const feedbackActionId = feedbackConfig?.actionId ??
|
|
613
|
+
const feedbackBlock = feedbackConfig ? createSlackFeedbackBlock(feedbackConfig) : void 0;
|
|
614
|
+
const feedbackActionId = feedbackConfig?.actionId ?? SLACK_FEEDBACK_ACTION_ID;
|
|
621
615
|
const threadStarted = createThreadStartedHandler(options);
|
|
622
616
|
const threadContextChanged = createThreadContextChangedHandler();
|
|
623
617
|
const threadContextStore = options.threadContextStore ?? createSlackAssistantThreadContextStore();
|
|
@@ -639,7 +633,7 @@ function createSlackAssistantBridge(options) {
|
|
|
639
633
|
function install(app) {
|
|
640
634
|
app.assistant(assistant);
|
|
641
635
|
if (feedbackConfig) {
|
|
642
|
-
|
|
636
|
+
registerSlackFeedbackAction(app, {
|
|
643
637
|
...feedbackConfig,
|
|
644
638
|
resolveSessionId: (context) => resolveFeedbackSessionId(context, sessionStrategy),
|
|
645
639
|
onFeedback: feedbackConfig.onFeedback ?? (async (_ctx) => {
|
|
@@ -654,9 +648,15 @@ function createSlackAssistantBridge(options) {
|
|
|
654
648
|
};
|
|
655
649
|
}
|
|
656
650
|
|
|
651
|
+
// src/assistant/index.ts
|
|
652
|
+
import {
|
|
653
|
+
createSlackAssistantThreadContextStore as createSlackAssistantThreadContextStore2,
|
|
654
|
+
parseSlackMessageActivityFromMessageEvent as parseSlackMessageActivityFromMessageEvent2
|
|
655
|
+
} from "@cuylabs/channel-slack/assistant";
|
|
656
|
+
|
|
657
657
|
export {
|
|
658
|
-
parseSlackMessageActivityFromMessageEvent,
|
|
659
658
|
resolveAssistantSessionId,
|
|
660
|
-
|
|
661
|
-
|
|
659
|
+
createSlackAssistantBridge,
|
|
660
|
+
createSlackAssistantThreadContextStore2 as createSlackAssistantThreadContextStore,
|
|
661
|
+
parseSlackMessageActivityFromMessageEvent2 as parseSlackMessageActivityFromMessageEvent
|
|
662
662
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AgentContextFragmentInput, AgentContextFragmentBuildContext, AgentContextFragmentKind, AgentContextFragmentRole, AgentContextFragmentPlacement, AgentContextFragmentLifetime, AgentContextFragmentBudgetBehavior, AgentMiddleware } from '@cuylabs/agent-core';
|
|
2
|
+
import { SlackAmbientTurnContext } from '@cuylabs/channel-slack/core';
|
|
3
|
+
|
|
4
|
+
declare const DEFAULT_SLACK_CONTEXT_FRAGMENT_KEY = "slackContextFragment";
|
|
5
|
+
interface SlackContextFragmentPayload extends Partial<Pick<AgentContextFragmentInput, "budgetBehavior" | "dedupeKey" | "kind" | "lifetime" | "maxChars" | "metadata" | "placement" | "role" | "source" | "title">> {
|
|
6
|
+
content: string;
|
|
7
|
+
}
|
|
8
|
+
interface SlackContextFragmentResolverContext {
|
|
9
|
+
slack: Readonly<SlackAmbientTurnContext>;
|
|
10
|
+
step: AgentContextFragmentBuildContext;
|
|
11
|
+
}
|
|
12
|
+
type SlackContextFragmentResolver = (context: SlackContextFragmentResolverContext) => AgentContextFragmentInput | SlackContextFragmentPayload | string | undefined | Promise<AgentContextFragmentInput | SlackContextFragmentPayload | string | undefined>;
|
|
13
|
+
interface SlackContextFragmentMiddlewareOptions {
|
|
14
|
+
name?: string;
|
|
15
|
+
contextKey?: string;
|
|
16
|
+
resolve?: SlackContextFragmentResolver;
|
|
17
|
+
kind?: AgentContextFragmentKind;
|
|
18
|
+
role?: AgentContextFragmentRole;
|
|
19
|
+
placement?: AgentContextFragmentPlacement;
|
|
20
|
+
lifetime?: AgentContextFragmentLifetime;
|
|
21
|
+
title?: string;
|
|
22
|
+
source?: string;
|
|
23
|
+
budgetBehavior?: AgentContextFragmentBudgetBehavior;
|
|
24
|
+
maxChars?: number;
|
|
25
|
+
dedupeKey?: string | ((context: SlackContextFragmentResolverContext) => string | undefined);
|
|
26
|
+
metadata?: Record<string, unknown> | ((context: SlackContextFragmentResolverContext) => Record<string, unknown> | undefined);
|
|
27
|
+
}
|
|
28
|
+
declare function createSlackContextFragmentMiddleware(options?: SlackContextFragmentMiddlewareOptions): AgentMiddleware;
|
|
29
|
+
|
|
30
|
+
export { DEFAULT_SLACK_CONTEXT_FRAGMENT_KEY as D, type SlackContextFragmentMiddlewareOptions as S, type SlackContextFragmentPayload as a, type SlackContextFragmentResolver as b, type SlackContextFragmentResolverContext as c, createSlackContextFragmentMiddleware as d };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Server } from 'node:http';
|
|
2
2
|
import { Application } from 'express';
|
|
3
3
|
import { App, ExpressReceiver } from '@slack/bolt';
|
|
4
|
-
import { CreateSlackBoltAppOptions
|
|
4
|
+
import { CreateSlackBoltAppOptions } from '@cuylabs/channel-slack/transports/http';
|
|
5
|
+
import { SlackDirectAuthOptions, SlackDirectAuthMode } from '@cuylabs/channel-slack/auth';
|
|
5
6
|
import { C as CreateSlackAssistantBridgeOptions, b as SlackAssistantFeedbackConfig, S as SlackAssistantBridge } from './options-Uf-qmQKN.js';
|
|
6
7
|
import { SlackFeedbackHandler } from '@cuylabs/channel-slack/feedback';
|
|
7
8
|
import '@cuylabs/agent-core';
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mountSlackAssistantAgent
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-DHPD4XH5.js";
|
|
8
|
-
import "./chunk-ANIZ5NT4.js";
|
|
9
|
-
import "./chunk-I2KLQ2HA.js";
|
|
3
|
+
} from "./chunk-5NQYLOAW.js";
|
|
4
|
+
import "./chunk-ZDVD46RT.js";
|
|
5
|
+
import "./chunk-ELR6MQD7.js";
|
|
6
|
+
import "./chunk-NOVWLAVP.js";
|
|
10
7
|
export {
|
|
11
8
|
mountSlackAssistantAgent
|
|
12
9
|
};
|