@cuylabs/channel-slack-agent-core 0.7.0 → 0.9.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 (43) hide show
  1. package/README.md +4 -2
  2. package/dist/adapter/index.d.ts +6 -5
  3. package/dist/adapter/index.js +2 -2
  4. package/dist/{adapter-B3CI611y.d.ts → adapter-vbqtraAr.d.ts} +1 -1
  5. package/dist/app-surface.d.ts +6 -5
  6. package/dist/app-surface.js +4 -4
  7. package/dist/app.d.ts +6 -5
  8. package/dist/app.js +5 -5
  9. package/dist/assistant/index.d.ts +5 -4
  10. package/dist/assistant/index.js +2 -2
  11. package/dist/{chunk-TCNJY7QA.js → chunk-D4CSEAIF.js} +1 -1
  12. package/dist/{chunk-MGBNGG4D.js → chunk-FJP6ZFUB.js} +241 -4
  13. package/dist/{chunk-7DUO5BMW.js → chunk-GKZRDNEB.js} +4 -25
  14. package/dist/{chunk-VMVQIDNR.js → chunk-HHXAXSG6.js} +2 -2
  15. package/dist/{chunk-DJPKRKGP.js → chunk-JU5R6JZG.js} +1 -1
  16. package/dist/{chunk-76SRS54H.js → chunk-KAEZPS3U.js} +1 -1
  17. package/dist/chunk-OP27SSZU.js +409 -0
  18. package/dist/{chunk-FQWFB54C.js → chunk-XA7U3GRN.js} +1 -1
  19. package/dist/express-assistant.d.ts +4 -3
  20. package/dist/express-assistant.js +3 -3
  21. package/dist/express.d.ts +5 -4
  22. package/dist/express.js +3 -3
  23. package/dist/history/index.d.ts +6 -5
  24. package/dist/index.d.ts +11 -10
  25. package/dist/index.js +10 -34
  26. package/dist/interactive/index.d.ts +5 -65
  27. package/dist/interactive/index.js +3 -27
  28. package/dist/interactive-BigrPKnu.d.ts +30 -0
  29. package/dist/{options-CdqBABcM.d.ts → options-ByNm2o89.d.ts} +38 -3
  30. package/dist/{options-BcDReOJv.d.ts → options-CGUfVStV.d.ts} +1 -1
  31. package/dist/shared/index.d.ts +7 -76
  32. package/dist/shared/index.js +1 -1
  33. package/dist/socket.d.ts +6 -5
  34. package/dist/socket.js +5 -5
  35. package/dist/{types-CRWzJB5G.d.ts → types-BeGPexio.d.ts} +2 -2
  36. package/dist/{types-Crpil4kb.d.ts → types-Bz4OYEAV.d.ts} +6 -55
  37. package/docs/concepts/interactive-requests.md +7 -7
  38. package/docs/reference/boundary.md +5 -3
  39. package/docs/reference/exports.md +18 -18
  40. package/package.json +2 -2
  41. package/dist/chunk-X7ILLZZP.js +0 -1046
  42. package/dist/interactive-o_NZb-Xg.d.ts +0 -47
  43. /package/dist/{chunk-TMADMHBN.js → chunk-VBGQD6JT.js} +0 -0
package/README.md CHANGED
@@ -8,7 +8,8 @@ surfaces for Express Events API, Socket Mode, Slack Assistant, app mentions,
8
8
  DMs, feedback, approvals, or human input.
9
9
 
10
10
  Generic Slack mechanics such as parsing, policy, history, setup, auth, targets,
11
- users, entrypoints, artifacts, and transports live in `@cuylabs/channel-slack`.
11
+ users, entrypoints, artifacts, interactive stores/builders, response sinks, and
12
+ transports live in `@cuylabs/channel-slack`.
12
13
 
13
14
  ## Install
14
15
 
@@ -22,7 +23,8 @@ Install Slack peer dependencies for the surfaces you use:
22
23
  npm install @slack/bolt @slack/web-api express
23
24
  ```
24
25
 
25
- Postgres-backed interactive request storage lazy-loads `pg` when you pass a
26
+ Postgres-backed interactive request storage lives in
27
+ `@cuylabs/channel-slack/interactive` and lazy-loads `pg` when you pass a
26
28
  connection string. Install `pg` only when your application uses that helper
27
29
  without injecting its own client.
28
30
 
@@ -1,12 +1,13 @@
1
- export { c as createSlackChannelAdapter } from '../adapter-B3CI611y.js';
2
- import { a as SlackChannelOptions } from '../types-CRWzJB5G.js';
3
- export { S as SlackChannelAdapter, b as SlackSessionStrategy, c as SlackStreamingMode, d as SlackToolStartEvent } from '../types-CRWzJB5G.js';
1
+ export { c as createSlackChannelAdapter } from '../adapter-vbqtraAr.js';
2
+ import { a as SlackChannelOptions } from '../types-BeGPexio.js';
3
+ export { S as SlackChannelAdapter, b as SlackSessionStrategy, c as SlackStreamingMode, d as SlackToolStartEvent } from '../types-BeGPexio.js';
4
4
  import { SlackActivityInfo } from '@cuylabs/channel-slack/core';
5
5
  import '@cuylabs/agent-core';
6
- import '../options-BcDReOJv.js';
6
+ import '../options-CGUfVStV.js';
7
7
  import '../artifacts/index.js';
8
8
  import '@cuylabs/channel-slack/artifacts';
9
- import '../interactive-o_NZb-Xg.js';
9
+ import '../interactive-BigrPKnu.js';
10
+ import '@cuylabs/channel-slack/interactive';
10
11
 
11
12
  /**
12
13
  * Session mapping — Slack activity info to agent-core session IDs.
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createSlackChannelAdapter,
3
3
  createSlackSessionMap
4
- } from "../chunk-FQWFB54C.js";
5
- import "../chunk-TMADMHBN.js";
4
+ } from "../chunk-XA7U3GRN.js";
5
+ import "../chunk-VBGQD6JT.js";
6
6
  export {
7
7
  createSlackChannelAdapter,
8
8
  createSlackSessionMap
@@ -1,4 +1,4 @@
1
- import { a as SlackChannelOptions, S as SlackChannelAdapter } from './types-CRWzJB5G.js';
1
+ import { a as SlackChannelOptions, S as SlackChannelAdapter } from './types-BeGPexio.js';
2
2
 
3
3
  /**
4
4
  * Slack Channel Adapter
@@ -1,14 +1,15 @@
1
1
  import { AgentTurnSource, Logger } from '@cuylabs/agent-core';
2
2
  import { App } from '@slack/bolt';
3
3
  import { WebClient } from '@slack/web-api';
4
- import { C as CreateSlackAssistantBridgeOptions, b as SlackAssistantFeedbackConfig, S as SlackAssistantBridge } from './options-CdqBABcM.js';
5
- import { a as SlackChannelOptions } from './types-CRWzJB5G.js';
4
+ import { C as CreateSlackAssistantBridgeOptions, d as SlackAssistantFeedbackConfig, S as SlackAssistantBridge } from './options-ByNm2o89.js';
5
+ import { a as SlackChannelOptions } from './types-BeGPexio.js';
6
6
  import { SlackTurnRequestContext, SlackAssistantUtilities, SlackTurnPreparation } from '@cuylabs/channel-slack/core';
7
7
  import { SlackFeedbackHandler } from '@cuylabs/channel-slack/feedback';
8
- import { c as SlackInteractiveController } from './types-Crpil4kb.js';
8
+ import { a as SlackInteractiveController } from './types-Bz4OYEAV.js';
9
9
  import { d as SlackAgentViewWorkflowController } from './types-CiwGU6zC.js';
10
- import './interactive-o_NZb-Xg.js';
11
- import './options-BcDReOJv.js';
10
+ import './interactive-BigrPKnu.js';
11
+ import '@cuylabs/channel-slack/interactive';
12
+ import './options-CGUfVStV.js';
12
13
  import './artifacts/index.js';
13
14
  import '@cuylabs/channel-slack/artifacts';
14
15
  import '@cuylabs/channel-slack/assistant';
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  installSlackAgentAppSurface
3
- } from "./chunk-7DUO5BMW.js";
4
- import "./chunk-MGBNGG4D.js";
3
+ } from "./chunk-GKZRDNEB.js";
4
+ import "./chunk-FJP6ZFUB.js";
5
5
  import "./chunk-ELR6MQD7.js";
6
- import "./chunk-FQWFB54C.js";
7
- import "./chunk-TMADMHBN.js";
6
+ import "./chunk-XA7U3GRN.js";
7
+ import "./chunk-VBGQD6JT.js";
8
8
  export {
9
9
  installSlackAgentAppSurface
10
10
  };
package/dist/app.d.ts CHANGED
@@ -5,17 +5,18 @@ import { CreateSlackBoltAppOptions } from '@cuylabs/channel-slack/transports/htt
5
5
  import { SlackDirectAuthOptions, SlackDirectAuthMode } from '@cuylabs/channel-slack/auth';
6
6
  import { SlackAgentAppSurfaceOptions } from './app-surface.js';
7
7
  export { MountSlackAgentAppTurnRequestContext } from './app-surface.js';
8
- import { S as SlackAssistantBridge } from './options-CdqBABcM.js';
8
+ import { S as SlackAssistantBridge } from './options-ByNm2o89.js';
9
9
  import '@cuylabs/agent-core';
10
10
  import '@slack/web-api';
11
- import './types-CRWzJB5G.js';
11
+ import './types-BeGPexio.js';
12
12
  import '@cuylabs/channel-slack/core';
13
- import './options-BcDReOJv.js';
13
+ import './options-CGUfVStV.js';
14
14
  import './artifacts/index.js';
15
15
  import '@cuylabs/channel-slack/artifacts';
16
- import './interactive-o_NZb-Xg.js';
16
+ import './interactive-BigrPKnu.js';
17
+ import '@cuylabs/channel-slack/interactive';
17
18
  import '@cuylabs/channel-slack/feedback';
18
- import './types-Crpil4kb.js';
19
+ import './types-Bz4OYEAV.js';
19
20
  import './types-CiwGU6zC.js';
20
21
  import '@cuylabs/channel-slack/views';
21
22
  import '@cuylabs/channel-slack/assistant';
package/dist/app.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  mountSlackAgentApp
3
- } from "./chunk-76SRS54H.js";
4
- import "./chunk-7DUO5BMW.js";
5
- import "./chunk-MGBNGG4D.js";
3
+ } from "./chunk-KAEZPS3U.js";
4
+ import "./chunk-GKZRDNEB.js";
5
+ import "./chunk-FJP6ZFUB.js";
6
6
  import "./chunk-ELR6MQD7.js";
7
- import "./chunk-FQWFB54C.js";
8
- import "./chunk-TMADMHBN.js";
7
+ import "./chunk-XA7U3GRN.js";
8
+ import "./chunk-VBGQD6JT.js";
9
9
  export {
10
10
  mountSlackAgentApp
11
11
  };
@@ -1,12 +1,13 @@
1
- import { C as CreateSlackAssistantBridgeOptions, S as SlackAssistantBridge } from '../options-CdqBABcM.js';
2
- export { A as AssistantLifecycleArgs, a as AssistantThreadStartedArgs, M as MaybePromise, b as SlackAssistantFeedbackConfig, c as SlackAssistantSessionStrategy, d as SlackAssistantStatusContext, e as SlackAssistantThreadContextStoreLike, f as SlackAssistantThreadStartedContext, g as SlackAssistantTurnPreparation, h as SlackAssistantUserMessageContext, r as resolveAssistantSessionId } from '../options-CdqBABcM.js';
1
+ import { C as CreateSlackAssistantBridgeOptions, S as SlackAssistantBridge } from '../options-ByNm2o89.js';
2
+ export { A as AssistantLifecycleArgs, a as AssistantThreadStartedArgs, M as MaybePromise, b as SlackAssistantCancelControlOptions, c as SlackAssistantCancelControlVisibleWhen, d as SlackAssistantFeedbackConfig, e as SlackAssistantSessionStrategy, f as SlackAssistantStatusContext, g as SlackAssistantThreadContextStoreLike, h as SlackAssistantThreadStartedContext, i as SlackAssistantTurnCancelContext, j as SlackAssistantTurnControlsOptions, k as SlackAssistantTurnPreparation, l as SlackAssistantUserMessageContext, r as resolveAssistantSessionId } from '../options-ByNm2o89.js';
3
3
  export { ParsedAssistantUserMessage, createSlackAssistantThreadContextStore, parseSlackMessageActivityFromMessageEvent } from '@cuylabs/channel-slack/assistant';
4
4
  import '@cuylabs/agent-core';
5
5
  import '@slack/bolt';
6
6
  import '@slack/web-api';
7
7
  import '@cuylabs/channel-slack/core';
8
- import '../interactive-o_NZb-Xg.js';
9
- import '../options-BcDReOJv.js';
8
+ import '../interactive-BigrPKnu.js';
9
+ import '@cuylabs/channel-slack/interactive';
10
+ import '../options-CGUfVStV.js';
10
11
  import '../artifacts/index.js';
11
12
  import '@cuylabs/channel-slack/artifacts';
12
13
  import '@cuylabs/channel-slack/feedback';
@@ -3,9 +3,9 @@ import {
3
3
  createSlackAssistantThreadContextStore,
4
4
  parseSlackMessageActivityFromMessageEvent,
5
5
  resolveAssistantSessionId
6
- } from "../chunk-MGBNGG4D.js";
6
+ } from "../chunk-FJP6ZFUB.js";
7
7
  import "../chunk-ELR6MQD7.js";
8
- import "../chunk-TMADMHBN.js";
8
+ import "../chunk-VBGQD6JT.js";
9
9
  export {
10
10
  createSlackAssistantBridge,
11
11
  createSlackAssistantThreadContextStore,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createSlackChannelAdapter
3
- } from "./chunk-FQWFB54C.js";
3
+ } from "./chunk-XA7U3GRN.js";
4
4
 
5
5
  // src/express.ts
6
6
  import {
@@ -7,10 +7,11 @@ import {
7
7
  UnsupportedSlackInteractiveRequestError,
8
8
  bridgeAgentEventsToSlack,
9
9
  resolveSlackEventBridgeOptions
10
- } from "./chunk-TMADMHBN.js";
10
+ } from "./chunk-VBGQD6JT.js";
11
11
 
12
12
  // src/assistant/bridge.ts
13
13
  import { Assistant } from "@slack/bolt";
14
+ import { resolveSlackTurnCancelActionId as resolveSlackTurnCancelActionId2 } from "@cuylabs/channel-slack/turn-controls";
14
15
 
15
16
  // src/assistant/options.ts
16
17
  var DEFAULT_INITIAL_REPLY = "Hi, how can I help?";
@@ -294,7 +295,7 @@ function createAssistantInteractiveResponder(params) {
294
295
 
295
296
  // src/assistant/lifecycle/user-message.ts
296
297
  function createUserMessageHandler(deps) {
297
- const { options, feedbackBlock, sessionStrategy } = deps;
298
+ const { options, feedbackBlock, sessionStrategy, turnControlController } = deps;
298
299
  const taskDisplayMode = options.taskDisplayMode ?? "timeline";
299
300
  const messageFormatter = resolveSlackMessageFormatter(
300
301
  options.formatChatMarkdown ?? {}
@@ -497,6 +498,17 @@ function createUserMessageHandler(deps) {
497
498
  });
498
499
  const abortController = new AbortController();
499
500
  timeoutId = timeoutMs > 0 ? setTimeout(() => abortController.abort(), timeoutMs) : void 0;
501
+ const cancelControl = turnControlController?.createCancelControl({
502
+ abortController,
503
+ channel,
504
+ client,
505
+ logger: diagnosticsLogger,
506
+ sessionId,
507
+ ...teamId ? { teamId } : {},
508
+ threadTs,
509
+ userId: userId ?? "unknown"
510
+ });
511
+ cancelControl?.show("turn-start");
500
512
  await runWithSlackTurnContext(
501
513
  {
502
514
  slackActivity: parsed,
@@ -533,6 +545,7 @@ function createUserMessageHandler(deps) {
533
545
  const translated = (async function* () {
534
546
  try {
535
547
  for await (const event of events) {
548
+ cancelControl?.sync(event);
536
549
  if (event.type === "error") {
537
550
  translatedError = toError(
538
551
  event.error
@@ -561,6 +574,8 @@ ${formatStreamError(translatedError)}`
561
574
  ${formatStreamError(translatedError)}`
562
575
  };
563
576
  yield { type: "complete" };
577
+ } finally {
578
+ cancelControl?.clear("turn-finished");
564
579
  }
565
580
  })();
566
581
  const finalText = await bridgeAgentEventsToSlack(
@@ -617,6 +632,213 @@ ${formatStreamError(translatedError)}`
617
632
  };
618
633
  }
619
634
 
635
+ // src/assistant/turn-controls.ts
636
+ import { randomUUID } from "crypto";
637
+ import {
638
+ createSlackTurnCancelMessage,
639
+ registerSlackTurnCancelAction,
640
+ resolveSlackTurnCancelActionId
641
+ } from "@cuylabs/channel-slack/turn-controls";
642
+ function createSlackAssistantTurnControlController(options) {
643
+ const resolvedCancelOptions = resolveCancelOptions(options);
644
+ if (!resolvedCancelOptions) {
645
+ return void 0;
646
+ }
647
+ const cancelOptions = resolvedCancelOptions;
648
+ const actionId = resolveSlackTurnCancelActionId(cancelOptions.actionId);
649
+ const activeControls = /* @__PURE__ */ new Map();
650
+ function install(app) {
651
+ registerSlackTurnCancelAction(app, {
652
+ actionId,
653
+ onCancel: (context) => handleCancelAction(context)
654
+ });
655
+ }
656
+ function createCancelControl(controlOptions) {
657
+ const control = {
658
+ abortController: controlOptions.abortController,
659
+ channel: controlOptions.channel,
660
+ client: controlOptions.client,
661
+ controlId: randomUUID(),
662
+ logger: controlOptions.logger,
663
+ pending: Promise.resolve(),
664
+ sessionId: controlOptions.sessionId,
665
+ ...controlOptions.teamId ? { teamId: controlOptions.teamId } : {},
666
+ threadTs: controlOptions.threadTs,
667
+ userId: controlOptions.userId,
668
+ visible: false
669
+ };
670
+ activeControls.set(control.controlId, control);
671
+ return {
672
+ show(reason) {
673
+ showCancelControl(control, reason);
674
+ },
675
+ clear(reason) {
676
+ clearCancelControl(control, reason);
677
+ },
678
+ sync(event) {
679
+ syncCancelControlForEvent(control, event);
680
+ }
681
+ };
682
+ }
683
+ async function handleCancelAction(context) {
684
+ const control = activeControls.get(context.controlId);
685
+ if (!control) {
686
+ await context.deleteMessage().catch(() => void 0);
687
+ await acknowledge(context, cancelOptions.alreadyCompletedAck);
688
+ return;
689
+ }
690
+ if (context.userId !== control.userId) {
691
+ await acknowledge(context, cancelOptions.unauthorizedAck);
692
+ return;
693
+ }
694
+ clearCancelControl(control, "button-cancel");
695
+ activeControls.delete(control.controlId);
696
+ if (!control.abortController.signal.aborted) {
697
+ control.abortController.abort(createSlackTurnCancelledError());
698
+ }
699
+ await cancelOptions.onCancel?.({
700
+ controlId: control.controlId,
701
+ sessionId: control.sessionId,
702
+ channelId: control.channel,
703
+ threadTs: control.threadTs,
704
+ userId: control.userId,
705
+ ...control.teamId ? { teamId: control.teamId } : {}
706
+ });
707
+ await acknowledge(context, cancelOptions.canceledAck);
708
+ }
709
+ function showCancelControl(control, reason) {
710
+ if (control.visible || control.abortController.signal.aborted) {
711
+ return;
712
+ }
713
+ control.visible = true;
714
+ enqueueControlUpdate(control, "show", reason, async () => {
715
+ const message = createSlackTurnCancelMessage({
716
+ actionId,
717
+ controlId: control.controlId,
718
+ messageText: cancelOptions.messageText,
719
+ buttonText: cancelOptions.buttonText,
720
+ sessionId: control.sessionId
721
+ });
722
+ if (control.target) {
723
+ await control.client.chat.update({
724
+ channel: control.target.channel,
725
+ ts: control.target.ts,
726
+ text: message.text,
727
+ blocks: message.blocks
728
+ });
729
+ return;
730
+ }
731
+ const response = await control.client.chat.postMessage({
732
+ channel: control.channel,
733
+ thread_ts: control.threadTs,
734
+ text: message.text,
735
+ blocks: message.blocks
736
+ });
737
+ if (response.channel && response.ts) {
738
+ control.target = { channel: response.channel, ts: response.ts };
739
+ }
740
+ });
741
+ }
742
+ function clearCancelControl(control, reason) {
743
+ const terminal = isTerminalClearReason(reason);
744
+ if (terminal) {
745
+ activeControls.delete(control.controlId);
746
+ }
747
+ if (!control.visible) {
748
+ return;
749
+ }
750
+ control.visible = false;
751
+ enqueueControlUpdate(control, "clear", reason, async () => {
752
+ if (!control.target) {
753
+ return;
754
+ }
755
+ const target = control.target;
756
+ control.target = void 0;
757
+ await control.client.chat.delete({
758
+ channel: target.channel,
759
+ ts: target.ts
760
+ });
761
+ });
762
+ }
763
+ function syncCancelControlForEvent(control, event) {
764
+ switch (event.type) {
765
+ case "text-start":
766
+ case "text-delta":
767
+ case "text-end":
768
+ if (cancelOptions.visibleWhen === "before-output") {
769
+ clearCancelControl(control, "streaming-started");
770
+ }
771
+ break;
772
+ case "reasoning-start":
773
+ case "reasoning-delta":
774
+ case "reasoning-end":
775
+ case "tool-start":
776
+ case "approval-request":
777
+ case "human-input-request":
778
+ showCancelControl(control, event.type);
779
+ break;
780
+ case "status":
781
+ if (isWaitingForAgentStatus(event.status)) {
782
+ showCancelControl(control, `status:${event.status}`);
783
+ } else if (event.status === "idle" || event.status === "error") {
784
+ clearCancelControl(control, `status:${event.status}`);
785
+ }
786
+ break;
787
+ case "complete":
788
+ clearCancelControl(control, "turn-finished");
789
+ break;
790
+ case "error":
791
+ clearCancelControl(control, "turn-error");
792
+ break;
793
+ default:
794
+ break;
795
+ }
796
+ }
797
+ function enqueueControlUpdate(control, action, reason, update) {
798
+ control.pending = control.pending.then(update);
799
+ control.pending = control.pending.catch((error) => {
800
+ control.logger.warn?.("Slack turn cancel control update failed", {
801
+ action,
802
+ controlId: control.controlId,
803
+ error: formatErrorForLog(error),
804
+ reason,
805
+ sessionId: control.sessionId
806
+ });
807
+ });
808
+ }
809
+ async function acknowledge(context, text) {
810
+ if (text === false) {
811
+ return;
812
+ }
813
+ await context.acknowledgeEphemeral(text ?? "Canceled the running request.");
814
+ }
815
+ return { install, createCancelControl };
816
+ }
817
+ function resolveCancelOptions(options) {
818
+ if (!options?.cancel) {
819
+ return void 0;
820
+ }
821
+ const input = options.cancel === true ? {} : options.cancel;
822
+ return {
823
+ ...input,
824
+ visibleWhen: input.visibleWhen ?? "before-output",
825
+ canceledAck: input.canceledAck ?? "Canceled the running request.",
826
+ alreadyCompletedAck: input.alreadyCompletedAck ?? "That request is no longer running.",
827
+ unauthorizedAck: input.unauthorizedAck ?? "Only the user who started this request can cancel it."
828
+ };
829
+ }
830
+ function isWaitingForAgentStatus(status) {
831
+ return status === "processing" || status === "thinking" || status === "reasoning" || status === "calling-tool" || status === "waiting-approval" || status === "waiting-input";
832
+ }
833
+ function isTerminalClearReason(reason) {
834
+ return reason === "streaming-started" || reason === "turn-finished" || reason === "turn-error" || reason === "button-cancel";
835
+ }
836
+ function createSlackTurnCancelledError() {
837
+ return Object.assign(new Error("Slack turn was cancelled by the user."), {
838
+ category: "cancelled"
839
+ });
840
+ }
841
+
620
842
  // src/assistant/bridge.ts
621
843
  import { createSlackAssistantThreadContextStore } from "@cuylabs/channel-slack/assistant";
622
844
  function createSlackAssistantBridge(options) {
@@ -634,13 +856,20 @@ function createSlackAssistantBridge(options) {
634
856
  const feedbackConfig = options.feedback === false ? void 0 : options.feedback ?? {};
635
857
  const feedbackBlock = feedbackConfig ? createSlackFeedbackBlock(feedbackConfig) : void 0;
636
858
  const feedbackActionId = feedbackConfig?.actionId ?? SLACK_FEEDBACK_ACTION_ID;
859
+ const turnControlController = createSlackAssistantTurnControlController(
860
+ options.turnControls
861
+ );
862
+ const turnCancelActionId = turnControlController ? resolveSlackTurnCancelActionId2(
863
+ resolveTurnCancelActionIdOption(options.turnControls)
864
+ ) : void 0;
637
865
  const threadStarted = createThreadStartedHandler(options);
638
866
  const threadContextChanged = createThreadContextChangedHandler();
639
867
  const threadContextStore = options.threadContextStore ?? createSlackAssistantThreadContextStore();
640
868
  const userMessage = createUserMessageHandler({
641
869
  options,
642
870
  feedbackBlock,
643
- sessionStrategy
871
+ sessionStrategy,
872
+ ...turnControlController ? { turnControlController } : {}
644
873
  });
645
874
  const config = {
646
875
  threadStarted,
@@ -662,13 +891,21 @@ function createSlackAssistantBridge(options) {
662
891
  })
663
892
  });
664
893
  }
894
+ turnControlController?.install(app);
665
895
  }
666
896
  return {
667
897
  assistant,
668
898
  install,
669
- ...feedbackConfig ? { feedbackActionId } : {}
899
+ ...feedbackConfig ? { feedbackActionId } : {},
900
+ ...turnCancelActionId ? { turnCancelActionId } : {}
670
901
  };
671
902
  }
903
+ function resolveTurnCancelActionIdOption(options) {
904
+ if (!options || !options.cancel) {
905
+ return void 0;
906
+ }
907
+ return typeof options.cancel === "object" ? options.cancel.actionId : void 0;
908
+ }
672
909
 
673
910
  // src/assistant/index.ts
674
911
  import {
@@ -1,13 +1,12 @@
1
1
  import {
2
2
  createSlackAssistantBridge
3
- } from "./chunk-MGBNGG4D.js";
3
+ } from "./chunk-FJP6ZFUB.js";
4
4
  import {
5
- createSlackFeedbackBlock,
6
- registerSlackFeedbackAction
5
+ createSlackFeedbackBlock
7
6
  } from "./chunk-ELR6MQD7.js";
8
7
  import {
9
8
  createSlackChannelAdapter
10
- } from "./chunk-FQWFB54C.js";
9
+ } from "./chunk-XA7U3GRN.js";
11
10
 
12
11
  // src/app-surface.ts
13
12
  var DEFAULT_TIMEOUT_MS = 12e4;
@@ -49,7 +48,7 @@ function installSlackAgentAppSurface(boltApp, options) {
49
48
  ...resolveSession ? { resolveSession: toAssistantResolveSession(resolveSession) } : {},
50
49
  ...interactive ? { handleInteractiveRequest: interactive.handleInteractiveRequest } : {}
51
50
  });
52
- boltApp.assistant(bridge.assistant);
51
+ bridge.install(boltApp);
53
52
  const channelAdapter = createSlackChannelAdapter({
54
53
  source: channelSource,
55
54
  sessionStrategy: assistantBridgeOptions.sessionStrategy,
@@ -99,15 +98,6 @@ function installSlackAgentAppSurface(boltApp, options) {
99
98
  } : {}
100
99
  });
101
100
  channelAdapter.mount(boltApp);
102
- if (feedbackConfig) {
103
- const feedbackSessionStrategy = assistantBridgeOptions.sessionStrategy ?? "thread-aware";
104
- registerSlackFeedbackAction(boltApp, {
105
- ...feedbackConfig,
106
- resolveSessionId: (ctx) => resolveFeedbackSessionId(ctx, feedbackSessionStrategy),
107
- onFeedback: feedbackConfig.onFeedback ?? (async (_ctx) => {
108
- })
109
- });
110
- }
111
101
  interactive?.install(boltApp);
112
102
  viewWorkflows?.install(boltApp);
113
103
  return { bridge };
@@ -191,17 +181,6 @@ function formatErrorForLog(error) {
191
181
  }
192
182
  return String(error);
193
183
  }
194
- function resolveFeedbackSessionId(context, strategy) {
195
- const threadTs = context.threadTs ?? context.messageTs;
196
- switch (strategy) {
197
- case "channel-id":
198
- return context.channelId;
199
- case "user-per-thread":
200
- return `${context.channelId}:${threadTs}:${context.userId}`;
201
- default:
202
- return `${context.channelId}:${threadTs}`;
203
- }
204
- }
205
184
 
206
185
  export {
207
186
  installSlackAgentAppSurface
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  installSlackAgentAppSurface
3
- } from "./chunk-7DUO5BMW.js";
3
+ } from "./chunk-GKZRDNEB.js";
4
4
  import {
5
5
  createSlackAssistantBridge
6
- } from "./chunk-MGBNGG4D.js";
6
+ } from "./chunk-FJP6ZFUB.js";
7
7
 
8
8
  // src/socket.ts
9
9
  import { createSlackSocketBoltApp } from "@cuylabs/channel-slack/transports/socket";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createSlackAssistantBridge
3
- } from "./chunk-MGBNGG4D.js";
3
+ } from "./chunk-FJP6ZFUB.js";
4
4
 
5
5
  // src/express-assistant.ts
6
6
  import {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  installSlackAgentAppSurface
3
- } from "./chunk-7DUO5BMW.js";
3
+ } from "./chunk-GKZRDNEB.js";
4
4
 
5
5
  // src/app.ts
6
6
  import {