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.
arcade_slack/__init__.py
ADDED
|
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,,
|