| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #1462 +/- ##
==========================================
+ Coverage 91.35% 91.43% +0.08%
==========================================
Files 229 232 +3
Lines 7262 7334 +72
==========================================
+ Hits 6634 6706 +72
Misses 628 628 ☔ View full report in Codecov by Sentry. |
Sorry, something went wrong.
There was a problem hiding this comment.
@WilliamBergamin Thanks a bunch for this PR! It's super exciting.
❓ Can you please provide some code for us to manually test? I'm having trouble importing SayStream and I'm unsure if I'm importing the incorrect path or have the sample app configured incorrectly. What is the import path?
Sorry, something went wrong.
There was a problem hiding this comment.
🎙️ Leaving a few comments too but an example listener in description might be helpful for later CHANGELOG I agree!
Sorry, something went wrong.
| # 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_id=req.context.channel_id, | ||
| thread_ts=thread_ts, | ||
| team_id=req.context.team_id, | ||
| user_id=req.context.user_id, | ||
| ) |
There was a problem hiding this comment.
👾 thought: Defaulting to different threading behavior for say and say_stream concerns me somewhat.
🔮 ramble: I understand thread_ts is required to stream chat at this time, but if "parent" messages can be streamed in the future we might want to revisit also say behavior?
Sorry, something went wrong.
There was a problem hiding this comment.
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?
Sorry, something went wrong.
There was a problem hiding this comment.
@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...
Sorry, something went wrong.
| assert say_stream is None | ||
| assert context.say_stream is None |
There was a problem hiding this comment.
🌟 praise: This is a pleasant assertion to have for application code guards too I think!
Sorry, something went wrong.
Co-authored-by: Eden Zimbelman <eden.zimbelman@salesforce.com>
|
@mwbrooks check out this app I've been using for testing app.pyimport os
import logging
from time import sleep
from slack_bolt import App, BoltContext, SayStream
from slack_bolt.adapter.socket_mode import SocketModeHandler
from slack_sdk import WebClient
logging.basicConfig(level=logging.DEBUG)
app = App(token=os.environ.get("SLACK_BOT_TOKEN"))
@app.event("app_mention")
def handle_app_mention(client: WebClient, say_stream: SayStream, context: BoltContext):
stream = say_stream(buffer_size=100)
client.assistant_threads_setStatus(
channel_id=context.channel_id,
thread_ts=say_stream.thread_ts,
status="Thinking...",
loading_messages=[
"Waking up from my mass-production nap...",
"Putting on my thinking cap...",
"Consulting the ancient Stack Overflow...",
"Bribing the servers with virtual cookies...",
"Loading witty response... please hold...",
],
)
stream.append(markdown_text="*Someone rang the bat signal!* :bat:\n\n")
sleep(5)
stream.append(markdown_text="Oh wait, it's just an @mention. Even better!\n\n")
stream.append(markdown_text="> Fun fact: I was mass-produced in a mass-production factory, but I like to think I'm *one of a kind*.\n\n")
sleep(1)
stream.append(markdown_text="Anyway, here's my *totally professional* take:\n\n")
stream.append(markdown_text="1. `say_stream` is basically magic — words appear like I'm *actually typing* :sparkles:\n")
sleep(1)
stream.append(markdown_text="2. Streaming means you don't have to stare at a blank screen wondering if I ghosted you\n")
sleep(1)
stream.append(markdown_text="3. Bolt for Python makes building Slack apps easier than microwaving leftovers\n\n")
sleep(0.5)
stream.append(markdown_text="_*mic drop*_ :microphone:")
stream.stop()
@app.message("")
def handle_ask_bot(client: WebClient, say_stream: SayStream, context: BoltContext):
stream = say_stream(buffer_size=100)
client.assistant_threads_setStatus(
channel_id=context.channel_id,
thread_ts=say_stream.thread_ts,
status="Thinking...",
loading_messages=[
"Rummaging through my one brain cell...",
"Asking my rubber duck for advice...",
"Warming up the nonsense generator...",
"Downloading more RAM (just kidding)...",
"Practicing my typing... clack clack clack...",
],
)
stream.append(markdown_text="*Psst...* you just DMed a bot. Bold move. I respect that. :sunglasses:\n\n")
sleep(5)
stream.append(markdown_text="Let me consult my *vast knowledge database*...\n\n")
stream.append(markdown_text="```\n[ scanning... ]\n[ found: 1 brain cell ]\n[ deploying it now ]\n```\n\n")
sleep(1)
stream.append(markdown_text="Okay here's the deal:\n\n")
sleep(1)
stream.append(markdown_text=":rocket: *Streaming responses* means you get to watch me think in real time — terrifying, I know\n")
sleep(1)
stream.append(markdown_text=":hammer_and_wrench: *Bolt for Python* is the secret sauce behind my dazzling personality\n")
sleep(1)
stream.append(markdown_text=":zap: *Socket Mode* keeps our conversation nice and private — no nosy webhooks here\n\n")
sleep(0.5)
stream.append(markdown_text="That's all I've got. Don't forget to tip your bot! :robot_face:")
stream.stop()
if __name__ == "__main__":
SocketModeHandler(app, os.environ.get("SLACK_APP_TOKEN")).start(){
"_metadata": {
"major_version": 1,
"minor_version": 1
},
"display_information": {
"name": "say_stream_experiment"
},
"features": {
"app_home": {
"home_tab_enabled": false,
"messages_tab_enabled": true,
"messages_tab_read_only_enabled": false
},
"bot_user": {
"display_name": "say_stream_experiment",
"always_online": false
}
},
"oauth_config": {
"scopes": {
"bot": [
"app_mentions:read",
"chat:write",
"im:read",
"im:write",
"channels:history",
"im:history"
]
}
},
"settings": {
"event_subscriptions": {
"bot_events": [
"app_mention",
"message.im"
]
},
"interactivity": {
"is_enabled": true
},
"org_deploy_enabled": true,
"socket_mode_enabled": true,
"token_rotation_enabled": false
}
} |
Sorry, something went wrong.
There was a problem hiding this comment.
@WilliamBergamin Super awesome changes recent! I'm finding this streams to channel as expected 🐢 💨
I'm leaving a note on experimental documentation but nothing to block this from merging I think!
Sorry, something went wrong.
| "say_stream is experimental and may change in future versions.", | ||
| category=ExperimentalWarning, | ||
| stacklevel=2, | ||
| ) |
There was a problem hiding this comment.
🔍 note: I might not find this in outputs at the moment - would this be something to include in docstring for say_stream too?
Sorry, something went wrong.
There was a problem hiding this comment.
I might not find this in outputs at the moment
Interesting 🤔 I an seeing it on my end, let me see how I should add this to the docstring
Sorry, something went wrong.
Sorry, something went wrong.
There was a problem hiding this comment.
✅ Woohoo, I'm already loving seeing say and say_stream side-by-side. Best friends 🫛
🧪 I've tested this on a Standalone Workspace and Enterprise Organization. Both work great now!
➡️ I'll look into rolling this into our sample agent app tomorrow!
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Summary
This PR aims to introduce a new kwarg say_stream, it allows developers the ability to easily use a WebClient.chat_stream object initialized with logical default values.
say_stream is WebClient.chat_stream initialized with
say_stream is available on app.event and app.message listeners, if Bolt fails to extract channel_id or thread_ts then say_stream will be None
Testing
- clone this branch
- build the project with scripts/build_pypi_package.sh
- Import the package in a Bolt project
- Play around with say_stream
Sample app.py{ "_metadata": { "major_version": 1, "minor_version": 1 }, "display_information": { "name": "say_stream_experiment" }, "features": { "app_home": { "home_tab_enabled": false, "messages_tab_enabled": true, "messages_tab_read_only_enabled": false }, "bot_user": { "display_name": "say_stream_experiment", "always_online": false } }, "oauth_config": { "scopes": { "bot": [ "app_mentions:read", "chat:write", "im:read", "im:write", "channels:history", "im:history" ] } }, "settings": { "event_subscriptions": { "bot_events": [ "app_mention", "message.im" ] }, "interactivity": { "is_enabled": true }, "org_deploy_enabled": true, "socket_mode_enabled": true, "token_rotation_enabled": false } }Category
Requirements
Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.