@cuylabs/channel-slack-agent-core 0.5.1 → 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.
Files changed (89) hide show
  1. package/README.md +20 -39
  2. package/dist/{adapter.d.ts → adapter/index.d.ts} +7 -5
  3. package/dist/adapter/index.js +9 -0
  4. package/dist/{adapter-Cmd2C90g.d.ts → adapter-B3CI611y.d.ts} +1 -1
  5. package/dist/app-surface.d.ts +13 -3
  6. package/dist/app-surface.js +5 -7
  7. package/dist/app.d.ts +9 -4
  8. package/dist/app.js +6 -9
  9. package/dist/artifacts/index.d.ts +57 -0
  10. package/dist/artifacts/index.js +6 -0
  11. package/dist/{assistant.d.ts → assistant/index.d.ts} +6 -4
  12. package/dist/{assistant.js → assistant/index.js} +3 -5
  13. package/dist/{chunk-CYEBGC6G.js → chunk-76SRS54H.js} +5 -5
  14. package/dist/{chunk-M64Z6TYL.js → chunk-7DUO5BMW.js} +16 -6
  15. package/dist/{chunk-NIPAN4KA.js → chunk-A2PLAVW6.js} +2 -3
  16. package/dist/chunk-C7CHMYV6.js +226 -0
  17. package/dist/chunk-C7VSW4ZM.js +548 -0
  18. package/dist/{chunk-JMLB7A2V.js → chunk-DJPKRKGP.js} +5 -5
  19. package/dist/chunk-ELR6MQD7.js +12 -0
  20. package/dist/{chunk-FDRQOG7Q.js → chunk-FQWFB54C.js} +26 -15
  21. package/dist/{chunk-BFUPAJON.js → chunk-MGBNGG4D.js} +59 -37
  22. package/dist/chunk-NNCVHQC4.js +94 -0
  23. package/dist/chunk-P7PFQ3SQ.js +396 -0
  24. package/dist/{chunk-WO4BJMF3.js → chunk-TCNJY7QA.js} +5 -5
  25. package/dist/{chunk-DHPD4XH5.js → chunk-TMADMHBN.js} +210 -29
  26. package/dist/{chunk-IWUYIAY5.js → chunk-VMVQIDNR.js} +5 -7
  27. package/dist/{chunk-IXY3BXU5.js → chunk-X7ILLZZP.js} +359 -2
  28. package/dist/context-fragments-CQEDcjYR.d.ts +30 -0
  29. package/dist/express-assistant.d.ts +6 -3
  30. package/dist/express-assistant.js +4 -7
  31. package/dist/express.d.ts +7 -3
  32. package/dist/express.js +3 -6
  33. package/dist/feedback/index.d.ts +1 -0
  34. package/dist/feedback/index.js +10 -0
  35. package/dist/history/index.d.ts +61 -0
  36. package/dist/history/index.js +8 -0
  37. package/dist/index.d.ts +23 -16
  38. package/dist/index.js +81 -160
  39. package/dist/interactive/index.d.ts +71 -0
  40. package/dist/{interactive.js → interactive/index.js} +9 -4
  41. package/dist/mcp.js +0 -1
  42. package/dist/{options-C7OYeNR-.d.ts → options-BcDReOJv.d.ts} +48 -0
  43. package/dist/{options-Uf-qmQKN.d.ts → options-CdqBABcM.d.ts} +26 -1
  44. package/dist/{shared.d.ts → shared/index.d.ts} +24 -36
  45. package/dist/{shared.js → shared/index.js} +2 -6
  46. package/dist/socket.d.ts +9 -4
  47. package/dist/socket.js +6 -9
  48. package/dist/source/index.d.ts +154 -0
  49. package/dist/source/index.js +38 -0
  50. package/dist/{types-BqRzb_Cd.d.ts → types-CRWzJB5G.d.ts} +35 -0
  51. package/dist/types-CiwGU6zC.d.ts +56 -0
  52. package/dist/views/index.d.ts +8 -0
  53. package/dist/views/index.js +10 -0
  54. package/docs/README.md +18 -0
  55. package/docs/concepts/final-response-artifacts.md +39 -0
  56. package/docs/concepts/interactive-requests.md +43 -0
  57. package/docs/concepts/tool-task-rendering.md +46 -0
  58. package/docs/concepts/view-workflows.md +52 -0
  59. package/docs/reference/boundary.md +22 -0
  60. package/docs/reference/exports.md +26 -0
  61. package/package.json +36 -50
  62. package/dist/adapter.js +0 -13
  63. package/dist/bolt.d.ts +0 -8
  64. package/dist/bolt.js +0 -10
  65. package/dist/chunk-2SUAW6MV.js +0 -12
  66. package/dist/chunk-645NNJIM.js +0 -12
  67. package/dist/chunk-ANIZ5NT4.js +0 -12
  68. package/dist/chunk-GNXWTKQ6.js +0 -48
  69. package/dist/chunk-HFT2FXJP.js +0 -12
  70. package/dist/chunk-I2KLQ2HA.js +0 -22
  71. package/dist/chunk-K2E6A377.js +0 -12
  72. package/dist/chunk-NDVXBI7Z.js +0 -12
  73. package/dist/chunk-PX4RGO3N.js +0 -12
  74. package/dist/chunk-VHGV66M7.js +0 -12
  75. package/dist/diagnostics.d.ts +0 -1
  76. package/dist/diagnostics.js +0 -10
  77. package/dist/feedback.d.ts +0 -1
  78. package/dist/feedback.js +0 -10
  79. package/dist/history.d.ts +0 -1
  80. package/dist/history.js +0 -10
  81. package/dist/interactive.d.ts +0 -30
  82. package/dist/policy.d.ts +0 -1
  83. package/dist/policy.js +0 -10
  84. package/dist/setup.d.ts +0 -1
  85. package/dist/setup.js +0 -10
  86. package/dist/targets.d.ts +0 -1
  87. package/dist/targets.js +0 -10
  88. package/dist/users.d.ts +0 -1
  89. package/dist/users.js +0 -10
@@ -0,0 +1,548 @@
1
+ // src/source/event-queue.ts
2
+ function coalesceSlackAgentEvents(previous, next) {
3
+ if (previous.type === "text-delta" && next.type === "text-delta") {
4
+ return {
5
+ type: "text-delta",
6
+ text: previous.text + next.text
7
+ };
8
+ }
9
+ return void 0;
10
+ }
11
+ function routeSlackAgentEvent({
12
+ event,
13
+ logger,
14
+ onRecord,
15
+ queue,
16
+ sequence,
17
+ state
18
+ }) {
19
+ if (sequence !== void 0) {
20
+ if (state.deliveredSequences.has(sequence)) {
21
+ logger?.debug?.("Skipping duplicate Slack agent event", {
22
+ eventType: event.type,
23
+ sequence,
24
+ sessionId: state.sessionId,
25
+ turnId: state.turnId
26
+ });
27
+ return false;
28
+ }
29
+ state.deliveredSequences.add(sequence);
30
+ }
31
+ onRecord?.(event, sequence);
32
+ if (!shouldQueueSlackAgentEvent({ event, logger, sequence, state })) {
33
+ return false;
34
+ }
35
+ queue.push(event, coalesceSlackAgentEvents);
36
+ return true;
37
+ }
38
+ function shouldQueueSlackAgentEvent({
39
+ event,
40
+ logger,
41
+ sequence,
42
+ state
43
+ }) {
44
+ const status = slackAgentEventStatusKey(event);
45
+ if (!status) {
46
+ if (event.type === "subagent-complete" || event.type === "subagent-error") {
47
+ state.lastQueuedStatusByKey.delete(`subagent:${event.dispatchId}`);
48
+ }
49
+ return true;
50
+ }
51
+ const previous = state.lastQueuedStatusByKey.get(status.key);
52
+ if (previous === status.status) {
53
+ logger?.debug?.("Skipping duplicate Slack status event", {
54
+ eventType: event.type,
55
+ sequence,
56
+ sessionId: state.sessionId,
57
+ status: status.status,
58
+ statusKey: status.key,
59
+ turnId: state.turnId
60
+ });
61
+ return false;
62
+ }
63
+ state.lastQueuedStatusByKey.set(status.key, status.status);
64
+ return true;
65
+ }
66
+ function slackAgentEventStatusKey(event) {
67
+ if (event.type === "status") {
68
+ return { key: "root", status: event.status };
69
+ }
70
+ if (event.type === "subagent-event" && event.event.type === "status") {
71
+ return {
72
+ key: `subagent:${event.dispatchId}`,
73
+ status: event.event.status
74
+ };
75
+ }
76
+ return void 0;
77
+ }
78
+
79
+ // src/source/responses.ts
80
+ async function* immediateSlackTextResponse(text) {
81
+ yield { type: "text-start" };
82
+ yield { type: "text-delta", text };
83
+ yield { type: "text-end" };
84
+ yield { type: "complete", output: text };
85
+ }
86
+ function isSlackCancelMessage(message) {
87
+ const normalized = message.trim().toLowerCase();
88
+ return /^(cancel|stop|abort|nevermind|never mind|discard|quit)\b[.!?]*$/.test(
89
+ normalized
90
+ );
91
+ }
92
+ function resolveSlackTypedApprovalAction(message) {
93
+ const normalized = message.trim().toLowerCase();
94
+ if (/^(allow|approve|approved|yes|y)\b[.!?]*$/.test(normalized)) {
95
+ return "allow";
96
+ }
97
+ if (/^(deny|denied|no|n)\b[.!?]*$/.test(normalized)) {
98
+ return "deny";
99
+ }
100
+ if (/^(remember|always|allow always|approve always)\b[.!?]*$/.test(normalized)) {
101
+ return "remember";
102
+ }
103
+ return void 0;
104
+ }
105
+ function isRunningAgentTurnError(error) {
106
+ return error instanceof Error && /already has a running turn/i.test(error.message);
107
+ }
108
+ function isAbortLikeError(error) {
109
+ if (error instanceof DOMException) {
110
+ return error.name === "AbortError";
111
+ }
112
+ if (error instanceof Error) {
113
+ return error.name === "AbortError" || /aborted/i.test(error.message);
114
+ }
115
+ return false;
116
+ }
117
+
118
+ // src/source/status-visibility.ts
119
+ function resolveSlackTurnStatusVisibilityOptions(options) {
120
+ return {
121
+ checkIntervalMs: Math.max(1, normalizeMs(options?.checkIntervalMs, 5e3)),
122
+ toolStaleWarningMs: normalizeMs(options?.toolStaleWarningMs, 0),
123
+ turnStaleWarningMs: normalizeMs(options?.turnStaleWarningMs, 0)
124
+ };
125
+ }
126
+ function shouldInspectSlackTurnStatusVisibility(options) {
127
+ return options.toolStaleWarningMs > 0 || options.turnStaleWarningMs > 0;
128
+ }
129
+ function recordSlackTurnActivity(state, event, nowMs = Date.now()) {
130
+ state.lastActivityAtMs = nowMs;
131
+ switch (event.type) {
132
+ case "text-start":
133
+ case "text-delta":
134
+ case "text-end":
135
+ state.phase = "streaming";
136
+ state.currentTool = void 0;
137
+ break;
138
+ case "reasoning-start":
139
+ case "reasoning-delta":
140
+ case "reasoning-end":
141
+ case "message":
142
+ case "step-start":
143
+ case "step-finish":
144
+ case "status":
145
+ case "turn-boundary":
146
+ if (!isSlackTerminalTurnPhase(state.phase)) {
147
+ state.phase = "reasoning";
148
+ }
149
+ break;
150
+ case "tool-start":
151
+ state.phase = "tool-running";
152
+ state.currentTool = {
153
+ startedAtMs: nowMs,
154
+ toolCallId: event.toolCallId,
155
+ toolName: event.toolName
156
+ };
157
+ break;
158
+ case "tool-result":
159
+ case "tool-error":
160
+ if (state.currentTool?.toolCallId === event.toolCallId) {
161
+ state.currentTool = void 0;
162
+ }
163
+ if (!isSlackTerminalTurnPhase(state.phase)) {
164
+ state.phase = "reasoning";
165
+ }
166
+ break;
167
+ case "approval-request":
168
+ state.currentTool = void 0;
169
+ state.phase = "waiting-approval";
170
+ break;
171
+ case "approval-resolved":
172
+ if (!isSlackTerminalTurnPhase(state.phase)) {
173
+ state.phase = "reasoning";
174
+ }
175
+ break;
176
+ case "human-input-request":
177
+ state.currentTool = void 0;
178
+ state.phase = "waiting-input";
179
+ break;
180
+ case "human-input-resolved":
181
+ if (!isSlackTerminalTurnPhase(state.phase)) {
182
+ state.phase = "reasoning";
183
+ }
184
+ break;
185
+ case "complete":
186
+ state.currentTool = void 0;
187
+ state.phase = "completed";
188
+ break;
189
+ case "error":
190
+ state.currentTool = void 0;
191
+ state.phase = "failed";
192
+ break;
193
+ default:
194
+ break;
195
+ }
196
+ }
197
+ function inspectSlackTurnStatusVisibility({
198
+ formatToolStaleStatus = defaultToolStaleStatus,
199
+ formatTurnStaleStatus = defaultTurnStaleStatus,
200
+ nowMs = Date.now(),
201
+ options,
202
+ state
203
+ }) {
204
+ if (isSlackTerminalTurnPhase(state.phase) || isSlackWaitingForHumanTurnPhase(state.phase)) {
205
+ return void 0;
206
+ }
207
+ if (state.currentTool && options.toolStaleWarningMs > 0) {
208
+ const elapsedMs = nowMs - state.currentTool.startedAtMs;
209
+ if (elapsedMs >= options.toolStaleWarningMs) {
210
+ return createSlackTurnStatusVisibilityWarning({
211
+ id: `tool:${state.currentTool.toolCallId}`,
212
+ message: formatToolStaleStatus(state.currentTool.toolName),
213
+ nowMs,
214
+ state,
215
+ thresholdMs: options.toolStaleWarningMs,
216
+ type: "tool"
217
+ });
218
+ }
219
+ }
220
+ if (options.turnStaleWarningMs <= 0) {
221
+ return void 0;
222
+ }
223
+ const idleMs = nowMs - state.lastActivityAtMs;
224
+ if (idleMs < options.turnStaleWarningMs) {
225
+ return void 0;
226
+ }
227
+ return createSlackTurnStatusVisibilityWarning({
228
+ id: `turn:${state.phase}`,
229
+ message: formatTurnStaleStatus(state.phase),
230
+ nowMs,
231
+ state,
232
+ thresholdMs: options.turnStaleWarningMs,
233
+ type: "turn"
234
+ });
235
+ }
236
+ function isSlackWaitingForHumanTurnPhase(phase) {
237
+ return phase === "waiting-approval" || phase === "waiting-input";
238
+ }
239
+ function isSlackTerminalTurnPhase(phase) {
240
+ return phase === "completed" || phase === "failed" || phase === "cancelled";
241
+ }
242
+ function createSlackTurnStatusVisibilityWarning({
243
+ id,
244
+ message,
245
+ nowMs,
246
+ state,
247
+ thresholdMs,
248
+ type
249
+ }) {
250
+ if (state.statusWarningsSent.has(id)) {
251
+ return void 0;
252
+ }
253
+ state.statusWarningsSent.add(id);
254
+ const receivedEventCount = Object.values(state.eventCounts).reduce(
255
+ (total, count) => total + count,
256
+ 0
257
+ );
258
+ const idleMs = type === "tool" && state.currentTool ? nowMs - state.currentTool.startedAtMs : nowMs - state.lastActivityAtMs;
259
+ return {
260
+ elapsedMs: nowMs - state.startedAtMs,
261
+ ...state.firstEventAtMs === void 0 ? {} : { firstEventLatencyMs: state.firstEventAtMs - state.startedAtMs },
262
+ ...state.firstEventType ? { firstEventType: state.firstEventType } : {},
263
+ id,
264
+ idleMs,
265
+ message,
266
+ phase: state.phase,
267
+ receivedEventCount,
268
+ ...state.sessionId ? { sessionId: state.sessionId } : {},
269
+ staleBeforeFirstEvent: receivedEventCount === 0,
270
+ thresholdMs,
271
+ ...state.currentTool ? {
272
+ toolCallId: state.currentTool.toolCallId,
273
+ toolName: state.currentTool.toolName
274
+ } : {},
275
+ ...state.turnId ? { turnId: state.turnId } : {},
276
+ type
277
+ };
278
+ }
279
+ function defaultToolStaleStatus(toolName) {
280
+ return `Still waiting on ${toolName}...`;
281
+ }
282
+ function defaultTurnStaleStatus(phase) {
283
+ switch (phase) {
284
+ case "streaming":
285
+ return "The response stream is taking longer than expected. I am still working on it.";
286
+ case "tool-running":
287
+ return "A tool is taking longer than expected. I am still waiting for it.";
288
+ default:
289
+ return "This request is taking longer than expected. I am still working on it.";
290
+ }
291
+ }
292
+ function normalizeMs(value, fallback) {
293
+ if (value === void 0 || !Number.isFinite(value) || value < 0) {
294
+ return fallback;
295
+ }
296
+ return Math.floor(value);
297
+ }
298
+
299
+ // src/source/subagent-completion-notifier.ts
300
+ function createSlackSubagentCompletionNotifier({
301
+ enabled = true,
302
+ formatMessage = formatDefaultSlackSubagentCompletionMessage,
303
+ logger,
304
+ postMessage: initialPostMessage
305
+ } = {}) {
306
+ const runningByDispatchId = /* @__PURE__ */ new Map();
307
+ const detachedTurnIds = /* @__PURE__ */ new Set();
308
+ const deliveredInlineDispatchIds = /* @__PURE__ */ new Set();
309
+ const postedTerminalKeys = /* @__PURE__ */ new Set();
310
+ let postMessage = initialPostMessage;
311
+ function trackStartedRun(turn, event) {
312
+ if (!enabled || deliveredInlineDispatchIds.has(event.dispatchId)) {
313
+ return;
314
+ }
315
+ const slack = slackThreadContext(turn.slack);
316
+ if (!slack) {
317
+ logger?.debug?.("Skipping subagent Slack notification tracking", {
318
+ dispatchId: event.dispatchId,
319
+ reason: "missing-slack-thread-context",
320
+ sessionId: turn.sessionId,
321
+ turnId: turn.turnId
322
+ });
323
+ return;
324
+ }
325
+ runningByDispatchId.set(event.dispatchId, {
326
+ dispatchId: event.dispatchId,
327
+ role: event.role,
328
+ sessionId: turn.sessionId,
329
+ slack,
330
+ title: event.title,
331
+ turnId: turn.turnId
332
+ });
333
+ }
334
+ function markResultDeliveredInline(event) {
335
+ deliveredInlineDispatchIds.add(event.dispatchId);
336
+ runningByDispatchId.delete(event.dispatchId);
337
+ }
338
+ function markTurnDetached(turnId) {
339
+ detachedTurnIds.add(turnId);
340
+ }
341
+ async function postDetachedCompletionsFromEventStore(eventStore) {
342
+ if (!enabled || runningByDispatchId.size === 0) {
343
+ return;
344
+ }
345
+ let records;
346
+ try {
347
+ records = await eventStore.list({
348
+ type: ["subagent-complete", "subagent-error"]
349
+ });
350
+ } catch (error) {
351
+ logger?.warn?.(
352
+ "Failed to inspect dispatch events for Slack notifications",
353
+ {
354
+ error: formatNotifierError(error)
355
+ }
356
+ );
357
+ return;
358
+ }
359
+ for (const record of records) {
360
+ if (!isSlackSubagentTerminalEvent(record.event)) {
361
+ continue;
362
+ }
363
+ const run = runningByDispatchId.get(record.dispatchId);
364
+ if (!run || !detachedTurnIds.has(run.turnId)) {
365
+ continue;
366
+ }
367
+ await postTerminalEvent(record.event);
368
+ }
369
+ }
370
+ async function postTerminalEvent(event) {
371
+ if (!enabled || deliveredInlineDispatchIds.has(event.dispatchId)) {
372
+ return;
373
+ }
374
+ const key = `${event.dispatchId}:${event.type}`;
375
+ if (postedTerminalKeys.has(key)) {
376
+ return;
377
+ }
378
+ const run = runningByDispatchId.get(event.dispatchId);
379
+ if (!run) {
380
+ logger?.debug?.("Skipping detached subagent Slack notification", {
381
+ dispatchId: event.dispatchId,
382
+ eventType: event.type,
383
+ reason: "missing-tracked-start"
384
+ });
385
+ return;
386
+ }
387
+ if (!postMessage) {
388
+ logger?.debug?.("Skipping detached subagent Slack notification", {
389
+ dispatchId: event.dispatchId,
390
+ eventType: event.type,
391
+ reason: "missing-slack-poster"
392
+ });
393
+ return;
394
+ }
395
+ try {
396
+ await postMessage(formatMessage({ event, run }));
397
+ postedTerminalKeys.add(key);
398
+ runningByDispatchId.delete(event.dispatchId);
399
+ logger?.info?.("Slack subagent completion notification sent", {
400
+ channelId: run.slack.channelId,
401
+ dispatchId: event.dispatchId,
402
+ eventType: event.type,
403
+ sessionId: run.sessionId,
404
+ threadTs: run.slack.threadTs,
405
+ turnId: run.turnId
406
+ });
407
+ } catch (error) {
408
+ logger?.warn?.("Failed to send Slack subagent completion notification", {
409
+ dispatchId: event.dispatchId,
410
+ error: formatNotifierError(error),
411
+ eventType: event.type,
412
+ sessionId: run.sessionId,
413
+ turnId: run.turnId
414
+ });
415
+ }
416
+ }
417
+ return {
418
+ clear() {
419
+ runningByDispatchId.clear();
420
+ detachedTurnIds.clear();
421
+ deliveredInlineDispatchIds.clear();
422
+ postedTerminalKeys.clear();
423
+ },
424
+ markResultDeliveredInline,
425
+ markTurnDetached,
426
+ postDetachedCompletionsFromEventStore,
427
+ postTerminalEvent,
428
+ setPostMessage(nextPostMessage) {
429
+ postMessage = nextPostMessage;
430
+ },
431
+ trackStartedRun
432
+ };
433
+ }
434
+ function isSlackSubagentTerminalEvent(event) {
435
+ return event.type === "subagent-complete" || event.type === "subagent-error";
436
+ }
437
+ function formatDefaultSlackSubagentCompletionMessage({
438
+ event,
439
+ run
440
+ }) {
441
+ const roleTitle = formatRoleTitle(event.role || run.role);
442
+ const title = event.title || run.title || roleTitle;
443
+ const dispatchId = event.dispatchId || run.dispatchId;
444
+ const completed = event.type === "subagent-complete";
445
+ const statusText = completed ? "Result ready" : event.status === "cancelled" ? "Cancelled" : "Failed";
446
+ const heading = completed ? "Subagent result ready" : "Subagent stopped";
447
+ const instruction = completed ? `Ask me to retrieve the result for subagent \`${escapeCode(dispatchId)}\`.` : `The subagent did not finish successfully: ${event.error}`;
448
+ const fallback = [
449
+ `${roleTitle} ${statusText.toLowerCase()}: ${title}`,
450
+ "",
451
+ `Subagent ID: ${dispatchId}`,
452
+ instruction
453
+ ].join("\n");
454
+ return {
455
+ channel: run.slack.channelId,
456
+ thread_ts: run.slack.threadTs,
457
+ text: fallback,
458
+ blocks: [
459
+ {
460
+ type: "section",
461
+ text: {
462
+ type: "mrkdwn",
463
+ text: `*${escapeMrkdwn(heading)}*`
464
+ }
465
+ },
466
+ { type: "divider" },
467
+ {
468
+ type: "section",
469
+ fields: [
470
+ {
471
+ type: "mrkdwn",
472
+ text: `*Subagent*
473
+ ${escapeMrkdwn(roleTitle)}`
474
+ },
475
+ {
476
+ type: "mrkdwn",
477
+ text: `*Status*
478
+ ${escapeMrkdwn(statusText)}`
479
+ },
480
+ {
481
+ type: "mrkdwn",
482
+ text: `*Task*
483
+ ${escapeMrkdwn(title)}`
484
+ },
485
+ {
486
+ type: "mrkdwn",
487
+ text: `*Subagent ID*
488
+ \`${escapeCode(dispatchId)}\``
489
+ }
490
+ ]
491
+ },
492
+ {
493
+ type: "context",
494
+ elements: [
495
+ {
496
+ type: "mrkdwn",
497
+ text: escapeMrkdwn(instruction)
498
+ }
499
+ ]
500
+ }
501
+ ]
502
+ };
503
+ }
504
+ function slackThreadContext(slack) {
505
+ if (!slack?.channelId || !slack.threadTs) {
506
+ return void 0;
507
+ }
508
+ return {
509
+ channelId: slack.channelId,
510
+ threadTs: slack.threadTs,
511
+ ...slack.channelType ? { channelType: slack.channelType } : {},
512
+ ...slack.messageTs ? { messageTs: slack.messageTs } : {},
513
+ ...slack.teamId ? { teamId: slack.teamId } : {}
514
+ };
515
+ }
516
+ function formatRoleTitle(role) {
517
+ const words = role.replace(/[_-]+/g, " ").trim();
518
+ return words ? words.charAt(0).toUpperCase() + words.slice(1) : "Subagent";
519
+ }
520
+ function escapeMrkdwn(value) {
521
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
522
+ }
523
+ function escapeCode(value) {
524
+ return escapeMrkdwn(value).replace(/`/g, "'");
525
+ }
526
+ function formatNotifierError(error) {
527
+ return error instanceof Error ? error.stack ?? error.message : String(error);
528
+ }
529
+
530
+ export {
531
+ coalesceSlackAgentEvents,
532
+ routeSlackAgentEvent,
533
+ shouldQueueSlackAgentEvent,
534
+ immediateSlackTextResponse,
535
+ isSlackCancelMessage,
536
+ resolveSlackTypedApprovalAction,
537
+ isRunningAgentTurnError,
538
+ isAbortLikeError,
539
+ resolveSlackTurnStatusVisibilityOptions,
540
+ shouldInspectSlackTurnStatusVisibility,
541
+ recordSlackTurnActivity,
542
+ inspectSlackTurnStatusVisibility,
543
+ isSlackWaitingForHumanTurnPhase,
544
+ isSlackTerminalTurnPhase,
545
+ createSlackSubagentCompletionNotifier,
546
+ isSlackSubagentTerminalEvent,
547
+ formatDefaultSlackSubagentCompletionMessage
548
+ };
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createSlackAssistantBridge
3
- } from "./chunk-BFUPAJON.js";
4
- import {
5
- bolt_exports
6
- } from "./chunk-ANIZ5NT4.js";
3
+ } from "./chunk-MGBNGG4D.js";
7
4
 
8
5
  // src/express-assistant.ts
6
+ import {
7
+ createSlackBoltApp
8
+ } from "@cuylabs/channel-slack/transports/http";
9
9
  async function mountSlackAssistantAgent(options) {
10
10
  const {
11
11
  botToken,
@@ -29,7 +29,7 @@ async function mountSlackAssistantAgent(options) {
29
29
  app: expressApp,
30
30
  authMode,
31
31
  routePath
32
- } = await (0, bolt_exports.createSlackBoltApp)({
32
+ } = await createSlackBoltApp({
33
33
  signingSecret,
34
34
  path,
35
35
  botToken,
@@ -0,0 +1,12 @@
1
+ // src/feedback/index.ts
2
+ import {
3
+ SLACK_FEEDBACK_ACTION_ID,
4
+ createSlackFeedbackBlock,
5
+ registerSlackFeedbackAction
6
+ } from "@cuylabs/channel-slack/feedback";
7
+
8
+ export {
9
+ SLACK_FEEDBACK_ACTION_ID,
10
+ createSlackFeedbackBlock,
11
+ registerSlackFeedbackAction
12
+ };
@@ -1,22 +1,25 @@
1
+ import {
2
+ UnsupportedSlackInteractiveRequestError,
3
+ bridgeAgentEventsToSlack,
4
+ resolveSlackEventBridgeOptions
5
+ } from "./chunk-TMADMHBN.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 "./chunk-DHPD4XH5.js";
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 {};
@@ -73,6 +73,11 @@ function buildThreadPayload(info, respondInThread) {
73
73
  function buildResponseSink(say, client, info, respondInThread, chatStreamStartArgs, sayStream) {
74
74
  const threadPayload = buildThreadPayload(info, respondInThread);
75
75
  return {
76
+ artifactClient: client,
77
+ artifactTarget: {
78
+ channelId: info.channelId,
79
+ ...threadPayload.thread_ts ? { threadTs: threadPayload.thread_ts } : {}
80
+ },
76
81
  async postMessage(text) {
77
82
  const result = await say({ text, ...threadPayload });
78
83
  const response = result;
@@ -167,6 +172,7 @@ function createSlackChannelAdapter(options) {
167
172
  formatToolTitle: options.formatToolTitle,
168
173
  formatToolUpdate: options.formatToolUpdate,
169
174
  formatToolDetails: options.formatToolDetails,
175
+ formatToolResultOutput: options.formatToolResultOutput,
170
176
  formatToolError: options.formatToolError,
171
177
  formatReasoningUpdate: options.formatReasoningUpdate,
172
178
  interactiveMode: options.interactiveMode,
@@ -180,7 +186,13 @@ function createSlackChannelAdapter(options) {
180
186
  maxTaskUpdates: options.maxTaskUpdates,
181
187
  maxTaskUpdateTextChars: options.maxTaskUpdateTextChars,
182
188
  maxTaskUpdateFieldChars: options.maxTaskUpdateFieldChars,
183
- chatStreamFinalArgs: options.chatStreamFinalArgs
189
+ chatStreamFinalArgs: options.chatStreamFinalArgs,
190
+ publishFinalResponseArtifact: options.publishFinalResponseArtifact,
191
+ finalResponseArtifactMode: options.finalResponseArtifactMode,
192
+ finalResponseArtifactStreamThreshold: options.finalResponseArtifactStreamThreshold,
193
+ formatFinalResponseArtifactContinuationNotice: options.formatFinalResponseArtifactContinuationNotice,
194
+ formatFinalResponseArtifactMessage: options.formatFinalResponseArtifactMessage,
195
+ onFinalResponseArtifactError: options.onFinalResponseArtifactError
184
196
  }
185
197
  );
186
198
  const timeout = options.timeout ?? 12e4;
@@ -465,7 +477,6 @@ function formatErrorForLog(error) {
465
477
  }
466
478
 
467
479
  export {
468
- resolveThreadAwareSlackSessionId,
469
480
  createSlackSessionMap,
470
481
  createSlackChannelAdapter
471
482
  };