botinabox 1.8.4 → 1.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.
@@ -1,4 +1,7 @@
1
1
  import { C as ChannelAdapter, c as ChannelMeta, a as ChannelCapabilities, I as InboundMessage, b as ChannelConfig, H as HealthStatus, O as OutboundPayload, S as SendResult } from '../../channel-06G0vbIn.js';
2
+ import { H as HookBus, a as ChatPipeline } from '../../chat-pipeline-DisuC8SB.js';
3
+ import 'better-sqlite3';
4
+ import '../../provider-DLGUfnNx.js';
2
5
 
3
6
  /**
4
7
  * SlackAdapter — ChannelAdapter implementation for Slack.
@@ -159,4 +162,32 @@ interface SlackConfig {
159
162
  signingSecret?: string;
160
163
  }
161
164
 
162
- export { type BoltClient, SlackAdapter, type SlackConfig, type SlackEvent, type SlackFile, type TranscribeOptions, type TranscribeResult, createSlackAdapter as default, downloadAudio, enrichVoiceMessage, extractVoiceTranscript, formatForSlack, parseSlackEvent, transcribeAudio };
165
+ /**
166
+ * SlackBoltAdapter — real Bolt Socket Mode integration for botinabox.
167
+ *
168
+ * Handles:
169
+ * - Bolt app lifecycle (start, stop)
170
+ * - Inbound message parsing + self-filtering
171
+ * - response.ready → Slack message delivery
172
+ * - file.deliver → Slack file upload
173
+ *
174
+ * Apps just instantiate and start:
175
+ * const slack = new SlackBoltAdapter({ botToken, appToken, hooks, pipeline });
176
+ * await slack.start();
177
+ */
178
+
179
+ interface SlackBoltAdapterConfig {
180
+ botToken: string;
181
+ appToken: string;
182
+ hooks: HookBus;
183
+ pipeline: ChatPipeline;
184
+ }
185
+ declare class SlackBoltAdapter {
186
+ private app;
187
+ private config;
188
+ constructor(config: SlackBoltAdapterConfig);
189
+ start(): Promise<void>;
190
+ stop(): Promise<void>;
191
+ }
192
+
193
+ export { type BoltClient, SlackAdapter, SlackBoltAdapter, type SlackBoltAdapterConfig, type SlackConfig, type SlackEvent, type SlackFile, type TranscribeOptions, type TranscribeResult, createSlackAdapter as default, downloadAudio, enrichVoiceMessage, extractVoiceTranscript, formatForSlack, parseSlackEvent, transcribeAudio };
@@ -5,6 +5,9 @@ import {
5
5
  parseSlackEvent,
6
6
  transcribeAudio
7
7
  } from "../../chunk-NNPCKR6G.js";
8
+ import {
9
+ chunkText
10
+ } from "../../chunk-ZTZFPTOQ.js";
8
11
 
9
12
  // src/channels/slack/outbound.ts
10
13
  function formatForSlack(text) {
@@ -80,8 +83,87 @@ var SlackAdapter = class {
80
83
  function createSlackAdapter(client) {
81
84
  return new SlackAdapter(client);
82
85
  }
86
+
87
+ // src/channels/slack/bolt-adapter.ts
88
+ var SlackBoltAdapter = class {
89
+ app = null;
90
+ config;
91
+ constructor(config) {
92
+ this.config = config;
93
+ }
94
+ async start() {
95
+ const boltModule = "@slack/bolt";
96
+ const bolt = await import(boltModule);
97
+ const { enrichVoiceMessage: enrichVoiceMessage2 } = await import("../../inbound-ZJHAYVMF.js");
98
+ const boltApp = new bolt.App({
99
+ token: this.config.botToken,
100
+ appToken: this.config.appToken,
101
+ socketMode: true
102
+ });
103
+ this.app = boltApp;
104
+ const { hooks, pipeline, botToken } = this.config;
105
+ boltApp.event("message", async ({ event }) => {
106
+ if (event.bot_id || event.app_id) return;
107
+ const subtype = event.subtype;
108
+ if (subtype && subtype !== "file_share") return;
109
+ let inbound = parseSlackEvent(event);
110
+ inbound = { ...inbound, channel: "slack", account: event.channel };
111
+ if (!inbound.body) return;
112
+ if (inbound.body.includes("[Voice message \u2014 no transcript available]")) {
113
+ inbound = await enrichVoiceMessage2(inbound, botToken);
114
+ }
115
+ await hooks.emit("message.inbound", inbound);
116
+ });
117
+ hooks.register("response.ready", async (ctx) => {
118
+ const threadId = ctx.threadId;
119
+ const text = ctx.text;
120
+ const taskId = ctx.taskId;
121
+ if (!text) return;
122
+ const channelId = await pipeline.resolveChannel(threadId, taskId);
123
+ if (!channelId) return;
124
+ const formatted = formatForSlack(text);
125
+ const chunks = chunkText(formatted, 3800);
126
+ for (const chunk of chunks) {
127
+ await boltApp.client.chat.postMessage({
128
+ token: botToken,
129
+ channel: channelId,
130
+ text: chunk
131
+ });
132
+ }
133
+ }, { priority: 90 });
134
+ hooks.register("file.deliver", async (ctx) => {
135
+ const filePath = ctx.filePath;
136
+ const fileName = ctx.fileName;
137
+ const taskId = ctx.taskId;
138
+ const threadId = ctx.threadId;
139
+ const channelId = await pipeline.resolveChannel(threadId, taskId);
140
+ if (!channelId || !filePath) return;
141
+ try {
142
+ const { createReadStream, existsSync } = await import("fs");
143
+ const { basename } = await import("path");
144
+ if (existsSync(filePath)) {
145
+ await boltApp.client.filesUploadV2({
146
+ token: botToken,
147
+ channel_id: channelId,
148
+ file: createReadStream(filePath),
149
+ filename: basename(filePath),
150
+ title: fileName ?? basename(filePath)
151
+ });
152
+ }
153
+ } catch {
154
+ }
155
+ });
156
+ await boltApp.start();
157
+ }
158
+ async stop() {
159
+ if (this.app) {
160
+ await this.app.stop();
161
+ }
162
+ }
163
+ };
83
164
  export {
84
165
  SlackAdapter,
166
+ SlackBoltAdapter,
85
167
  createSlackAdapter as default,
86
168
  downloadAudio,
87
169
  enrichVoiceMessage,