-
Notifications
You must be signed in to change notification settings - Fork 280
feat: add support for say_stream utility #1462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
cacf2ad
f30dd71
3e49461
a4a63c8
55ea797
6a7f0f7
42b6c4d
eda8e73
db99b51
9aaedf7
143e8e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # Don't add async module imports here | ||
| from .say_stream import SayStream | ||
|
|
||
| __all__ = [ | ||
| "SayStream", | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import warnings | ||
| from typing import Optional | ||
|
|
||
| from slack_sdk.web.async_client import AsyncWebClient | ||
| from slack_sdk.web.async_chat_stream import AsyncChatStream | ||
|
|
||
| from slack_bolt.warning import ExperimentalWarning | ||
|
|
||
|
|
||
| class AsyncSayStream: | ||
| client: AsyncWebClient | ||
| channel: Optional[str] | ||
| recipient_team_id: Optional[str] | ||
| recipient_user_id: Optional[str] | ||
| thread_ts: Optional[str] | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| client: AsyncWebClient, | ||
| channel: Optional[str] = None, | ||
| recipient_team_id: Optional[str] = None, | ||
| recipient_user_id: Optional[str] = None, | ||
| thread_ts: Optional[str] = None, | ||
| ): | ||
| self.client = client | ||
| self.channel = channel | ||
| self.recipient_team_id = recipient_team_id | ||
| self.recipient_user_id = recipient_user_id | ||
| self.thread_ts = thread_ts | ||
|
|
||
| async def __call__( | ||
| self, | ||
| *, | ||
| buffer_size: Optional[int] = None, | ||
| channel: Optional[str] = None, | ||
| recipient_team_id: Optional[str] = None, | ||
| recipient_user_id: Optional[str] = None, | ||
| thread_ts: Optional[str] = None, | ||
| **kwargs, | ||
| ) -> AsyncChatStream: | ||
| warnings.warn( | ||
| "say_stream is experimental and may change in future versions.", | ||
| category=ExperimentalWarning, | ||
| stacklevel=2, | ||
| ) | ||
|
|
||
| channel = channel or self.channel | ||
| thread_ts = thread_ts or self.thread_ts | ||
| if channel is None: | ||
| raise ValueError("say_stream without channel here is unsupported") | ||
| if thread_ts is None: | ||
| raise ValueError("say_stream without thread_ts here is unsupported") | ||
|
|
||
| if buffer_size is not None: | ||
| return await self.client.chat_stream( | ||
| buffer_size=buffer_size, | ||
| channel=channel, | ||
| recipient_team_id=recipient_team_id or self.recipient_team_id, | ||
| recipient_user_id=recipient_user_id or self.recipient_user_id, | ||
| thread_ts=thread_ts, | ||
| **kwargs, | ||
| ) | ||
| return await self.client.chat_stream( | ||
| channel=channel, | ||
| recipient_team_id=recipient_team_id or self.recipient_team_id, | ||
| recipient_user_id=recipient_user_id or self.recipient_user_id, | ||
| thread_ts=thread_ts, | ||
| **kwargs, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import warnings | ||
| from typing import Optional | ||
|
|
||
| from slack_sdk import WebClient | ||
| from slack_sdk.web.chat_stream import ChatStream | ||
|
|
||
| from slack_bolt.warning import ExperimentalWarning | ||
|
|
||
|
|
||
| class SayStream: | ||
| client: WebClient | ||
| channel: Optional[str] | ||
| recipient_team_id: Optional[str] | ||
| recipient_user_id: Optional[str] | ||
| thread_ts: Optional[str] | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| client: WebClient, | ||
| channel: Optional[str] = None, | ||
| recipient_team_id: Optional[str] = None, | ||
| recipient_user_id: Optional[str] = None, | ||
| thread_ts: Optional[str] = None, | ||
| ): | ||
| self.client = client | ||
| self.channel = channel | ||
| self.recipient_team_id = recipient_team_id | ||
| self.recipient_user_id = recipient_user_id | ||
| self.thread_ts = thread_ts | ||
|
|
||
| def __call__( | ||
| self, | ||
| *, | ||
| buffer_size: Optional[int] = None, | ||
| channel: Optional[str] = None, | ||
| recipient_team_id: Optional[str] = None, | ||
| recipient_user_id: Optional[str] = None, | ||
| thread_ts: Optional[str] = None, | ||
| **kwargs, | ||
| ) -> ChatStream: | ||
| warnings.warn( | ||
| "say_stream is experimental and may change in future versions.", | ||
| category=ExperimentalWarning, | ||
| stacklevel=2, | ||
| ) | ||
|
|
||
| channel = channel or self.channel | ||
| thread_ts = thread_ts or self.thread_ts | ||
| if channel is None: | ||
| raise ValueError("say_stream without channel here is unsupported") | ||
| if thread_ts is None: | ||
| raise ValueError("say_stream without thread_ts here is unsupported") | ||
|
|
||
| if buffer_size is not None: | ||
| return self.client.chat_stream( | ||
| buffer_size=buffer_size, | ||
| channel=channel, | ||
| recipient_team_id=recipient_team_id or self.recipient_team_id, | ||
| recipient_user_id=recipient_user_id or self.recipient_user_id, | ||
| thread_ts=thread_ts, | ||
| **kwargs, | ||
| ) | ||
| return self.client.chat_stream( | ||
| channel=channel, | ||
| recipient_team_id=recipient_team_id or self.recipient_team_id, | ||
| recipient_user_id=recipient_user_id or self.recipient_user_id, | ||
| thread_ts=thread_ts, | ||
| **kwargs, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
|
|
||
| from slack_bolt.context.assistant.assistant_utilities import AssistantUtilities | ||
| from slack_bolt.context.assistant.thread_context_store.store import AssistantThreadContextStore | ||
| from slack_bolt.context.say_stream.say_stream import SayStream | ||
| from slack_bolt.middleware import Middleware | ||
| from slack_bolt.request.payload_utils import is_assistant_event, to_event | ||
| from slack_bolt.request.request import BoltRequest | ||
|
|
@@ -30,4 +31,15 @@ def process(self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], Bo | |
| req.context["set_suggested_prompts"] = assistant.set_suggested_prompts | ||
| req.context["get_thread_context"] = assistant.get_thread_context | ||
| req.context["save_thread_context"] = assistant.save_thread_context | ||
|
|
||
| # TODO: in the future we might want to introduce a "proper" extract_ts utility | ||
| thread_ts = req.context.thread_ts or event.get("ts") | ||
| if req.context.channel_id and thread_ts: | ||
| req.context["say_stream"] = SayStream( | ||
| client=req.context.client, | ||
| channel=req.context.channel_id, | ||
| recipient_team_id=req.context.team_id or req.context.enterprise_id, | ||
| recipient_user_id=req.context.user_id, | ||
| thread_ts=thread_ts, | ||
| ) | ||
|
Comment on lines
+35
to
+44
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👾 thought: Defaulting to different threading behavior for 🔮 ramble: I understand
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yess I think we can revisite the say behavior in the future, but changing it I think would result a breaking change 🤔 I can add a TODO or maybe create an issue for this?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @WilliamBergamin Thanks for keeping note of this too! 📫 I'm partial to waiting for related feedback since this might be an expected experience for most! I fear that knowing some of the implementation details biases me... |
||
| return next() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔍 note: I might not find this in outputs at the moment - would this be something to include in docstring for
say_streamtoo?