@cuylabs/channel-slack-agent-core 0.6.0 → 0.7.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 +7 -0
- package/dist/adapter/index.d.ts +6 -3
- package/dist/adapter/index.js +2 -2
- package/dist/{adapter-Cmd2C90g.d.ts → adapter-B3CI611y.d.ts} +1 -1
- package/dist/app-surface.d.ts +13 -3
- package/dist/app-surface.js +4 -4
- package/dist/app.d.ts +7 -3
- package/dist/app.js +5 -5
- package/dist/artifacts/index.d.ts +57 -0
- package/dist/artifacts/index.js +6 -0
- package/dist/assistant/index.d.ts +5 -3
- package/dist/assistant/index.js +2 -2
- package/dist/{chunk-FNT4TXNQ.js → chunk-76SRS54H.js} +1 -1
- package/dist/{chunk-P7KK5GQG.js → chunk-7DUO5BMW.js} +11 -2
- package/dist/chunk-C7CHMYV6.js +226 -0
- package/dist/{chunk-5NQYLOAW.js → chunk-DJPKRKGP.js} +1 -1
- package/dist/{chunk-TIQGJ52F.js → chunk-FQWFB54C.js} +14 -2
- package/dist/{chunk-ZDVD46RT.js → chunk-MGBNGG4D.js} +23 -1
- package/dist/chunk-NNCVHQC4.js +94 -0
- package/dist/{chunk-VCXPNQRB.js → chunk-TCNJY7QA.js} +1 -1
- package/dist/{chunk-NOVWLAVP.js → chunk-TMADMHBN.js} +209 -20
- package/dist/{chunk-QEJ7TAZJ.js → chunk-VMVQIDNR.js} +2 -2
- package/dist/{chunk-J6CW2RGO.js → chunk-X7ILLZZP.js} +359 -2
- package/dist/express-assistant.d.ts +4 -2
- package/dist/express-assistant.js +3 -3
- package/dist/express.d.ts +5 -2
- package/dist/express.js +3 -3
- package/dist/history/index.d.ts +7 -3
- package/dist/index.d.ts +12 -6
- package/dist/index.js +28 -10
- package/dist/interactive/index.d.ts +43 -2
- package/dist/interactive/index.js +9 -3
- package/dist/{options-C7OYeNR-.d.ts → options-BcDReOJv.d.ts} +48 -0
- package/dist/{options-Uf-qmQKN.d.ts → options-CdqBABcM.d.ts} +26 -1
- package/dist/shared/index.d.ts +20 -6
- package/dist/shared/index.js +1 -1
- package/dist/socket.d.ts +7 -3
- package/dist/socket.js +5 -5
- package/dist/{types-BqRzb_Cd.d.ts → types-CRWzJB5G.d.ts} +35 -0
- package/dist/types-CiwGU6zC.d.ts +56 -0
- package/dist/views/index.d.ts +8 -0
- package/dist/views/index.js +10 -0
- package/docs/README.md +7 -0
- package/docs/concepts/final-response-artifacts.md +39 -0
- package/docs/concepts/interactive-requests.md +43 -0
- package/docs/concepts/tool-task-rendering.md +46 -0
- package/docs/concepts/view-workflows.md +52 -0
- package/docs/reference/exports.md +18 -16
- package/package.json +14 -4
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// src/artifacts/final-response.ts
|
|
2
|
+
import {
|
|
3
|
+
publishSlackCanvasArtifact,
|
|
4
|
+
publishSlackTextArtifact
|
|
5
|
+
} from "@cuylabs/channel-slack/artifacts";
|
|
6
|
+
var DEFAULT_MIN_CHARACTERS = 4e3;
|
|
7
|
+
var DEFAULT_TITLE = "Agent response";
|
|
8
|
+
function createSlackFinalResponseArtifactPublisher({
|
|
9
|
+
minCharacters = DEFAULT_MIN_CHARACTERS,
|
|
10
|
+
title = DEFAULT_TITLE,
|
|
11
|
+
summary,
|
|
12
|
+
channelCanvas = true,
|
|
13
|
+
fallback = "file",
|
|
14
|
+
onPublished,
|
|
15
|
+
onError
|
|
16
|
+
} = {}) {
|
|
17
|
+
const configuredThreshold = Math.floor(minCharacters);
|
|
18
|
+
const threshold = Number.isFinite(configuredThreshold) && configuredThreshold > 0 ? configuredThreshold : DEFAULT_MIN_CHARACTERS;
|
|
19
|
+
return async (context) => {
|
|
20
|
+
const text = context.text.trim();
|
|
21
|
+
if (text.length < threshold) {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
const resolvedTitle = normalizeText(await resolveValue(title, context)) ?? DEFAULT_TITLE;
|
|
25
|
+
const resolvedSummary = normalizeText(await resolveValue(summary, context));
|
|
26
|
+
let lastError;
|
|
27
|
+
try {
|
|
28
|
+
const publication = await publishSlackCanvasArtifact({
|
|
29
|
+
client: context.client,
|
|
30
|
+
channelId: context.channelId,
|
|
31
|
+
...context.threadTs ? { threadTs: context.threadTs } : {},
|
|
32
|
+
artifact: {
|
|
33
|
+
kind: "canvas",
|
|
34
|
+
title: resolvedTitle,
|
|
35
|
+
markdown: text,
|
|
36
|
+
channelCanvas,
|
|
37
|
+
...resolvedSummary ? { summary: resolvedSummary } : {},
|
|
38
|
+
metadata: {
|
|
39
|
+
source: "slack-final-response",
|
|
40
|
+
characterCount: text.length
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const result = { publication };
|
|
45
|
+
await onPublished?.(result, context);
|
|
46
|
+
return result;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
lastError = error;
|
|
49
|
+
}
|
|
50
|
+
if (fallback === "file") {
|
|
51
|
+
try {
|
|
52
|
+
const publication = await publishSlackTextArtifact({
|
|
53
|
+
client: context.client,
|
|
54
|
+
channelId: context.channelId,
|
|
55
|
+
...context.threadTs ? { threadTs: context.threadTs } : {},
|
|
56
|
+
artifact: {
|
|
57
|
+
kind: "text",
|
|
58
|
+
title: resolvedTitle,
|
|
59
|
+
text,
|
|
60
|
+
filename: filenameFromTitle(resolvedTitle),
|
|
61
|
+
...resolvedSummary ? { summary: resolvedSummary } : {},
|
|
62
|
+
metadata: {
|
|
63
|
+
source: "slack-final-response",
|
|
64
|
+
characterCount: text.length,
|
|
65
|
+
canvasFallback: true
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const result = { publication };
|
|
70
|
+
await onPublished?.(result, context);
|
|
71
|
+
return result;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
lastError = error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
await onError?.(lastError, context);
|
|
77
|
+
return void 0;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function resolveValue(value, context) {
|
|
81
|
+
return typeof value === "function" ? await value(context) : value;
|
|
82
|
+
}
|
|
83
|
+
function normalizeText(value) {
|
|
84
|
+
const trimmed = value?.trim();
|
|
85
|
+
return trimmed ? trimmed : void 0;
|
|
86
|
+
}
|
|
87
|
+
function filenameFromTitle(title) {
|
|
88
|
+
const slug = title.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
89
|
+
return `${slug || "agent-response"}.txt`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export {
|
|
93
|
+
createSlackFinalResponseArtifactPublisher
|
|
94
|
+
};
|
|
@@ -21,6 +21,10 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
21
21
|
let chatStreamAppendDisabled = false;
|
|
22
22
|
let chatStreamOverflowed = false;
|
|
23
23
|
let msgTooLongFallbackPosted = false;
|
|
24
|
+
let finalResponseStreamTextSuppressed = false;
|
|
25
|
+
let chatStreamContinuationNoticeAppended = false;
|
|
26
|
+
let progressiveContinuationNoticeShown = false;
|
|
27
|
+
let finalResponseArtifactContinuationNotice;
|
|
24
28
|
let statusLabel = "";
|
|
25
29
|
let lastNotifiedStatus = "";
|
|
26
30
|
let lastProgressiveUpdateAtMs;
|
|
@@ -54,15 +58,21 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
54
58
|
}
|
|
55
59
|
async function updateIfNeeded(force = false) {
|
|
56
60
|
if (!postedTs || !postedChannel || !fullResponse) return;
|
|
57
|
-
const
|
|
61
|
+
const replacingWithArtifact = shouldReplaceFinalResponseWithArtifact();
|
|
62
|
+
const replacementTextSuppressed = replacingWithArtifact && hasCrossedFinalResponseArtifactStreamThreshold();
|
|
63
|
+
if (replacementTextSuppressed && progressiveContinuationNoticeShown && !force) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const shouldUpdate = force || !replacementTextSuppressed && fullResponse.length - lastUpdateLength >= options.progressiveUpdateThreshold && shouldIssueProgressiveUpdate();
|
|
58
67
|
if (shouldUpdate) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
postedTs,
|
|
62
|
-
options.formatMessageText(fullResponse)
|
|
63
|
-
);
|
|
68
|
+
const text = formatProgressiveResponseText();
|
|
69
|
+
await sink.updateMessage(postedChannel, postedTs, text);
|
|
64
70
|
lastUpdateLength = fullResponse.length;
|
|
65
71
|
lastProgressiveUpdateAtMs = Date.now();
|
|
72
|
+
if (replacementTextSuppressed) {
|
|
73
|
+
progressiveContinuationNoticeShown = true;
|
|
74
|
+
finalResponseStreamTextSuppressed = true;
|
|
75
|
+
}
|
|
66
76
|
}
|
|
67
77
|
}
|
|
68
78
|
function shouldIssueProgressiveUpdate() {
|
|
@@ -74,6 +84,41 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
74
84
|
}
|
|
75
85
|
return Date.now() - lastProgressiveUpdateAtMs >= options.progressiveUpdateIntervalMs;
|
|
76
86
|
}
|
|
87
|
+
function shouldReplaceFinalResponseWithArtifact() {
|
|
88
|
+
return Boolean(
|
|
89
|
+
options.publishFinalResponseArtifact && options.finalResponseArtifactMode === "replace"
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
function finalResponseArtifactStreamThreshold() {
|
|
93
|
+
return Math.max(1, options.finalResponseArtifactStreamThreshold ?? 4e3);
|
|
94
|
+
}
|
|
95
|
+
function hasCrossedFinalResponseArtifactStreamThreshold() {
|
|
96
|
+
return fullResponse.length > finalResponseArtifactStreamThreshold();
|
|
97
|
+
}
|
|
98
|
+
function getFinalResponseArtifactContinuationNotice() {
|
|
99
|
+
if (finalResponseArtifactContinuationNotice !== void 0) {
|
|
100
|
+
return finalResponseArtifactContinuationNotice;
|
|
101
|
+
}
|
|
102
|
+
const notice = options.formatFinalResponseArtifactContinuationNotice?.({
|
|
103
|
+
text: fullResponse,
|
|
104
|
+
formattedText: options.formatMessageText(fullResponse)
|
|
105
|
+
});
|
|
106
|
+
finalResponseArtifactContinuationNotice = notice?.trim() ? notice : "";
|
|
107
|
+
return finalResponseArtifactContinuationNotice || void 0;
|
|
108
|
+
}
|
|
109
|
+
function formatTruncatedFinalResponseWithContinuationNotice() {
|
|
110
|
+
const threshold = finalResponseArtifactStreamThreshold();
|
|
111
|
+
const visibleText = fullResponse.slice(0, threshold).trimEnd();
|
|
112
|
+
const formattedText = options.formatMessageText(visibleText);
|
|
113
|
+
const notice = getFinalResponseArtifactContinuationNotice();
|
|
114
|
+
return notice ? `${formattedText}${notice}` : formattedText;
|
|
115
|
+
}
|
|
116
|
+
function formatProgressiveResponseText() {
|
|
117
|
+
if (shouldReplaceFinalResponseWithArtifact() && hasCrossedFinalResponseArtifactStreamThreshold()) {
|
|
118
|
+
return formatTruncatedFinalResponseWithContinuationNotice();
|
|
119
|
+
}
|
|
120
|
+
return options.formatMessageText(fullResponse);
|
|
121
|
+
}
|
|
77
122
|
function ensureChatStream() {
|
|
78
123
|
if (chatStream) {
|
|
79
124
|
return chatStream;
|
|
@@ -99,6 +144,16 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
99
144
|
function formatToolTitle(toolName) {
|
|
100
145
|
return options.formatToolTitle?.(toolName) ?? toolName;
|
|
101
146
|
}
|
|
147
|
+
function formatToolResultOutput(event) {
|
|
148
|
+
const formatted = options.formatToolResultOutput?.(event);
|
|
149
|
+
if (formatted === null) {
|
|
150
|
+
return void 0;
|
|
151
|
+
}
|
|
152
|
+
if (formatted !== void 0) {
|
|
153
|
+
return normalizeStreamChunkOutput(formatted, { truncate: false });
|
|
154
|
+
}
|
|
155
|
+
return formatStreamChunkOutput(event.result);
|
|
156
|
+
}
|
|
102
157
|
function subAgentTaskId(dispatchId) {
|
|
103
158
|
return `subagent:${dispatchId}`;
|
|
104
159
|
}
|
|
@@ -166,6 +221,38 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
166
221
|
}
|
|
167
222
|
await appendToChatStream({ markdown_text: formatted });
|
|
168
223
|
}
|
|
224
|
+
async function appendFinalResponseTextToChatStream(text, previousLength) {
|
|
225
|
+
if (!shouldReplaceFinalResponseWithArtifact()) {
|
|
226
|
+
await appendChatStreamText(text);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
const threshold = finalResponseArtifactStreamThreshold();
|
|
230
|
+
if (previousLength >= threshold) {
|
|
231
|
+
finalResponseStreamTextSuppressed = true;
|
|
232
|
+
await appendFinalResponseArtifactContinuationNotice();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const remainingVisibleCharacters = threshold - previousLength;
|
|
236
|
+
const visibleText = text.slice(0, remainingVisibleCharacters);
|
|
237
|
+
if (visibleText) {
|
|
238
|
+
await appendChatStreamText(visibleText);
|
|
239
|
+
}
|
|
240
|
+
if (text.length > remainingVisibleCharacters) {
|
|
241
|
+
finalResponseStreamTextSuppressed = true;
|
|
242
|
+
await appendFinalResponseArtifactContinuationNotice();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
async function appendFinalResponseArtifactContinuationNotice() {
|
|
246
|
+
if (chatStreamContinuationNoticeAppended) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const notice = getFinalResponseArtifactContinuationNotice();
|
|
250
|
+
if (!notice) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
chatStreamContinuationNoticeAppended = true;
|
|
254
|
+
await appendToChatStream({ markdown_text: notice });
|
|
255
|
+
}
|
|
169
256
|
async function appendChatStreamChunk(chunk) {
|
|
170
257
|
if (chatStreamAppendDisabled) {
|
|
171
258
|
return;
|
|
@@ -314,6 +401,47 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
314
401
|
await postMsgTooLongFallback(fallbackText ?? markdownText);
|
|
315
402
|
}
|
|
316
403
|
}
|
|
404
|
+
async function publishFinalResponseArtifact(text, formattedText) {
|
|
405
|
+
if (!options.publishFinalResponseArtifact) {
|
|
406
|
+
return void 0;
|
|
407
|
+
}
|
|
408
|
+
const client = sink.artifactClient;
|
|
409
|
+
const channelId = sink.artifactTarget?.channelId;
|
|
410
|
+
if (!text || !client || !channelId) {
|
|
411
|
+
return void 0;
|
|
412
|
+
}
|
|
413
|
+
const context = {
|
|
414
|
+
text,
|
|
415
|
+
formattedText,
|
|
416
|
+
client,
|
|
417
|
+
channelId,
|
|
418
|
+
...sink.artifactTarget?.threadTs ? { threadTs: sink.artifactTarget.threadTs } : {}
|
|
419
|
+
};
|
|
420
|
+
try {
|
|
421
|
+
const result = await options.publishFinalResponseArtifact(context);
|
|
422
|
+
return result ? { result, context } : void 0;
|
|
423
|
+
} catch (error) {
|
|
424
|
+
try {
|
|
425
|
+
await options.onFinalResponseArtifactError?.(error, context);
|
|
426
|
+
} catch {
|
|
427
|
+
}
|
|
428
|
+
return void 0;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
function formatFinalResponseArtifactMessage(result, context) {
|
|
432
|
+
const message = options.formatFinalResponseArtifactMessage?.(result, context)?.trim();
|
|
433
|
+
if (message) {
|
|
434
|
+
return message;
|
|
435
|
+
}
|
|
436
|
+
const title = result.publication.artifact.title.trim() || "Agent response";
|
|
437
|
+
if (result.publication.method === "canvas") {
|
|
438
|
+
return `I created a Slack Canvas for the full response: ${title}`;
|
|
439
|
+
}
|
|
440
|
+
if (result.publication.method === "file") {
|
|
441
|
+
return `I uploaded the full response as a file: ${title}`;
|
|
442
|
+
}
|
|
443
|
+
return `I published the full response as a Slack artifact: ${title}`;
|
|
444
|
+
}
|
|
317
445
|
try {
|
|
318
446
|
for await (const event of events) {
|
|
319
447
|
switch (event.type) {
|
|
@@ -323,19 +451,25 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
323
451
|
await ensurePlaceholder();
|
|
324
452
|
}
|
|
325
453
|
break;
|
|
326
|
-
case "text-delta":
|
|
454
|
+
case "text-delta": {
|
|
327
455
|
if (statusLabel) {
|
|
328
456
|
statusLabel = "";
|
|
329
457
|
await notifyStatus("", event);
|
|
330
458
|
}
|
|
459
|
+
const previousResponseLength = fullResponse.length;
|
|
331
460
|
fullResponse += event.text;
|
|
332
461
|
if (options.streamingMode === "chat-stream") {
|
|
333
|
-
await
|
|
462
|
+
await appendFinalResponseTextToChatStream(
|
|
463
|
+
event.text,
|
|
464
|
+
previousResponseLength
|
|
465
|
+
);
|
|
334
466
|
} else if (options.streamingMode === "progressive") {
|
|
335
467
|
await ensurePlaceholder();
|
|
336
|
-
|
|
468
|
+
const crossedReplacementThreshold = shouldReplaceFinalResponseWithArtifact() && previousResponseLength <= finalResponseArtifactStreamThreshold() && hasCrossedFinalResponseArtifactStreamThreshold();
|
|
469
|
+
await updateIfNeeded(crossedReplacementThreshold);
|
|
337
470
|
}
|
|
338
471
|
break;
|
|
472
|
+
}
|
|
339
473
|
case "text-end":
|
|
340
474
|
break;
|
|
341
475
|
// ── Reasoning ───────────────────────────────────────────────────
|
|
@@ -390,7 +524,7 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
390
524
|
id: event.toolCallId,
|
|
391
525
|
title: toolTitle,
|
|
392
526
|
status: "complete",
|
|
393
|
-
output:
|
|
527
|
+
output: formatToolResultOutput(event)
|
|
394
528
|
});
|
|
395
529
|
}
|
|
396
530
|
break;
|
|
@@ -529,7 +663,7 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
529
663
|
id: subAgentToolTaskId(event.dispatchId, childEvent.toolCallId),
|
|
530
664
|
title: `${roleTitle}: ${toolTitle}`,
|
|
531
665
|
status: "complete",
|
|
532
|
-
output:
|
|
666
|
+
output: formatToolResultOutput(childEvent)
|
|
533
667
|
});
|
|
534
668
|
} else if (childEvent.type === "tool-error") {
|
|
535
669
|
const toolTitle = formatToolTitle(childEvent.toolName);
|
|
@@ -594,15 +728,20 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
594
728
|
}
|
|
595
729
|
break;
|
|
596
730
|
// ── Completion ──────────────────────────────────────────────────
|
|
597
|
-
case "complete":
|
|
731
|
+
case "complete": {
|
|
598
732
|
if (!fullResponse && event.output) {
|
|
733
|
+
const previousResponseLength = fullResponse.length;
|
|
599
734
|
fullResponse = event.output;
|
|
600
735
|
if (options.streamingMode === "chat-stream") {
|
|
601
|
-
await
|
|
736
|
+
await appendFinalResponseTextToChatStream(
|
|
737
|
+
event.output,
|
|
738
|
+
previousResponseLength
|
|
739
|
+
);
|
|
602
740
|
}
|
|
603
741
|
}
|
|
604
742
|
await finalizeOpenSubAgentTasks();
|
|
605
743
|
break;
|
|
744
|
+
}
|
|
606
745
|
// ── Interactive requests (unsupported in Slack transport) ────────
|
|
607
746
|
case "approval-request": {
|
|
608
747
|
const msg = options.formatApprovalRequired(event.request);
|
|
@@ -664,17 +803,32 @@ async function bridgeAgentEventsToSlack(events, sink, options) {
|
|
|
664
803
|
break;
|
|
665
804
|
}
|
|
666
805
|
}
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
806
|
+
const rawFinalText = fullResponse.trim();
|
|
807
|
+
let finalText = rawFinalText ? options.formatMessageText(rawFinalText) : "_No response_";
|
|
808
|
+
let publishedArtifact;
|
|
809
|
+
if (shouldReplaceFinalResponseWithArtifact()) {
|
|
810
|
+
publishedArtifact = await publishFinalResponseArtifact(
|
|
811
|
+
rawFinalText,
|
|
671
812
|
finalText
|
|
672
813
|
);
|
|
814
|
+
if (publishedArtifact) {
|
|
815
|
+
finalText = formatFinalResponseArtifactMessage(
|
|
816
|
+
publishedArtifact.result,
|
|
817
|
+
publishedArtifact.context
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (options.streamingMode === "chat-stream") {
|
|
822
|
+
const chatStreamFinalText = publishedArtifact || !rawFinalText || finalResponseStreamTextSuppressed ? finalText : void 0;
|
|
823
|
+
await stopChatStream(chatStreamFinalText, finalText);
|
|
673
824
|
} else if (postedTs && postedChannel) {
|
|
674
825
|
await sink.updateMessage(postedChannel, postedTs, finalText);
|
|
675
826
|
} else {
|
|
676
827
|
await sink.postMessage(finalText);
|
|
677
828
|
}
|
|
829
|
+
if (!shouldReplaceFinalResponseWithArtifact()) {
|
|
830
|
+
await publishFinalResponseArtifact(rawFinalText, finalText);
|
|
831
|
+
}
|
|
678
832
|
return fullResponse;
|
|
679
833
|
} catch (error) {
|
|
680
834
|
if (error instanceof UnsupportedSlackInteractiveRequestError) {
|
|
@@ -702,11 +856,14 @@ function formatStreamChunkOutput(value) {
|
|
|
702
856
|
return void 0;
|
|
703
857
|
}
|
|
704
858
|
const text = typeof value === "string" ? value : safeJsonStringify(value) ?? String(value);
|
|
859
|
+
return normalizeStreamChunkOutput(text, { truncate: true });
|
|
860
|
+
}
|
|
861
|
+
function normalizeStreamChunkOutput(text, options) {
|
|
705
862
|
const normalized = text.trim();
|
|
706
863
|
if (!normalized) {
|
|
707
864
|
return void 0;
|
|
708
865
|
}
|
|
709
|
-
return normalized.length > 500 ? `${normalized.slice(0, 497).trimEnd()}...` : normalized;
|
|
866
|
+
return options.truncate && normalized.length > 500 ? `${normalized.slice(0, 497).trimEnd()}...` : normalized;
|
|
710
867
|
}
|
|
711
868
|
function isSlackMsgTooLongError(error) {
|
|
712
869
|
if (typeof error === "object" && error !== null) {
|
|
@@ -764,7 +921,20 @@ var DEFAULT_OPTIONS = {
|
|
|
764
921
|
maxTaskUpdateFieldChars: 500,
|
|
765
922
|
interactiveMode: "message-and-error",
|
|
766
923
|
formatApprovalRequired: (request) => `This turn requires approval for "${request.tool}", but in-channel approval is not configured for this Slack host.`,
|
|
767
|
-
formatHumanInputRequired: (request) => `This turn is waiting for input: ${request.title}. In-channel human input is not configured for this Slack host
|
|
924
|
+
formatHumanInputRequired: (request) => `This turn is waiting for input: ${request.title}. In-channel human input is not configured for this Slack host.`,
|
|
925
|
+
finalResponseArtifactMode: "supplemental",
|
|
926
|
+
finalResponseArtifactStreamThreshold: 4e3,
|
|
927
|
+
formatFinalResponseArtifactContinuationNotice: () => "\n\nFull response is long. I will publish the complete answer as a Slack artifact when it finishes.",
|
|
928
|
+
formatFinalResponseArtifactMessage: (result) => {
|
|
929
|
+
const title = result.publication.artifact.title.trim() || "Agent response";
|
|
930
|
+
if (result.publication.method === "canvas") {
|
|
931
|
+
return `I created a Slack Canvas for the full response: ${title}`;
|
|
932
|
+
}
|
|
933
|
+
if (result.publication.method === "file") {
|
|
934
|
+
return `I uploaded the full response as a file: ${title}`;
|
|
935
|
+
}
|
|
936
|
+
return `I published the full response as a Slack artifact: ${title}`;
|
|
937
|
+
}
|
|
768
938
|
};
|
|
769
939
|
function resolveSlackEventBridgeOptions(partial) {
|
|
770
940
|
return {
|
|
@@ -775,6 +945,7 @@ function resolveSlackEventBridgeOptions(partial) {
|
|
|
775
945
|
formatToolTitle: partial.formatToolTitle ?? DEFAULT_OPTIONS.formatToolTitle,
|
|
776
946
|
formatToolUpdate: partial.formatToolUpdate ?? DEFAULT_OPTIONS.formatToolUpdate,
|
|
777
947
|
...partial.formatToolDetails ? { formatToolDetails: partial.formatToolDetails } : {},
|
|
948
|
+
...partial.formatToolResultOutput ? { formatToolResultOutput: partial.formatToolResultOutput } : {},
|
|
778
949
|
formatToolError: partial.formatToolError ?? DEFAULT_OPTIONS.formatToolError,
|
|
779
950
|
formatReasoningUpdate: partial.formatReasoningUpdate ?? DEFAULT_OPTIONS.formatReasoningUpdate,
|
|
780
951
|
formatMessageText: partial.formatMessageText ?? DEFAULT_OPTIONS.formatMessageText,
|
|
@@ -799,7 +970,16 @@ function resolveSlackEventBridgeOptions(partial) {
|
|
|
799
970
|
formatApprovalRequired: partial.formatApprovalRequired ?? DEFAULT_OPTIONS.formatApprovalRequired,
|
|
800
971
|
formatHumanInputRequired: partial.formatHumanInputRequired ?? DEFAULT_OPTIONS.formatHumanInputRequired,
|
|
801
972
|
...partial.onStatusChange ? { onStatusChange: partial.onStatusChange } : {},
|
|
802
|
-
...partial.chatStreamFinalArgs ? { chatStreamFinalArgs: partial.chatStreamFinalArgs } : {}
|
|
973
|
+
...partial.chatStreamFinalArgs ? { chatStreamFinalArgs: partial.chatStreamFinalArgs } : {},
|
|
974
|
+
...partial.publishFinalResponseArtifact ? { publishFinalResponseArtifact: partial.publishFinalResponseArtifact } : {},
|
|
975
|
+
finalResponseArtifactMode: partial.finalResponseArtifactMode ?? DEFAULT_OPTIONS.finalResponseArtifactMode,
|
|
976
|
+
finalResponseArtifactStreamThreshold: resolvePositiveInteger(
|
|
977
|
+
partial.finalResponseArtifactStreamThreshold,
|
|
978
|
+
DEFAULT_OPTIONS.finalResponseArtifactStreamThreshold ?? 4e3
|
|
979
|
+
),
|
|
980
|
+
formatFinalResponseArtifactContinuationNotice: partial.formatFinalResponseArtifactContinuationNotice ?? DEFAULT_OPTIONS.formatFinalResponseArtifactContinuationNotice,
|
|
981
|
+
formatFinalResponseArtifactMessage: partial.formatFinalResponseArtifactMessage ?? DEFAULT_OPTIONS.formatFinalResponseArtifactMessage,
|
|
982
|
+
...partial.onFinalResponseArtifactError ? { onFinalResponseArtifactError: partial.onFinalResponseArtifactError } : {}
|
|
803
983
|
};
|
|
804
984
|
}
|
|
805
985
|
function resolveNonNegativeInteger(value, fallback) {
|
|
@@ -811,6 +991,15 @@ function resolveNonNegativeInteger(value, fallback) {
|
|
|
811
991
|
}
|
|
812
992
|
return Math.floor(value);
|
|
813
993
|
}
|
|
994
|
+
function resolvePositiveInteger(value, fallback) {
|
|
995
|
+
if (value === void 0) {
|
|
996
|
+
return fallback;
|
|
997
|
+
}
|
|
998
|
+
if (!Number.isFinite(value) || value < 1) {
|
|
999
|
+
return fallback;
|
|
1000
|
+
}
|
|
1001
|
+
return Math.floor(value);
|
|
1002
|
+
}
|
|
814
1003
|
|
|
815
1004
|
export {
|
|
816
1005
|
UnsupportedSlackInteractiveRequestError,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
installSlackAgentAppSurface
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7DUO5BMW.js";
|
|
4
4
|
import {
|
|
5
5
|
createSlackAssistantBridge
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MGBNGG4D.js";
|
|
7
7
|
|
|
8
8
|
// src/socket.ts
|
|
9
9
|
import { createSlackSocketBoltApp } from "@cuylabs/channel-slack/transports/socket";
|