arcade-slack 0.0.13__py3-none-any.whl

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.
File without changes
File without changes
@@ -0,0 +1,131 @@
1
+ from typing import Annotated
2
+
3
+ from slack_sdk import WebClient
4
+ from slack_sdk.errors import SlackApiError
5
+
6
+ from arcade.core.errors import RetryableToolError, ToolExecutionError
7
+ from arcade.core.schema import ToolContext
8
+ from arcade.sdk import tool
9
+ from arcade.sdk.auth import Slack
10
+
11
+
12
+ @tool(
13
+ requires_auth=Slack(
14
+ scopes=[
15
+ "chat:write",
16
+ "im:write",
17
+ "users.profile:read",
18
+ "users:read",
19
+ ],
20
+ )
21
+ )
22
+ def send_dm_to_user(
23
+ context: ToolContext,
24
+ user_name: Annotated[
25
+ str,
26
+ "The Slack username of the person you want to message. Slack usernames are ALWAYS lowercase.",
27
+ ],
28
+ message: Annotated[str, "The message you want to send"],
29
+ ):
30
+ """Send a direct message to a user in Slack."""
31
+
32
+ slackClient = WebClient(token=context.authorization.token)
33
+
34
+ try:
35
+ # Step 1: Retrieve the user's Slack ID based on their username
36
+ userListResponse = slackClient.users_list()
37
+ user_id = None
38
+ for user in userListResponse["members"]:
39
+ if user["name"].lower() == user_name.lower():
40
+ user_id = user["id"]
41
+ break
42
+
43
+ if not user_id:
44
+ raise RetryableToolError(
45
+ "User not found",
46
+ developer_message=f"User with username '{user_name}' not found.",
47
+ additional_prompt_content=format_users(userListResponse),
48
+ retry_after_ms=500, # Play nice with Slack API rate limits
49
+ )
50
+
51
+ # Step 2: Retrieve the DM channel ID with the user
52
+ im_response = slackClient.conversations_open(users=[user_id])
53
+ dm_channel_id = im_response["channel"]["id"]
54
+
55
+ # Step 3: Send the message as if it's from you (because we're using a user token)
56
+ slackClient.chat_postMessage(channel=dm_channel_id, text=message)
57
+
58
+ except SlackApiError as e:
59
+ error_message = e.response["error"] if "error" in e.response else str(e)
60
+ raise ToolExecutionError(
61
+ "Error sending message",
62
+ developer_message=f"Slack API Error: {error_message}",
63
+ )
64
+
65
+
66
+ def format_users(userListResponse: dict) -> str:
67
+ csv_string = "All active Slack users:\n\nname,real_name\n"
68
+ for user in userListResponse["members"]:
69
+ if not user.get("deleted", False):
70
+ name = user.get("name", "")
71
+ real_name = user.get("profile", {}).get("real_name", "")
72
+ csv_string += f"{name},{real_name}\n"
73
+ return csv_string.strip()
74
+
75
+
76
+ @tool(
77
+ requires_auth=Slack(
78
+ scopes=[
79
+ "chat:write",
80
+ "channels:read",
81
+ "groups:read",
82
+ ],
83
+ )
84
+ )
85
+ def send_message_to_channel(
86
+ context: ToolContext,
87
+ channel_name: Annotated[
88
+ str,
89
+ "The Slack channel name where you want to send the message. Slack channel names are ALWAYS lowercase.",
90
+ ],
91
+ message: Annotated[str, "The message you want to send"],
92
+ ):
93
+ """Send a message to a channel in Slack."""
94
+
95
+ slackClient = WebClient(token=context.authorization.token)
96
+
97
+ try:
98
+ # Step 1: Retrieve the list of channels
99
+ channels_response = slackClient.conversations_list()
100
+ channel_id = None
101
+ for channel in channels_response["channels"]:
102
+ if channel["name"].lower() == channel_name.lower():
103
+ channel_id = channel["id"]
104
+ break
105
+
106
+ if not channel_id:
107
+ raise RetryableToolError(
108
+ "Channel not found",
109
+ developer_message=f"Channel with name '{channel_name}' not found.",
110
+ additional_prompt_content=format_channels(channels_response),
111
+ retry_after_ms=500, # Play nice with Slack API rate limits
112
+ )
113
+
114
+ # Step 2: Send the message to the channel
115
+ slackClient.chat_postMessage(channel=channel_id, text=message)
116
+
117
+ except SlackApiError as e:
118
+ error_message = e.response["error"] if "error" in e.response else str(e)
119
+ raise ToolExecutionError(
120
+ "Error sending message",
121
+ developer_message=f"Slack API Error: {error_message}",
122
+ )
123
+
124
+
125
+ def format_channels(channels_response: dict) -> str:
126
+ csv_string = "All active Slack channels:\n\nname\n"
127
+ for channel in channels_response["channels"]:
128
+ if not channel.get("is_archived", False):
129
+ name = channel.get("name", "")
130
+ csv_string += f"{name}\n"
131
+ return csv_string.strip()
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.1
2
+ Name: arcade_slack
3
+ Version: 0.0.13
4
+ Summary: Slack tools for LLMs
5
+ Author: Arcade AI
6
+ Author-email: dev@arcade-ai.com
7
+ Requires-Python: >=3.10,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: arcade-ai (==0.0.13)
14
+ Requires-Dist: slack-sdk (>=3.31.0,<4.0.0)
@@ -0,0 +1,6 @@
1
+ arcade_slack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ arcade_slack/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ arcade_slack/tools/chat.py,sha256=jfMExcBRcKucr5_4jA3VTdWjD9IRQMiNRuojy0AiLho,4434
4
+ arcade_slack-0.0.13.dist-info/METADATA,sha256=96Z7t9PrJfRNF4nlgvJkrNpbZxnw75m-wTjk0wpDM3g,497
5
+ arcade_slack-0.0.13.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
6
+ arcade_slack-0.0.13.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any