Skip to content

Commit 60bd43d

Browse files
authored
feat: add authorship arguments to assistant threads and chat stream (#1862)
1 parent 726538c commit 60bd43d

7 files changed

Lines changed: 138 additions & 3 deletions

File tree

slack_sdk/web/async_chat_stream.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ def __init__(
4040
recipient_team_id: Optional[str] = None,
4141
recipient_user_id: Optional[str] = None,
4242
task_display_mode: Optional[str] = None,
43+
icon_emoji: Optional[str] = None,
44+
icon_url: Optional[str] = None,
45+
username: Optional[str] = None,
4346
**kwargs,
4447
):
4548
"""Initialize a new ChatStream instance.
@@ -57,6 +60,9 @@ def __init__(
5760
recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels.
5861
task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks
5962
with text and "plan" displays all tasks together.
63+
icon_emoji: Emoji to use as the icon for this message. Overrides icon_url.
64+
icon_url: Image URL to use as the icon for this message.
65+
username: The bot's username to display.
6066
buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value
6167
decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits.
6268
**kwargs: Additional arguments passed to the underlying API calls.
@@ -70,6 +76,9 @@ def __init__(
7076
"recipient_team_id": recipient_team_id,
7177
"recipient_user_id": recipient_user_id,
7278
"task_display_mode": task_display_mode,
79+
"icon_emoji": icon_emoji,
80+
"icon_url": icon_url,
81+
"username": username,
7382
**kwargs,
7483
}
7584
self._buffer = ""

slack_sdk/web/async_client.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2091,13 +2091,24 @@ async def assistant_threads_setStatus(
20912091
thread_ts: str,
20922092
status: str,
20932093
loading_messages: Optional[List[str]] = None,
2094+
icon_emoji: Optional[str] = None,
2095+
icon_url: Optional[str] = None,
2096+
username: Optional[str] = None,
20942097
**kwargs,
20952098
) -> AsyncSlackResponse:
20962099
"""Set the status for an AI assistant thread.
20972100
https://docs.slack.dev/reference/methods/assistant.threads.setStatus
20982101
"""
20992102
kwargs.update(
2100-
{"channel_id": channel_id, "thread_ts": thread_ts, "status": status, "loading_messages": loading_messages}
2103+
{
2104+
"channel_id": channel_id,
2105+
"thread_ts": thread_ts,
2106+
"status": status,
2107+
"loading_messages": loading_messages,
2108+
"icon_emoji": icon_emoji,
2109+
"icon_url": icon_url,
2110+
"username": username,
2111+
}
21012112
)
21022113
kwargs = _remove_none_values(kwargs)
21032114
return await self.api_call("assistant.threads.setStatus", json=kwargs)
@@ -2903,6 +2914,9 @@ async def chat_startStream(
29032914
recipient_user_id: Optional[str] = None,
29042915
chunks: Optional[Sequence[Union[Dict, Chunk]]] = None,
29052916
task_display_mode: Optional[str] = None, # timeline, plan
2917+
icon_emoji: Optional[str] = None,
2918+
icon_url: Optional[str] = None,
2919+
username: Optional[str] = None,
29062920
**kwargs,
29072921
) -> AsyncSlackResponse:
29082922
"""Starts a new streaming conversation.
@@ -2917,6 +2931,9 @@ async def chat_startStream(
29172931
"recipient_user_id": recipient_user_id,
29182932
"chunks": chunks,
29192933
"task_display_mode": task_display_mode,
2934+
"icon_emoji": icon_emoji,
2935+
"icon_url": icon_url,
2936+
"username": username,
29202937
}
29212938
)
29222939
_parse_web_class_objects(kwargs)
@@ -2960,6 +2977,9 @@ async def chat_stream(
29602977
recipient_team_id: Optional[str] = None,
29612978
recipient_user_id: Optional[str] = None,
29622979
task_display_mode: Optional[str] = None,
2980+
icon_emoji: Optional[str] = None,
2981+
icon_url: Optional[str] = None,
2982+
username: Optional[str] = None,
29632983
**kwargs,
29642984
) -> AsyncChatStream:
29652985
"""Stream markdown text into a conversation.
@@ -2988,6 +3008,9 @@ async def chat_stream(
29883008
recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels.
29893009
task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks
29903010
with text and "plan" displays all tasks together.
3011+
icon_emoji: Emoji to use as the icon for this message. Overrides icon_url.
3012+
icon_url: Image URL to use as the icon for this message.
3013+
username: The bot's username to display.
29913014
**kwargs: Additional arguments passed to the underlying API calls.
29923015
29933016
Returns:
@@ -3014,6 +3037,9 @@ async def chat_stream(
30143037
recipient_team_id=recipient_team_id,
30153038
recipient_user_id=recipient_user_id,
30163039
task_display_mode=task_display_mode,
3040+
icon_emoji=icon_emoji,
3041+
icon_url=icon_url,
3042+
username=username,
30173043
buffer_size=buffer_size,
30183044
**kwargs,
30193045
)

slack_sdk/web/chat_stream.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ def __init__(
3030
recipient_team_id: Optional[str] = None,
3131
recipient_user_id: Optional[str] = None,
3232
task_display_mode: Optional[str] = None,
33+
icon_emoji: Optional[str] = None,
34+
icon_url: Optional[str] = None,
35+
username: Optional[str] = None,
3336
**kwargs,
3437
):
3538
"""Initialize a new ChatStream instance.
@@ -47,6 +50,9 @@ def __init__(
4750
recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels.
4851
task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks
4952
with text and "plan" displays all tasks together.
53+
icon_emoji: Emoji to use as the icon for this message. Overrides icon_url.
54+
icon_url: Image URL to use as the icon for this message.
55+
username: The bot's username to display.
5056
buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value
5157
decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits.
5258
**kwargs: Additional arguments passed to the underlying API calls.
@@ -60,6 +66,9 @@ def __init__(
6066
"recipient_team_id": recipient_team_id,
6167
"recipient_user_id": recipient_user_id,
6268
"task_display_mode": task_display_mode,
69+
"icon_emoji": icon_emoji,
70+
"icon_url": icon_url,
71+
"username": username,
6372
**kwargs,
6473
}
6574
self._buffer = ""

slack_sdk/web/client.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2081,13 +2081,24 @@ def assistant_threads_setStatus(
20812081
thread_ts: str,
20822082
status: str,
20832083
loading_messages: Optional[List[str]] = None,
2084+
icon_emoji: Optional[str] = None,
2085+
icon_url: Optional[str] = None,
2086+
username: Optional[str] = None,
20842087
**kwargs,
20852088
) -> SlackResponse:
20862089
"""Set the status for an AI assistant thread.
20872090
https://docs.slack.dev/reference/methods/assistant.threads.setStatus
20882091
"""
20892092
kwargs.update(
2090-
{"channel_id": channel_id, "thread_ts": thread_ts, "status": status, "loading_messages": loading_messages}
2093+
{
2094+
"channel_id": channel_id,
2095+
"thread_ts": thread_ts,
2096+
"status": status,
2097+
"loading_messages": loading_messages,
2098+
"icon_emoji": icon_emoji,
2099+
"icon_url": icon_url,
2100+
"username": username,
2101+
}
20912102
)
20922103
kwargs = _remove_none_values(kwargs)
20932104
return self.api_call("assistant.threads.setStatus", json=kwargs)
@@ -2893,6 +2904,9 @@ def chat_startStream(
28932904
recipient_user_id: Optional[str] = None,
28942905
chunks: Optional[Sequence[Union[Dict, Chunk]]] = None,
28952906
task_display_mode: Optional[str] = None, # timeline, plan
2907+
icon_emoji: Optional[str] = None,
2908+
icon_url: Optional[str] = None,
2909+
username: Optional[str] = None,
28962910
**kwargs,
28972911
) -> SlackResponse:
28982912
"""Starts a new streaming conversation.
@@ -2907,6 +2921,9 @@ def chat_startStream(
29072921
"recipient_user_id": recipient_user_id,
29082922
"chunks": chunks,
29092923
"task_display_mode": task_display_mode,
2924+
"icon_emoji": icon_emoji,
2925+
"icon_url": icon_url,
2926+
"username": username,
29102927
}
29112928
)
29122929
_parse_web_class_objects(kwargs)
@@ -2950,6 +2967,9 @@ def chat_stream(
29502967
recipient_team_id: Optional[str] = None,
29512968
recipient_user_id: Optional[str] = None,
29522969
task_display_mode: Optional[str] = None,
2970+
icon_emoji: Optional[str] = None,
2971+
icon_url: Optional[str] = None,
2972+
username: Optional[str] = None,
29532973
**kwargs,
29542974
) -> ChatStream:
29552975
"""Stream markdown text into a conversation.
@@ -2978,6 +2998,9 @@ def chat_stream(
29782998
recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels.
29792999
task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks
29803000
with text and "plan" displays all tasks together.
3001+
icon_emoji: Emoji to use as the icon for this message. Overrides icon_url.
3002+
icon_url: Image URL to use as the icon for this message.
3003+
username: The bot's username to display.
29813004
**kwargs: Additional arguments passed to the underlying API calls.
29823005
29833006
Returns:
@@ -3004,6 +3027,9 @@ def chat_stream(
30043027
recipient_team_id=recipient_team_id,
30053028
recipient_user_id=recipient_user_id,
30063029
task_display_mode=task_display_mode,
3030+
icon_emoji=icon_emoji,
3031+
icon_url=icon_url,
3032+
username=username,
30073033
buffer_size=buffer_size,
30083034
**kwargs,
30093035
)

slack_sdk/web/legacy_client.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2092,13 +2092,24 @@ def assistant_threads_setStatus(
20922092
thread_ts: str,
20932093
status: str,
20942094
loading_messages: Optional[List[str]] = None,
2095+
icon_emoji: Optional[str] = None,
2096+
icon_url: Optional[str] = None,
2097+
username: Optional[str] = None,
20952098
**kwargs,
20962099
) -> Union[Future, SlackResponse]:
20972100
"""Set the status for an AI assistant thread.
20982101
https://docs.slack.dev/reference/methods/assistant.threads.setStatus
20992102
"""
21002103
kwargs.update(
2101-
{"channel_id": channel_id, "thread_ts": thread_ts, "status": status, "loading_messages": loading_messages}
2104+
{
2105+
"channel_id": channel_id,
2106+
"thread_ts": thread_ts,
2107+
"status": status,
2108+
"loading_messages": loading_messages,
2109+
"icon_emoji": icon_emoji,
2110+
"icon_url": icon_url,
2111+
"username": username,
2112+
}
21022113
)
21032114
kwargs = _remove_none_values(kwargs)
21042115
return self.api_call("assistant.threads.setStatus", json=kwargs)
@@ -2904,6 +2915,9 @@ def chat_startStream(
29042915
recipient_user_id: Optional[str] = None,
29052916
chunks: Optional[Sequence[Union[Dict, Chunk]]] = None,
29062917
task_display_mode: Optional[str] = None, # timeline, plan
2918+
icon_emoji: Optional[str] = None,
2919+
icon_url: Optional[str] = None,
2920+
username: Optional[str] = None,
29072921
**kwargs,
29082922
) -> Union[Future, SlackResponse]:
29092923
"""Starts a new streaming conversation.
@@ -2918,6 +2932,9 @@ def chat_startStream(
29182932
"recipient_user_id": recipient_user_id,
29192933
"chunks": chunks,
29202934
"task_display_mode": task_display_mode,
2935+
"icon_emoji": icon_emoji,
2936+
"icon_url": icon_url,
2937+
"username": username,
29212938
}
29222939
)
29232940
_parse_web_class_objects(kwargs)

tests/slack_sdk/web/test_chat_stream.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,26 @@ def test_streams_a_chunk_message(self):
242242
'[{"text": "\\n", "type": "markdown_text"}, {"text": ":space_invader:", "type": "markdown_text"}]',
243243
)
244244

245+
def test_streams_with_authorship_args(self):
246+
streamer = self.client.chat_stream(
247+
channel="C0123456789",
248+
thread_ts="123.000",
249+
username="Abacus",
250+
icon_emoji="abacus",
251+
)
252+
self.assertEqual(streamer._stream_args["username"], "Abacus")
253+
self.assertEqual(streamer._stream_args["icon_emoji"], "abacus")
254+
self.assertIsNone(streamer._stream_args["icon_url"])
255+
256+
streamer.append(markdown_text="counting...")
257+
streamer.stop()
258+
259+
if hasattr(self.thread.server, "chat_stream_requests"):
260+
start_request = self.thread.server.chat_stream_requests.get("/chat.startStream", {})
261+
self.assertEqual(start_request.get("username"), "Abacus")
262+
self.assertEqual(start_request.get("icon_emoji"), "abacus")
263+
self.assertNotIn("icon_url", start_request)
264+
245265
def test_streams_errors_when_appending_to_an_unstarted_stream(self):
246266
streamer = self.client.chat_stream(
247267
channel="C0123456789",

tests/slack_sdk_async/web/test_web_client_coverage.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,19 @@ async def run_method(self, method_name, method, async_method):
441441
status="is typing...",
442442
loading_states=["Thinking...", "Writing..."],
443443
)
444+
method(
445+
channel_id="D111",
446+
thread_ts="111.222",
447+
status="counting...",
448+
username="Abacus",
449+
icon_emoji="abacus",
450+
)
451+
await async_method(
452+
channel_id="D111",
453+
thread_ts="111.222",
454+
status="dreaming...",
455+
icon_url="https://example.com/clouds-square.png",
456+
)
444457
elif method_name == "assistant_threads_setTitle":
445458
self.api_methods_to_call.remove(method(channel_id="D111", thread_ts="111.222", title="New chat")["method"])
446459
await async_method(channel_id="D111", thread_ts="111.222", title="New chat")
@@ -587,6 +600,21 @@ async def run_method(self, method_name, method, async_method):
587600
await async_method(channel="C123", thread_ts="123.123")
588601
method(channel="C123", thread_ts="123.123", recipient_team_id="T123", recipient_user_id="U123")
589602
await async_method(channel="C123", thread_ts="123.123", recipient_team_id="T123", recipient_user_id="U123")
603+
method(
604+
channel="C123",
605+
thread_ts="123.123",
606+
recipient_team_id="T123",
607+
recipient_user_id="U123",
608+
username="Abacus",
609+
icon_emoji="abacus",
610+
)
611+
await async_method(
612+
channel="C123",
613+
thread_ts="123.123",
614+
recipient_team_id="T123",
615+
recipient_user_id="U123",
616+
icon_url="https://example.com/clouds-square.png",
617+
)
590618
elif method_name == "chat_stopStream":
591619
self.api_methods_to_call.remove(
592620
method(channel="C123", ts="123.123", blocks=[{"type": "markdown", "text": "**twelve**"}])["method"]

0 commit comments

Comments
 (0)