@chat-adapter/slack 4.16.1 → 4.18.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/dist/index.d.ts CHANGED
@@ -59,6 +59,12 @@ declare class SlackFormatConverter extends BaseFormatConverter {
59
59
  * Parse Slack mrkdwn into an AST.
60
60
  */
61
61
  toAst(mrkdwn: string): Root;
62
+ /**
63
+ * Convert AST to Slack blocks, using a native table block for the first table.
64
+ * Returns null if the AST contains no tables (caller should use regular text).
65
+ * Slack allows at most one table block per message; additional tables use ASCII.
66
+ */
67
+ toBlocksWithTable(ast: Root): SlackBlock[] | null;
62
68
  private nodeToMrkdwn;
63
69
  }
64
70
 
@@ -81,10 +87,10 @@ interface SlackAdapterConfig {
81
87
  * Defaults to `slack:installation`. The full key will be `{prefix}:{teamId}`.
82
88
  */
83
89
  installationKeyPrefix?: string;
84
- /** Logger instance for error reporting */
85
- logger: Logger;
86
- /** Signing secret for webhook verification */
87
- signingSecret: string;
90
+ /** Logger instance for error reporting. Defaults to ConsoleLogger. */
91
+ logger?: Logger;
92
+ /** Signing secret for webhook verification. Defaults to SLACK_SIGNING_SECRET env var. */
93
+ signingSecret?: string;
88
94
  /** Override bot username (optional) */
89
95
  userName?: string;
90
96
  }
@@ -163,7 +169,7 @@ declare class SlackAdapter implements Adapter<SlackThreadId, unknown> {
163
169
  private readonly requestContext;
164
170
  /** Bot user ID (e.g., U_BOT_123) used for mention detection */
165
171
  get botUserId(): string | undefined;
166
- constructor(config: SlackAdapterConfig);
172
+ constructor(config?: SlackAdapterConfig);
167
173
  /**
168
174
  * Get the current bot token for API calls.
169
175
  * Checks request context (multi-workspace) → default token (single-workspace) → throws.
@@ -307,6 +313,11 @@ declare class SlackAdapter implements Adapter<SlackThreadId, unknown> {
307
313
  * Includes a fetchData method that uses the bot token for auth.
308
314
  */
309
315
  private createAttachment;
316
+ /**
317
+ * Try to render a message using native Slack table blocks.
318
+ * Returns blocks + fallback text if the message contains tables, null otherwise.
319
+ */
320
+ private renderWithTableBlocks;
310
321
  postMessage(threadId: string, message: AdapterPostableMessage): Promise<RawMessage<unknown>>;
311
322
  postEphemeral(threadId: string, userId: string, message: AdapterPostableMessage): Promise<EphemeralMessage>;
312
323
  openModal(triggerId: string, modal: ModalElement, contextId?: string): Promise<{
@@ -445,6 +456,6 @@ declare class SlackAdapter implements Adapter<SlackThreadId, unknown> {
445
456
  */
446
457
  private sendToResponseUrl;
447
458
  }
448
- declare function createSlackAdapter(config?: Partial<SlackAdapterConfig>): SlackAdapter;
459
+ declare function createSlackAdapter(config?: SlackAdapterConfig): SlackAdapter;
449
460
 
450
461
  export { type EncryptedTokenData, SlackAdapter, type SlackAdapterConfig, type SlackEvent, SlackFormatConverter, type SlackInstallation, SlackFormatConverter as SlackMarkdownConverter, type SlackReactionEvent, type SlackThreadId, cardToBlockKit, cardToFallbackText, createSlackAdapter, decodeKey };
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  defaultEmojiResolver,
18
18
  isJSX,
19
19
  Message,
20
+ parseMarkdown as parseMarkdown2,
20
21
  StreamingMarkdownRenderer,
21
22
  toModalElement
22
23
  } from "chat";
@@ -59,13 +60,14 @@ function cardToBlockKit(card) {
59
60
  alt_text: card.title || "Card image"
60
61
  });
61
62
  }
63
+ const state = { usedNativeTable: false };
62
64
  for (const child of card.children) {
63
- const childBlocks = convertChildToBlocks(child);
65
+ const childBlocks = convertChildToBlocks(child, state);
64
66
  blocks.push(...childBlocks);
65
67
  }
66
68
  return blocks;
67
69
  }
68
- function convertChildToBlocks(child) {
70
+ function convertChildToBlocks(child, state) {
69
71
  switch (child.type) {
70
72
  case "text":
71
73
  return [convertTextToBlock(child)];
@@ -76,13 +78,13 @@ function convertChildToBlocks(child) {
76
78
  case "actions":
77
79
  return [convertActionsToBlock(child)];
78
80
  case "section":
79
- return convertSectionToBlocks(child);
81
+ return convertSectionToBlocks(child, state);
80
82
  case "fields":
81
83
  return [convertFieldsToBlock(child)];
82
84
  case "link":
83
85
  return [convertLinkToBlock(child)];
84
86
  case "table":
85
- return convertTableToBlocks(child);
87
+ return convertTableToBlocks(child, state);
86
88
  default: {
87
89
  const text = cardChildToFallbackText(child);
88
90
  if (text) {
@@ -250,10 +252,10 @@ function convertRadioSelectToElement(radioSelect) {
250
252
  }
251
253
  return element;
252
254
  }
253
- function convertTableToBlocks(element) {
255
+ function convertTableToBlocks(element, state) {
254
256
  const MAX_ROWS = 100;
255
257
  const MAX_COLS = 20;
256
- if (element.rows.length > MAX_ROWS || element.headers.length > MAX_COLS) {
258
+ if (state.usedNativeTable || element.rows.length > MAX_ROWS || element.headers.length > MAX_COLS) {
257
259
  return [
258
260
  {
259
261
  type: "section",
@@ -266,31 +268,28 @@ ${tableElementToAscii(element.headers, element.rows)}
266
268
  }
267
269
  ];
268
270
  }
269
- const columns = element.headers.map((header, i) => ({
270
- id: `col_${i}`,
271
- header: {
272
- type: "plain_text",
273
- text: convertEmoji(header)
274
- }
271
+ state.usedNativeTable = true;
272
+ const headerRow = element.headers.map((header) => ({
273
+ type: "raw_text",
274
+ text: convertEmoji(header)
275
275
  }));
276
- const rows = element.rows.map((row) => ({
277
- cells: row.map((cell) => ({
278
- type: "plain_text",
276
+ const dataRows = element.rows.map(
277
+ (row) => row.map((cell) => ({
278
+ type: "raw_text",
279
279
  text: convertEmoji(cell)
280
280
  }))
281
- }));
281
+ );
282
282
  return [
283
283
  {
284
284
  type: "table",
285
- columns,
286
- rows
285
+ rows: [headerRow, ...dataRows]
287
286
  }
288
287
  ];
289
288
  }
290
- function convertSectionToBlocks(element) {
289
+ function convertSectionToBlocks(element, state) {
291
290
  const blocks = [];
292
291
  for (const child of element.children) {
293
- blocks.push(...convertChildToBlocks(child));
292
+ blocks.push(...convertChildToBlocks(child, state));
294
293
  }
295
294
  return blocks;
296
295
  }
@@ -428,16 +427,68 @@ var SlackFormatConverter = class extends BaseFormatConverter {
428
427
  */
429
428
  toAst(mrkdwn) {
430
429
  let markdown = mrkdwn;
431
- markdown = markdown.replace(/<@([^|>]+)\|([^>]+)>/g, "@$2");
432
- markdown = markdown.replace(/<@([^>]+)>/g, "@$1");
433
- markdown = markdown.replace(/<#[^|>]+\|([^>]+)>/g, "#$1");
434
- markdown = markdown.replace(/<#([^>]+)>/g, "#$1");
430
+ markdown = markdown.replace(/<@([A-Z0-9_]+)\|([^>]+)>/g, "@$2");
431
+ markdown = markdown.replace(/<@([A-Z0-9_]+)>/g, "@$1");
432
+ markdown = markdown.replace(/<#[A-Z0-9_]+\|([^>]+)>/g, "#$1");
433
+ markdown = markdown.replace(/<#([A-Z0-9_]+)>/g, "#$1");
435
434
  markdown = markdown.replace(/<(https?:\/\/[^|>]+)\|([^>]+)>/g, "[$2]($1)");
436
435
  markdown = markdown.replace(/<(https?:\/\/[^>]+)>/g, "$1");
437
436
  markdown = markdown.replace(/(?<![_*\\])\*([^*\n]+)\*(?![_*])/g, "**$1**");
438
437
  markdown = markdown.replace(/(?<!~)~([^~\n]+)~(?!~)/g, "~~$1~~");
439
438
  return parseMarkdown(markdown);
440
439
  }
440
+ /**
441
+ * Convert AST to Slack blocks, using a native table block for the first table.
442
+ * Returns null if the AST contains no tables (caller should use regular text).
443
+ * Slack allows at most one table block per message; additional tables use ASCII.
444
+ */
445
+ toBlocksWithTable(ast) {
446
+ const hasTable = ast.children.some((node) => isTableNode(node));
447
+ if (!hasTable) {
448
+ return null;
449
+ }
450
+ const blocks = [];
451
+ let usedNativeTable = false;
452
+ let textBuffer = [];
453
+ const flushText = () => {
454
+ if (textBuffer.length > 0) {
455
+ const text = textBuffer.join("\n\n");
456
+ if (text.trim()) {
457
+ blocks.push({
458
+ type: "section",
459
+ text: { type: "mrkdwn", text }
460
+ });
461
+ }
462
+ textBuffer = [];
463
+ }
464
+ };
465
+ for (const child of ast.children) {
466
+ const node = child;
467
+ if (isTableNode(node)) {
468
+ flushText();
469
+ if (usedNativeTable) {
470
+ blocks.push({
471
+ type: "section",
472
+ text: {
473
+ type: "mrkdwn",
474
+ text: `\`\`\`
475
+ ${tableToAscii(node)}
476
+ \`\`\``
477
+ }
478
+ });
479
+ } else {
480
+ blocks.push(
481
+ mdastTableToSlackBlock(node, this.nodeToMrkdwn.bind(this))
482
+ );
483
+ usedNativeTable = true;
484
+ }
485
+ } else {
486
+ textBuffer.push(this.nodeToMrkdwn(node));
487
+ }
488
+ }
489
+ flushText();
490
+ return blocks;
491
+ }
441
492
  nodeToMrkdwn(node) {
442
493
  if (isParagraphNode(node)) {
443
494
  return getNodeChildren(node).map((child) => this.nodeToMrkdwn(child)).join("");
@@ -489,6 +540,26 @@ ${tableToAscii(node)}
489
540
  return this.defaultNodeToText(node, (child) => this.nodeToMrkdwn(child));
490
541
  }
491
542
  };
543
+ function mdastTableToSlackBlock(node, cellConverter) {
544
+ const rows = [];
545
+ for (const row of node.children) {
546
+ const cells = getNodeChildren(row).map((cell) => ({
547
+ type: "raw_text",
548
+ text: getNodeChildren(cell).map(cellConverter).join("")
549
+ }));
550
+ rows.push(cells);
551
+ }
552
+ const block = { type: "table", rows };
553
+ if (node.align) {
554
+ const columnSettings = node.align.map(
555
+ (a) => ({
556
+ align: a || "left"
557
+ })
558
+ );
559
+ block.column_settings = columnSettings;
560
+ }
561
+ return block;
562
+ }
492
563
 
493
564
  // src/modals.ts
494
565
  function encodeModalMetadata(meta) {
@@ -636,6 +707,7 @@ function radioSelectToBlock(radioSelect) {
636
707
  }
637
708
 
638
709
  // src/index.ts
710
+ var SLACK_USER_ID_PATTERN = /^[A-Z0-9_]+$/;
639
711
  var SlackAdapter = class _SlackAdapter {
640
712
  name = "slack";
641
713
  userName;
@@ -664,18 +736,28 @@ var SlackAdapter = class _SlackAdapter {
664
736
  }
665
737
  return this._botUserId || void 0;
666
738
  }
667
- constructor(config) {
668
- this.client = new WebClient(config.botToken);
669
- this.signingSecret = config.signingSecret;
670
- this.defaultBotToken = config.botToken;
671
- this.logger = config.logger;
739
+ constructor(config = {}) {
740
+ const signingSecret = config.signingSecret ?? process.env.SLACK_SIGNING_SECRET;
741
+ if (!signingSecret) {
742
+ throw new ValidationError(
743
+ "slack",
744
+ "signingSecret is required. Set SLACK_SIGNING_SECRET or provide it in config."
745
+ );
746
+ }
747
+ const zeroConfig = !(config.signingSecret || config.botToken || config.clientId || config.clientSecret);
748
+ const botToken = config.botToken ?? (zeroConfig ? process.env.SLACK_BOT_TOKEN : void 0);
749
+ this.client = new WebClient(botToken);
750
+ this.signingSecret = signingSecret;
751
+ this.defaultBotToken = botToken;
752
+ this.logger = config.logger ?? new ConsoleLogger("info").child("slack");
672
753
  this.userName = config.userName || "bot";
673
754
  this._botUserId = config.botUserId || null;
674
- this.clientId = config.clientId;
675
- this.clientSecret = config.clientSecret;
755
+ this.clientId = config.clientId ?? (zeroConfig ? process.env.SLACK_CLIENT_ID : void 0);
756
+ this.clientSecret = config.clientSecret ?? (zeroConfig ? process.env.SLACK_CLIENT_SECRET : void 0);
676
757
  this.installationKeyPrefix = config.installationKeyPrefix ?? "slack:installation";
677
- if (config.encryptionKey) {
678
- this.encryptionKey = decodeKey(config.encryptionKey);
758
+ const encryptionKey = config.encryptionKey ?? process.env.SLACK_ENCRYPTION_KEY;
759
+ if (encryptionKey) {
760
+ this.encryptionKey = decodeKey(encryptionKey);
679
761
  }
680
762
  }
681
763
  /**
@@ -1281,7 +1363,28 @@ var SlackAdapter = class _SlackAdapter {
1281
1363
  this.logger.warn("Chat instance not initialized, ignoring event");
1282
1364
  return;
1283
1365
  }
1284
- if (event.subtype && event.subtype !== "bot_message") {
1366
+ const ignoredSubtypes = /* @__PURE__ */ new Set([
1367
+ "message_changed",
1368
+ "message_deleted",
1369
+ "message_replied",
1370
+ "channel_join",
1371
+ "channel_leave",
1372
+ "channel_topic",
1373
+ "channel_purpose",
1374
+ "channel_name",
1375
+ "channel_archive",
1376
+ "channel_unarchive",
1377
+ "group_join",
1378
+ "group_leave",
1379
+ "group_topic",
1380
+ "group_purpose",
1381
+ "group_name",
1382
+ "group_archive",
1383
+ "group_unarchive",
1384
+ "ekm_access_denied",
1385
+ "tombstone"
1386
+ ]);
1387
+ if (event.subtype && ignoredSubtypes.has(event.subtype)) {
1285
1388
  this.logger.debug("Ignoring message subtype", {
1286
1389
  subtype: event.subtype
1287
1390
  });
@@ -1538,12 +1641,22 @@ var SlackAdapter = class _SlackAdapter {
1538
1641
  * detection doesn't apply.
1539
1642
  */
1540
1643
  async resolveInlineMentions(text, skipSelfMention) {
1541
- const mentionPattern = /<@([A-Z0-9]+)(?:\|[^>]*)?>/g;
1542
1644
  const userIds = /* @__PURE__ */ new Set();
1543
- let match = mentionPattern.exec(text);
1544
- while (match) {
1545
- userIds.add(match[1]);
1546
- match = mentionPattern.exec(text);
1645
+ for (const segment of text.split("<")) {
1646
+ const end = segment.indexOf(">");
1647
+ if (end === -1) {
1648
+ continue;
1649
+ }
1650
+ const inner = segment.slice(0, end);
1651
+ if (!inner.startsWith("@")) {
1652
+ continue;
1653
+ }
1654
+ const rest = inner.slice(1);
1655
+ const pipeIdx = rest.indexOf("|");
1656
+ const uid = pipeIdx >= 0 ? rest.slice(0, pipeIdx) : rest;
1657
+ if (SLACK_USER_ID_PATTERN.test(uid)) {
1658
+ userIds.add(uid);
1659
+ }
1547
1660
  }
1548
1661
  if (userIds.size === 0) {
1549
1662
  return text;
@@ -1561,10 +1674,29 @@ var SlackAdapter = class _SlackAdapter {
1561
1674
  })
1562
1675
  );
1563
1676
  const nameMap = new Map(lookups);
1564
- return text.replace(/<@([A-Z0-9]+)(?:\|[^>]*)?>/g, (_m, uid) => {
1565
- const name = nameMap.get(uid);
1566
- return name ? `<@${uid}|${name}>` : `<@${uid}>`;
1567
- });
1677
+ let result = "";
1678
+ let remaining = text;
1679
+ let startIdx = remaining.indexOf("<@");
1680
+ while (startIdx !== -1) {
1681
+ result += remaining.slice(0, startIdx);
1682
+ remaining = remaining.slice(startIdx);
1683
+ const endIdx = remaining.indexOf(">");
1684
+ if (endIdx === -1) {
1685
+ break;
1686
+ }
1687
+ const inner = remaining.slice(2, endIdx);
1688
+ const pipeIdx = inner.indexOf("|");
1689
+ const uid = pipeIdx >= 0 ? inner.slice(0, pipeIdx) : inner;
1690
+ if (SLACK_USER_ID_PATTERN.test(uid)) {
1691
+ const name = nameMap.get(uid);
1692
+ result += name ? `<@${uid}|${name}>` : `<@${uid}>`;
1693
+ } else {
1694
+ result += remaining.slice(0, endIdx + 1);
1695
+ }
1696
+ remaining = remaining.slice(endIdx + 1);
1697
+ startIdx = remaining.indexOf("<@");
1698
+ }
1699
+ return result + remaining;
1568
1700
  }
1569
1701
  async parseSlackMessage(event, threadId, options) {
1570
1702
  const isMe = this.isMessageFromSelf(event);
@@ -1641,13 +1773,39 @@ var SlackAdapter = class _SlackAdapter {
1641
1773
  } : void 0
1642
1774
  };
1643
1775
  }
1776
+ /**
1777
+ * Try to render a message using native Slack table blocks.
1778
+ * Returns blocks + fallback text if the message contains tables, null otherwise.
1779
+ */
1780
+ renderWithTableBlocks(message) {
1781
+ let ast = null;
1782
+ if (typeof message === "object" && message !== null) {
1783
+ if ("ast" in message) {
1784
+ ast = message.ast;
1785
+ } else if ("markdown" in message) {
1786
+ ast = parseMarkdown2(message.markdown);
1787
+ }
1788
+ }
1789
+ if (!ast) {
1790
+ return null;
1791
+ }
1792
+ const blocks = this.formatConverter.toBlocksWithTable(ast);
1793
+ if (!blocks) {
1794
+ return null;
1795
+ }
1796
+ const fallbackText = convertEmojiPlaceholders(
1797
+ this.formatConverter.renderPostable(message),
1798
+ "slack"
1799
+ );
1800
+ return { text: fallbackText, blocks };
1801
+ }
1644
1802
  async postMessage(threadId, message) {
1645
1803
  const { channel, threadTs } = this.decodeThreadId(threadId);
1646
1804
  try {
1647
1805
  const files = extractFiles(message);
1648
1806
  if (files.length > 0) {
1649
1807
  await this.uploadFiles(files, channel, threadTs || void 0);
1650
- const hasText = typeof message === "string" || typeof message === "object" && message !== null && ("raw" in message || "markdown" in message || "ast" in message);
1808
+ const hasText = typeof message === "string" || typeof message === "object" && message !== null && ("raw" in message && message.raw || "markdown" in message && message.markdown || "ast" in message && message.ast);
1651
1809
  const card2 = extractCard(message);
1652
1810
  if (!(hasText || card2)) {
1653
1811
  return {
@@ -1687,6 +1845,33 @@ var SlackAdapter = class _SlackAdapter {
1687
1845
  raw: result2
1688
1846
  };
1689
1847
  }
1848
+ const tableResult = this.renderWithTableBlocks(message);
1849
+ if (tableResult) {
1850
+ this.logger.debug("Slack API: chat.postMessage (table blocks)", {
1851
+ channel,
1852
+ threadTs,
1853
+ blockCount: tableResult.blocks.length
1854
+ });
1855
+ const result2 = await this.client.chat.postMessage(
1856
+ this.withToken({
1857
+ channel,
1858
+ thread_ts: threadTs,
1859
+ text: tableResult.text,
1860
+ blocks: tableResult.blocks,
1861
+ unfurl_links: false,
1862
+ unfurl_media: false
1863
+ })
1864
+ );
1865
+ this.logger.debug("Slack API: chat.postMessage response", {
1866
+ messageId: result2.ts,
1867
+ ok: result2.ok
1868
+ });
1869
+ return {
1870
+ id: result2.ts,
1871
+ threadId,
1872
+ raw: result2
1873
+ };
1874
+ }
1690
1875
  const text = convertEmojiPlaceholders(
1691
1876
  this.formatConverter.renderPostable(message),
1692
1877
  "slack"
@@ -1751,6 +1936,34 @@ var SlackAdapter = class _SlackAdapter {
1751
1936
  raw: result2
1752
1937
  };
1753
1938
  }
1939
+ const tableResult = this.renderWithTableBlocks(message);
1940
+ if (tableResult) {
1941
+ this.logger.debug("Slack API: chat.postEphemeral (table blocks)", {
1942
+ channel,
1943
+ threadTs,
1944
+ userId,
1945
+ blockCount: tableResult.blocks.length
1946
+ });
1947
+ const result2 = await this.client.chat.postEphemeral(
1948
+ this.withToken({
1949
+ channel,
1950
+ thread_ts: threadTs || void 0,
1951
+ user: userId,
1952
+ text: tableResult.text,
1953
+ blocks: tableResult.blocks
1954
+ })
1955
+ );
1956
+ this.logger.debug("Slack API: chat.postEphemeral response", {
1957
+ messageTs: result2.message_ts,
1958
+ ok: result2.ok
1959
+ });
1960
+ return {
1961
+ id: result2.message_ts || "",
1962
+ threadId,
1963
+ usedFallback: false,
1964
+ raw: result2
1965
+ };
1966
+ }
1754
1967
  const text = convertEmojiPlaceholders(
1755
1968
  this.formatConverter.renderPostable(message),
1756
1969
  "slack"
@@ -1927,6 +2140,31 @@ var SlackAdapter = class _SlackAdapter {
1927
2140
  raw: result2
1928
2141
  };
1929
2142
  }
2143
+ const tableResult = this.renderWithTableBlocks(message);
2144
+ if (tableResult) {
2145
+ this.logger.debug("Slack API: chat.update (table blocks)", {
2146
+ channel,
2147
+ messageId,
2148
+ blockCount: tableResult.blocks.length
2149
+ });
2150
+ const result2 = await this.client.chat.update(
2151
+ this.withToken({
2152
+ channel,
2153
+ ts: messageId,
2154
+ text: tableResult.text,
2155
+ blocks: tableResult.blocks
2156
+ })
2157
+ );
2158
+ this.logger.debug("Slack API: chat.update response", {
2159
+ messageId: result2.ts,
2160
+ ok: result2.ok
2161
+ });
2162
+ return {
2163
+ id: result2.ts,
2164
+ threadId,
2165
+ raw: result2
2166
+ };
2167
+ }
1930
2168
  const text = convertEmojiPlaceholders(
1931
2169
  this.formatConverter.renderPostable(message),
1932
2170
  "slack"
@@ -2733,13 +2971,22 @@ var SlackAdapter = class _SlackAdapter {
2733
2971
  blocks: cardToBlockKit(card)
2734
2972
  };
2735
2973
  } else {
2736
- payload = {
2737
- replace_original: true,
2738
- text: convertEmojiPlaceholders(
2739
- this.formatConverter.renderPostable(message),
2740
- "slack"
2741
- )
2742
- };
2974
+ const tableResult = this.renderWithTableBlocks(message);
2975
+ if (tableResult) {
2976
+ payload = {
2977
+ replace_original: true,
2978
+ text: tableResult.text,
2979
+ blocks: tableResult.blocks
2980
+ };
2981
+ } else {
2982
+ payload = {
2983
+ replace_original: true,
2984
+ text: convertEmojiPlaceholders(
2985
+ this.formatConverter.renderPostable(message),
2986
+ "slack"
2987
+ )
2988
+ };
2989
+ }
2743
2990
  }
2744
2991
  if (options?.threadTs) {
2745
2992
  payload.thread_ts = options.threadTs;
@@ -2778,26 +3025,7 @@ var SlackAdapter = class _SlackAdapter {
2778
3025
  }
2779
3026
  };
2780
3027
  function createSlackAdapter(config) {
2781
- const signingSecret = config?.signingSecret ?? process.env.SLACK_SIGNING_SECRET;
2782
- if (!signingSecret) {
2783
- throw new ValidationError(
2784
- "slack",
2785
- "signingSecret is required. Set SLACK_SIGNING_SECRET or provide it in config."
2786
- );
2787
- }
2788
- const zeroConfig = !config;
2789
- const resolved = {
2790
- signingSecret,
2791
- botToken: config?.botToken ?? (zeroConfig ? process.env.SLACK_BOT_TOKEN : void 0),
2792
- clientId: config?.clientId ?? (zeroConfig ? process.env.SLACK_CLIENT_ID : void 0),
2793
- clientSecret: config?.clientSecret ?? (zeroConfig ? process.env.SLACK_CLIENT_SECRET : void 0),
2794
- encryptionKey: config?.encryptionKey ?? process.env.SLACK_ENCRYPTION_KEY,
2795
- installationKeyPrefix: config?.installationKeyPrefix,
2796
- logger: config?.logger ?? new ConsoleLogger("info").child("slack"),
2797
- userName: config?.userName,
2798
- botUserId: config?.botUserId
2799
- };
2800
- return new SlackAdapter(resolved);
3028
+ return new SlackAdapter(config ?? {});
2801
3029
  }
2802
3030
  export {
2803
3031
  SlackAdapter,