@agentforge/tools 0.8.2 → 0.9.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @agentforge/tools
2
2
 
3
- > Production-ready tools collection for AgentForge - 70 tools for web, data, file, utility, and agent operations
3
+ > Production-ready tools collection for AgentForge - 74 tools for web, data, file, utility, and agent operations
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@agentforge/tools)](https://www.npmjs.com/package/@agentforge/tools)
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue)](https://www.typescriptlang.org/)
@@ -8,7 +8,7 @@
8
8
 
9
9
  ## 🎉 Status: Production Ready & Published
10
10
 
11
- **70 production-ready tools** | **Full TypeScript support** | **Comprehensive documentation** | **LangChain compatible**
11
+ **74 production-ready tools** | **Full TypeScript support** | **Comprehensive documentation** | **LangChain compatible**
12
12
 
13
13
  ## 📦 Installation
14
14
 
@@ -22,9 +22,9 @@ yarn add @agentforge/tools
22
22
 
23
23
  ## 🎯 Overview
24
24
 
25
- This package provides **70 ready-to-use tools** organized into 5 categories:
25
+ This package provides **74 ready-to-use tools** organized into 5 categories:
26
26
 
27
- - **🌐 Web Tools** (11 tools) - HTTP requests, web search, web scraping, HTML parsing, URL manipulation
27
+ - **🌐 Web Tools** (15 tools) - HTTP requests, web search, web scraping, HTML parsing, URL manipulation, Slack integration
28
28
  - **📊 Data Tools** (18 tools) - JSON, CSV, XML processing and data transformation
29
29
  - **📁 File Tools** (18 tools) - File operations, directory management, path utilities
30
30
  - **🔧 Utility Tools** (22 tools) - Date/time, strings, math, validation
@@ -96,6 +96,13 @@ Tools for web interactions and HTTP operations.
96
96
  - **`urlBuilder`** - Build URLs from components
97
97
  - **`urlQueryParser`** - Parse query parameters
98
98
 
99
+ #### Slack Tools
100
+ - **`sendSlackMessage`** - Send messages to Slack channels
101
+ - **`notifySlack`** - Send notifications with @mentions
102
+ - **`getSlackChannels`** - List available Slack channels
103
+ - **`getSlackMessages`** - Read message history from channels
104
+ - **`createSlackTools()`** - Factory function for custom Slack configuration
105
+
99
106
  ### 📊 Data Tools (18 tools)
100
107
 
101
108
  Tools for data processing and transformation.
@@ -287,6 +294,71 @@ console.log(result.links);
287
294
  console.log(result.metadata);
288
295
  ```
289
296
 
297
+ ### Slack Integration Example
298
+
299
+ ```typescript
300
+ import {
301
+ sendSlackMessage,
302
+ notifySlack,
303
+ getSlackChannels,
304
+ getSlackMessages,
305
+ createSlackTools
306
+ } from '@agentforge/tools';
307
+
308
+ // Send a simple message
309
+ const message = await sendSlackMessage.execute({
310
+ channel: 'general',
311
+ message: 'Hello from AgentForge!'
312
+ });
313
+
314
+ // Send a notification with mentions
315
+ const notification = await notifySlack.execute({
316
+ channel: 'alerts',
317
+ message: 'System alert: High CPU usage detected',
318
+ mentions: ['john', 'jane'] // Will send as: @john @jane System alert...
319
+ });
320
+
321
+ // List available channels
322
+ const channels = await getSlackChannels.execute({
323
+ include_private: false // Only public channels
324
+ });
325
+ console.log(channels.data?.channels);
326
+
327
+ // Read message history
328
+ const history = await getSlackMessages.execute({
329
+ channel: 'general',
330
+ limit: 50
331
+ });
332
+ console.log(`Found ${history.data?.count} messages`);
333
+
334
+ // Custom configuration (for multiple workspaces or custom bot settings)
335
+ const customTools = createSlackTools({
336
+ token: 'xoxb-your-custom-token',
337
+ botName: 'My Custom Bot',
338
+ botIcon: ':rocket:'
339
+ });
340
+
341
+ await customTools.sendMessage.execute({
342
+ channel: 'general',
343
+ message: 'Message from custom bot!'
344
+ });
345
+ ```
346
+
347
+ **Environment Setup:**
348
+ ```bash
349
+ # Add to your .env file
350
+ SLACK_USER_TOKEN=xoxp-your-user-token
351
+ # OR
352
+ SLACK_BOT_TOKEN=xoxb-your-bot-token
353
+ ```
354
+
355
+ **Getting a Slack Token:**
356
+ 1. Go to [Slack API](https://api.slack.com/apps)
357
+ 2. Create a new app or select existing
358
+ 3. Add OAuth scopes: `chat:write`, `channels:read`, `channels:history`
359
+ 4. Install app to workspace
360
+ 5. Copy the token (starts with `xoxb-` for bot or `xoxp-` for user)
361
+
290
362
  ### Data Processing Example
291
363
 
292
364
  ```typescript
@@ -522,12 +594,13 @@ pnpm lint
522
594
 
523
595
  ## 📊 Tool Statistics
524
596
 
525
- - **Total Tools**: 69
526
- - **Web Tools**: 11
597
+ - **Total Tools**: 74
598
+ - **Web Tools**: 15 (includes 4 Slack tools)
527
599
  - **Data Tools**: 18
528
600
  - **File Tools**: 18
529
601
  - **Utility Tools**: 22
530
- - **Lines of Code**: ~2,500
602
+ - **Agent Tools**: 1
603
+ - **Lines of Code**: ~3,200
531
604
  - **Full TypeScript Support**: ✅
532
605
  - **Zod Validation**: ✅
533
606
  - **LangChain Compatible**: ✅
package/dist/index.cjs CHANGED
@@ -4,6 +4,7 @@ var core = require('@agentforge/core');
4
4
  var zod = require('zod');
5
5
  var axios = require('axios');
6
6
  var cheerio2 = require('cheerio');
7
+ var webApi = require('@slack/web-api');
7
8
  var sync = require('csv-parse/sync');
8
9
  var sync$1 = require('csv-stringify/sync');
9
10
  var fastXmlParser = require('fast-xml-parser');
@@ -682,6 +683,381 @@ var webSearch = core.toolBuilder().name("web-search").description(
682
683
  };
683
684
  }
684
685
  }).build();
686
+ var logLevel = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
687
+ var logger = core.createLogger("tools:slack", { level: logLevel });
688
+ var defaultSlackClient = null;
689
+ function getDefaultSlackClient() {
690
+ if (!defaultSlackClient) {
691
+ const token = process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN;
692
+ if (!token) {
693
+ throw new Error(
694
+ "Slack token not configured. Please set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
695
+ );
696
+ }
697
+ defaultSlackClient = new webApi.WebClient(token);
698
+ }
699
+ return defaultSlackClient;
700
+ }
701
+ var sendSlackMessage = core.toolBuilder().name("send-slack-message").description("Send a message to a Slack channel for team communication and notifications").category(core.ToolCategory.WEB).tags(["slack", "messaging", "communication"]).usageNotes(
702
+ "Use this for general team communication. For notifications with @mentions, consider using notify-slack instead. Use get-slack-channels first if you need to find the right channel."
703
+ ).suggests(["get-slack-channels"]).schema(
704
+ zod.z.object({
705
+ channel: zod.z.string().describe("Channel name (e.g., 'general') or ID (e.g., 'C123456')"),
706
+ message: zod.z.string().describe("Message content to send")
707
+ })
708
+ ).implementSafe(async ({ channel, message }) => {
709
+ logger.info("send-slack-message called", { channel, messageLength: message.length });
710
+ try {
711
+ const slack = getDefaultSlackClient();
712
+ const result = await slack.chat.postMessage({
713
+ channel,
714
+ text: message,
715
+ username: "AgentForge Bot",
716
+ icon_emoji: ":robot_face:"
717
+ });
718
+ logger.info("send-slack-message result", {
719
+ channel: result.channel,
720
+ timestamp: result.ts,
721
+ messageLength: message.length,
722
+ success: true
723
+ });
724
+ return {
725
+ channel: result.channel,
726
+ message,
727
+ timestamp: result.ts,
728
+ message_id: result.ts
729
+ };
730
+ } catch (error) {
731
+ logger.error("send-slack-message failed", {
732
+ channel,
733
+ error: error.message,
734
+ data: error.data
735
+ });
736
+ throw error;
737
+ }
738
+ }).build();
739
+ var notifySlack = core.toolBuilder().name("notify-slack").description("Send a notification to a Slack channel with optional @mentions for urgent alerts").category(core.ToolCategory.WEB).tags(["slack", "notification", "alert"]).usageNotes(
740
+ "Use this for urgent notifications that require @mentions. For general messages without mentions, use send-slack-message instead."
741
+ ).suggests(["get-slack-channels"]).schema(
742
+ zod.z.object({
743
+ channel: zod.z.string().describe("Channel name or ID"),
744
+ message: zod.z.string().describe("Notification message"),
745
+ mentions: zod.z.array(zod.z.string()).optional().describe("List of usernames to mention (without @)")
746
+ })
747
+ ).implementSafe(async ({ channel, message, mentions = [] }) => {
748
+ logger.info("notify-slack called", {
749
+ channel,
750
+ messageLength: message.length,
751
+ mentionCount: mentions.length
752
+ });
753
+ const slack = getDefaultSlackClient();
754
+ const mentionText = mentions.length > 0 ? mentions.map((m) => `<@${m}>`).join(" ") + " " : "";
755
+ const fullMessage = `${mentionText}${message}`;
756
+ const result = await slack.chat.postMessage({
757
+ channel,
758
+ text: fullMessage,
759
+ username: "AgentForge Bot",
760
+ icon_emoji: ":robot_face:"
761
+ });
762
+ logger.info("notify-slack result", {
763
+ channel: result.channel,
764
+ timestamp: result.ts,
765
+ mentions: mentions.length
766
+ });
767
+ return {
768
+ channel: result.channel,
769
+ message: fullMessage,
770
+ mentions,
771
+ timestamp: result.ts,
772
+ notification_id: result.ts
773
+ };
774
+ }).build();
775
+ var getSlackChannels = core.toolBuilder().name("get-slack-channels").description("Get a list of available Slack channels to find the right channel for messaging").category(core.ToolCategory.WEB).tags(["slack", "channels", "list"]).usageNotes(
776
+ "Use this first to discover available channels before sending messages. Helps ensure you are sending to the correct channel."
777
+ ).follows(["send-slack-message", "notify-slack"]).schema(
778
+ zod.z.object({
779
+ include_private: zod.z.boolean().optional().describe("Include private channels (default: false)")
780
+ })
781
+ ).implementSafe(async ({ include_private = false }) => {
782
+ logger.info("get-slack-channels called", { include_private });
783
+ const slack = getDefaultSlackClient();
784
+ const publicChannels = await slack.conversations.list({
785
+ types: "public_channel",
786
+ exclude_archived: true
787
+ });
788
+ let allChannels = publicChannels.channels || [];
789
+ if (include_private) {
790
+ const privateChannels = await slack.conversations.list({
791
+ types: "private_channel",
792
+ exclude_archived: true
793
+ });
794
+ allChannels = [...allChannels, ...privateChannels.channels || []];
795
+ }
796
+ logger.info("get-slack-channels result", {
797
+ channelCount: allChannels.length,
798
+ includePrivate: include_private
799
+ });
800
+ return {
801
+ count: allChannels.length,
802
+ channels: allChannels.map((c) => ({
803
+ id: c.id,
804
+ name: c.name,
805
+ is_private: c.is_private || false,
806
+ num_members: c.num_members || 0
807
+ }))
808
+ };
809
+ }).build();
810
+ var getSlackMessages = core.toolBuilder().name("get-slack-messages").description("Retrieve message history from a Slack channel to read recent conversations").category(core.ToolCategory.WEB).tags(["slack", "messages", "history", "read"]).usageNotes(
811
+ "Use this to read recent messages from a channel. Use get-slack-channels first if you need to find the channel ID. Returns messages in reverse chronological order (newest first)."
812
+ ).suggests(["get-slack-channels"]).schema(
813
+ zod.z.object({
814
+ channel: zod.z.string().describe("Channel name (e.g., 'general') or ID (e.g., 'C123456')"),
815
+ limit: zod.z.number().int().min(1).max(100).optional().describe("Number of messages to retrieve (default: 20, max: 100)")
816
+ })
817
+ ).implementSafe(async ({ channel, limit = 20 }) => {
818
+ logger.info("get-slack-messages called", { channel, limit });
819
+ try {
820
+ const slack = getDefaultSlackClient();
821
+ let channelId = channel;
822
+ if (!channel.startsWith("C") && !channel.startsWith("D")) {
823
+ const channels = await slack.conversations.list({
824
+ types: "public_channel,private_channel",
825
+ exclude_archived: true
826
+ });
827
+ const found = channels.channels?.find((c) => c.name === channel);
828
+ if (!found) {
829
+ logger.error("get-slack-messages: channel not found", { channel });
830
+ throw new Error(
831
+ `Channel '${channel}' not found. Use get-slack-channels to see available channels.`
832
+ );
833
+ }
834
+ channelId = found.id;
835
+ }
836
+ const result = await slack.conversations.history({
837
+ channel: channelId,
838
+ limit: Math.min(limit, 100)
839
+ // Cap at 100 for performance
840
+ });
841
+ logger.info("get-slack-messages result", {
842
+ channel: channelId,
843
+ messageCount: result.messages?.length || 0,
844
+ limit
845
+ });
846
+ return {
847
+ channel: channelId,
848
+ count: result.messages?.length || 0,
849
+ messages: result.messages?.map((m) => ({
850
+ user: m.user || "unknown",
851
+ text: m.text || "",
852
+ timestamp: m.ts,
853
+ thread_ts: m.thread_ts,
854
+ type: m.type,
855
+ subtype: m.subtype
856
+ })) || []
857
+ };
858
+ } catch (error) {
859
+ logger.error("get-slack-messages failed", {
860
+ channel,
861
+ error: error.message,
862
+ data: error.data
863
+ });
864
+ throw error;
865
+ }
866
+ }).build();
867
+ function createSlackTools(config = {}) {
868
+ const {
869
+ token,
870
+ botName = "AgentForge Bot",
871
+ botIcon = ":robot_face:",
872
+ logLevel: customLogLevel
873
+ } = config;
874
+ let configuredClient = null;
875
+ function getConfiguredSlackClient() {
876
+ if (!configuredClient) {
877
+ const slackToken = token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN;
878
+ if (!slackToken) {
879
+ throw new Error(
880
+ "Slack token not configured. Please provide a token in config or set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
881
+ );
882
+ }
883
+ configuredClient = new webApi.WebClient(slackToken);
884
+ }
885
+ return configuredClient;
886
+ }
887
+ const toolLogger = customLogLevel ? core.createLogger("tools:slack", { level: customLogLevel }) : logger;
888
+ const sendMessage = core.toolBuilder().name("send-slack-message").description("Send a message to a Slack channel for team communication and notifications").category(core.ToolCategory.WEB).tags(["slack", "messaging", "communication"]).usageNotes(
889
+ "Use this for general team communication. For notifications with @mentions, consider using notify-slack instead. Use get-slack-channels first if you need to find the right channel."
890
+ ).suggests(["get-slack-channels"]).schema(
891
+ zod.z.object({
892
+ channel: zod.z.string().describe("Channel name (e.g., 'general') or ID (e.g., 'C123456')"),
893
+ message: zod.z.string().describe("Message content to send")
894
+ })
895
+ ).implementSafe(async ({ channel, message }) => {
896
+ toolLogger.info("send-slack-message called", { channel, messageLength: message.length });
897
+ try {
898
+ const slack = getConfiguredSlackClient();
899
+ const result = await slack.chat.postMessage({
900
+ channel,
901
+ text: message,
902
+ username: botName,
903
+ icon_emoji: botIcon
904
+ });
905
+ toolLogger.info("send-slack-message result", {
906
+ channel: result.channel,
907
+ timestamp: result.ts,
908
+ messageLength: message.length,
909
+ success: true
910
+ });
911
+ return {
912
+ channel: result.channel,
913
+ message,
914
+ timestamp: result.ts,
915
+ message_id: result.ts
916
+ };
917
+ } catch (error) {
918
+ toolLogger.error("send-slack-message failed", {
919
+ channel,
920
+ error: error.message,
921
+ data: error.data
922
+ });
923
+ throw error;
924
+ }
925
+ }).build();
926
+ const notify = core.toolBuilder().name("notify-slack").description("Send a notification to a Slack channel with optional @mentions for urgent alerts").category(core.ToolCategory.WEB).tags(["slack", "notification", "alert"]).usageNotes(
927
+ "Use this for urgent notifications that require @mentions. For general messages without mentions, use send-slack-message instead."
928
+ ).suggests(["get-slack-channels"]).schema(
929
+ zod.z.object({
930
+ channel: zod.z.string().describe("Channel name or ID"),
931
+ message: zod.z.string().describe("Notification message"),
932
+ mentions: zod.z.array(zod.z.string()).optional().describe("List of usernames to mention (without @)")
933
+ })
934
+ ).implementSafe(async ({ channel, message, mentions = [] }) => {
935
+ toolLogger.info("notify-slack called", {
936
+ channel,
937
+ messageLength: message.length,
938
+ mentionCount: mentions.length
939
+ });
940
+ const slack = getConfiguredSlackClient();
941
+ const mentionText = mentions.length > 0 ? mentions.map((m) => `<@${m}>`).join(" ") + " " : "";
942
+ const fullMessage = `${mentionText}${message}`;
943
+ const result = await slack.chat.postMessage({
944
+ channel,
945
+ text: fullMessage,
946
+ username: botName,
947
+ icon_emoji: botIcon
948
+ });
949
+ toolLogger.info("notify-slack result", {
950
+ channel: result.channel,
951
+ timestamp: result.ts,
952
+ mentions: mentions.length
953
+ });
954
+ return {
955
+ channel: result.channel,
956
+ message: fullMessage,
957
+ mentions,
958
+ timestamp: result.ts,
959
+ notification_id: result.ts
960
+ };
961
+ }).build();
962
+ const getChannels = core.toolBuilder().name("get-slack-channels").description("Get a list of available Slack channels to find the right channel for messaging").category(core.ToolCategory.WEB).tags(["slack", "channels", "list"]).usageNotes(
963
+ "Use this first to discover available channels before sending messages. Helps ensure you are sending to the correct channel."
964
+ ).follows(["send-slack-message", "notify-slack"]).schema(
965
+ zod.z.object({
966
+ include_private: zod.z.boolean().optional().describe("Include private channels (default: false)")
967
+ })
968
+ ).implementSafe(async ({ include_private = false }) => {
969
+ toolLogger.info("get-slack-channels called", { include_private });
970
+ const slack = getConfiguredSlackClient();
971
+ const publicChannels = await slack.conversations.list({
972
+ types: "public_channel",
973
+ exclude_archived: true
974
+ });
975
+ let allChannels = publicChannels.channels || [];
976
+ if (include_private) {
977
+ const privateChannels = await slack.conversations.list({
978
+ types: "private_channel",
979
+ exclude_archived: true
980
+ });
981
+ allChannels = [...allChannels, ...privateChannels.channels || []];
982
+ }
983
+ toolLogger.info("get-slack-channels result", {
984
+ channelCount: allChannels.length,
985
+ includePrivate: include_private
986
+ });
987
+ return {
988
+ count: allChannels.length,
989
+ channels: allChannels.map((c) => ({
990
+ id: c.id,
991
+ name: c.name,
992
+ is_private: c.is_private || false,
993
+ num_members: c.num_members || 0
994
+ }))
995
+ };
996
+ }).build();
997
+ const getMessages = core.toolBuilder().name("get-slack-messages").description("Retrieve message history from a Slack channel to read recent conversations").category(core.ToolCategory.WEB).tags(["slack", "messages", "history", "read"]).usageNotes(
998
+ "Use this to read recent messages from a channel. Use get-slack-channels first if you need to find the channel ID. Returns messages in reverse chronological order (newest first)."
999
+ ).suggests(["get-slack-channels"]).schema(
1000
+ zod.z.object({
1001
+ channel: zod.z.string().describe("Channel name (e.g., 'general') or ID (e.g., 'C123456')"),
1002
+ limit: zod.z.number().int().min(1).max(100).optional().describe("Number of messages to retrieve (default: 20, max: 100)")
1003
+ })
1004
+ ).implementSafe(async ({ channel, limit = 20 }) => {
1005
+ toolLogger.info("get-slack-messages called", { channel, limit });
1006
+ try {
1007
+ const slack = getConfiguredSlackClient();
1008
+ let channelId = channel;
1009
+ if (!channel.startsWith("C") && !channel.startsWith("D")) {
1010
+ const channels = await slack.conversations.list({
1011
+ types: "public_channel,private_channel",
1012
+ exclude_archived: true
1013
+ });
1014
+ const found = channels.channels?.find((c) => c.name === channel);
1015
+ if (!found) {
1016
+ toolLogger.error("get-slack-messages: channel not found", { channel });
1017
+ throw new Error(
1018
+ `Channel '${channel}' not found. Use get-slack-channels to see available channels.`
1019
+ );
1020
+ }
1021
+ channelId = found.id;
1022
+ }
1023
+ const result = await slack.conversations.history({
1024
+ channel: channelId,
1025
+ limit: Math.min(limit, 100)
1026
+ });
1027
+ toolLogger.info("get-slack-messages result", {
1028
+ channel: channelId,
1029
+ messageCount: result.messages?.length || 0,
1030
+ limit
1031
+ });
1032
+ return {
1033
+ channel: channelId,
1034
+ count: result.messages?.length || 0,
1035
+ messages: result.messages?.map((m) => ({
1036
+ user: m.user || "unknown",
1037
+ text: m.text || "",
1038
+ timestamp: m.ts,
1039
+ thread_ts: m.thread_ts,
1040
+ type: m.type,
1041
+ subtype: m.subtype
1042
+ })) || []
1043
+ };
1044
+ } catch (error) {
1045
+ toolLogger.error("get-slack-messages failed", {
1046
+ channel,
1047
+ error: error.message,
1048
+ data: error.data
1049
+ });
1050
+ throw error;
1051
+ }
1052
+ }).build();
1053
+ return {
1054
+ sendMessage,
1055
+ notify,
1056
+ getChannels,
1057
+ getMessages
1058
+ };
1059
+ }
1060
+ var slackTools = [sendSlackMessage, notifySlack, getSlackChannels, getSlackMessages];
685
1061
  var jsonParser = core.toolBuilder().name("json-parser").description("Parse JSON string into an object. Validates JSON syntax and returns parsed data or error details.").category(core.ToolCategory.UTILITY).tags(["json", "parse", "data"]).schema(zod.z.object({
686
1062
  json: zod.z.string().describe("JSON string to parse"),
687
1063
  strict: zod.z.boolean().default(true).describe("Use strict JSON parsing (no trailing commas, etc.)")
@@ -1906,8 +2282,8 @@ var AskHumanInputSchema = zod.z.object({
1906
2282
  */
1907
2283
  suggestions: zod.z.array(zod.z.string()).optional().describe("Suggested responses for the human")
1908
2284
  });
1909
- var logLevel = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
1910
- var logger = core.createLogger("askHuman", { level: logLevel });
2285
+ var logLevel2 = process.env.LOG_LEVEL?.toLowerCase() || core.LogLevel.INFO;
2286
+ var logger2 = core.createLogger("askHuman", { level: logLevel2 });
1911
2287
  function createAskHumanTool() {
1912
2288
  return core.toolBuilder().name("ask-human").description(
1913
2289
  "Ask a human for input or approval. Use this when you need human guidance, approval for a critical action, or clarification on ambiguous requirements. The agent execution will pause until the human responds."
@@ -1940,13 +2316,13 @@ function createAskHumanTool() {
1940
2316
  suggestions: validatedInput.suggestions,
1941
2317
  status: "pending"
1942
2318
  };
1943
- logger.debug("About to call interrupt()", { humanRequest });
2319
+ logger2.debug("About to call interrupt()", { humanRequest });
1944
2320
  let response;
1945
2321
  try {
1946
2322
  response = interrupt(humanRequest);
1947
- logger.debug("interrupt() returned successfully", { response, responseType: typeof response });
2323
+ logger2.debug("interrupt() returned successfully", { response, responseType: typeof response });
1948
2324
  } catch (error) {
1949
- logger.debug("interrupt() threw error (expected for GraphInterrupt)", {
2325
+ logger2.debug("interrupt() threw error (expected for GraphInterrupt)", {
1950
2326
  errorType: error?.constructor?.name,
1951
2327
  error: error instanceof Error ? error.message : String(error)
1952
2328
  });
@@ -1983,6 +2359,7 @@ exports.calculator = calculator;
1983
2359
  exports.createAskHumanTool = createAskHumanTool;
1984
2360
  exports.createDuckDuckGoProvider = createDuckDuckGoProvider;
1985
2361
  exports.createSerperProvider = createSerperProvider;
2362
+ exports.createSlackTools = createSlackTools;
1986
2363
  exports.creditCardValidator = creditCardValidator;
1987
2364
  exports.csvGenerator = csvGenerator;
1988
2365
  exports.csvParser = csvParser;
@@ -2004,6 +2381,8 @@ exports.fileExists = fileExists;
2004
2381
  exports.fileReader = fileReader;
2005
2382
  exports.fileSearch = fileSearch;
2006
2383
  exports.fileWriter = fileWriter;
2384
+ exports.getSlackChannels = getSlackChannels;
2385
+ exports.getSlackMessages = getSlackMessages;
2007
2386
  exports.htmlParser = htmlParser;
2008
2387
  exports.httpClient = httpClient;
2009
2388
  exports.httpGet = httpGet;
@@ -2017,6 +2396,7 @@ exports.jsonToCsv = jsonToCsv;
2017
2396
  exports.jsonToXml = jsonToXml;
2018
2397
  exports.jsonValidator = jsonValidator;
2019
2398
  exports.mathFunctions = mathFunctions;
2399
+ exports.notifySlack = notifySlack;
2020
2400
  exports.objectOmit = objectOmit;
2021
2401
  exports.objectPick = objectPick;
2022
2402
  exports.pathBasename = pathBasename;
@@ -2030,6 +2410,8 @@ exports.pathResolve = pathResolve;
2030
2410
  exports.phoneValidator = phoneValidator;
2031
2411
  exports.randomNumber = randomNumber;
2032
2412
  exports.searchResultSchema = searchResultSchema;
2413
+ exports.sendSlackMessage = sendSlackMessage;
2414
+ exports.slackTools = slackTools;
2033
2415
  exports.statistics = statistics;
2034
2416
  exports.stringCaseConverter = stringCaseConverter;
2035
2417
  exports.stringJoin = stringJoin;