-
Notifications
You must be signed in to change notification settings - Fork 850
feat: accept chunks as arguments to chat.{start,append,stop}Stream methods #1806
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: feat-ai-apps-thinking-steps
Are you sure you want to change the base?
Changes from all commits
c3bdb2d
8c56e22
783ada5
1fb7355
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,155 @@ | ||
| import logging | ||
| from typing import Any, Dict, Optional, Sequence, Set, Union | ||
|
|
||
| from slack_sdk.errors import SlackObjectFormationError | ||
| from slack_sdk.models import show_unknown_key_warning | ||
| from slack_sdk.models.basic_objects import JsonObject | ||
|
|
||
|
|
||
| class Chunk(JsonObject): | ||
| """ | ||
| Chunk for streaming messages. | ||
| https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming | ||
| """ | ||
|
|
||
| attributes = {"type"} | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| type: Optional[str] = None, | ||
| ): | ||
| self.type = type | ||
|
|
||
| @classmethod | ||
| def parse(cls, chunk: Union[Dict, "Chunk"]) -> Optional["Chunk"]: | ||
| if chunk is None: | ||
| return None | ||
| elif isinstance(chunk, Chunk): | ||
| return chunk | ||
| else: | ||
| if "type" in chunk: | ||
| type = chunk["type"] | ||
| if type == MarkdownTextChunk.type: | ||
| return MarkdownTextChunk(**chunk) | ||
| elif type == TaskUpdateChunk.type: | ||
| return TaskUpdateChunk(**chunk) | ||
| else: | ||
| cls.logger.warning(f"Unknown chunk detected and skipped ({chunk})") | ||
| return None | ||
| else: | ||
| cls.logger.warning(f"Unknown chunk detected and skipped ({chunk})") | ||
| return None | ||
|
|
||
|
|
||
| class MarkdownTextChunk(Chunk): | ||
| type = "markdown_text" | ||
|
|
||
| @property | ||
| def attributes(self) -> Set[str]: # type: ignore[override] | ||
| return super().attributes.union({"text"}) | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| text: str, | ||
| **others: Dict, | ||
| ): | ||
| """Used for streaming text content with markdown formatting support. | ||
| https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming | ||
| """ | ||
| super().__init__(type=self.type) | ||
| show_unknown_key_warning(self, others) | ||
|
|
||
| self.text = text | ||
|
|
||
|
|
||
| class URLSource(JsonObject): | ||
| type = "url" | ||
|
|
||
| @property | ||
| def attributes(self) -> Set[str]: | ||
| return super().attributes.union( | ||
| { | ||
| "url", | ||
| "text", | ||
| "icon_url", | ||
| } | ||
| ) | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| url: str, | ||
| text: str, | ||
| icon_url: Optional[str] = None, | ||
| **others: Dict, | ||
| ): | ||
| show_unknown_key_warning(self, others) | ||
| self._url = url | ||
| self._text = text | ||
| self._icon_url = icon_url | ||
|
|
||
| def to_dict(self) -> Dict[str, Any]: | ||
| self.validate_json() | ||
| json: Dict[str, Union[str, Dict]] = { | ||
| "type": self.type, | ||
| "url": self._url, | ||
| "text": self._text, | ||
| } | ||
| if self._icon_url: | ||
| json["icon_url"] = self._icon_url | ||
| return json | ||
|
|
||
|
|
||
| class TaskUpdateChunk(Chunk): | ||
| type = "task_update" | ||
|
|
||
| @property | ||
| def attributes(self) -> Set[str]: # type: ignore[override] | ||
| return super().attributes.union( | ||
| { | ||
| "id", | ||
| "title", | ||
| "status", | ||
| "details", | ||
| "output", | ||
| "sources", | ||
| } | ||
| ) | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| id: str, | ||
| title: str, | ||
| status: str, # "pending", "in_progress", "complete", "error" | ||
|
Contributor
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. NIT: if you find this valuable I think you could use some sort of Enum instead of raw strings for the status but I'm not sure how this ill play out in a |
||
| details: Optional[str] = None, | ||
| output: Optional[str] = None, | ||
| sources: Optional[Sequence[Union[Dict, URLSource]]] = None, | ||
| **others: Dict, | ||
| ): | ||
| """Used for displaying tool execution progress in a timeline-style UI. | ||
| https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming | ||
| """ | ||
| super().__init__(type=self.type) | ||
| show_unknown_key_warning(self, others) | ||
|
|
||
| self.id = id | ||
| self.title = title | ||
| self.status = status | ||
| self.details = details | ||
| self.output = output | ||
| if sources is not None: | ||
| self.sources = [] | ||
| for src in sources: | ||
| if isinstance(src, Dict): | ||
| self.sources.append(src) | ||
| elif isinstance(src, URLSource): | ||
| self.sources.append(src.to_dict()) | ||
| else: | ||
| raise SlackObjectFormationError(f"Unsupported type for source in task update chunk: {type(src)}") | ||
|
Comment on lines
+147
to
+155
Member
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. 🪓 note: This is simplified alongside the changes of #1819 as well! |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,12 +7,13 @@ | |
| from typing import Any, Dict, List, Optional, Sequence, Union | ||
|
|
||
| import slack_sdk.errors as e | ||
| from slack_sdk.models.messages.chunk import Chunk | ||
| from slack_sdk.models.views import View | ||
| from slack_sdk.web.chat_stream import ChatStream | ||
|
|
||
| from ..models.attachments import Attachment | ||
| from ..models.blocks import Block, RichTextBlock | ||
| from ..models.metadata import Metadata, EntityMetadata, EventAndEntityMetadata | ||
| from ..models.metadata import EntityMetadata, EventAndEntityMetadata, Metadata | ||
| from .base_client import BaseClient, SlackResponse | ||
| from .internal_utils import ( | ||
| _parse_web_class_objects, | ||
|
|
@@ -2621,6 +2622,7 @@ def chat_appendStream( | |
| channel: str, | ||
| ts: str, | ||
| markdown_text: str, | ||
| chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, | ||
|
Contributor
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. Should the above |
||
| **kwargs, | ||
| ) -> SlackResponse: | ||
| """Appends text to an existing streaming conversation. | ||
|
|
@@ -2631,8 +2633,10 @@ def chat_appendStream( | |
| "channel": channel, | ||
| "ts": ts, | ||
| "markdown_text": markdown_text, | ||
| "chunks": chunks, | ||
| } | ||
| ) | ||
| _parse_web_class_objects(kwargs) | ||
| kwargs = _remove_none_values(kwargs) | ||
| return self.api_call("chat.appendStream", json=kwargs) | ||
|
|
||
|
|
@@ -2874,6 +2878,7 @@ def chat_startStream( | |
| markdown_text: Optional[str] = None, | ||
| recipient_team_id: Optional[str] = None, | ||
| recipient_user_id: Optional[str] = None, | ||
| chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, | ||
| **kwargs, | ||
| ) -> SlackResponse: | ||
| """Starts a new streaming conversation. | ||
|
|
@@ -2886,8 +2891,10 @@ def chat_startStream( | |
| "markdown_text": markdown_text, | ||
| "recipient_team_id": recipient_team_id, | ||
| "recipient_user_id": recipient_user_id, | ||
| "chunks": chunks, | ||
| } | ||
| ) | ||
| _parse_web_class_objects(kwargs) | ||
| kwargs = _remove_none_values(kwargs) | ||
| return self.api_call("chat.startStream", json=kwargs) | ||
|
|
||
|
|
@@ -2899,6 +2906,7 @@ def chat_stopStream( | |
| markdown_text: Optional[str] = None, | ||
| blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, | ||
| metadata: Optional[Union[Dict, Metadata]] = None, | ||
| chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, | ||
| **kwargs, | ||
| ) -> SlackResponse: | ||
| """Stops a streaming conversation. | ||
|
|
@@ -2911,6 +2919,7 @@ def chat_stopStream( | |
| "markdown_text": markdown_text, | ||
| "blocks": blocks, | ||
| "metadata": metadata, | ||
| "chunks": chunks, | ||
| } | ||
| ) | ||
| _parse_web_class_objects(kwargs) | ||
|
|
||
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: In 6073ffe of #1819 this is moved into the block elements class because it can be used in standalone messages - not just chunks.
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: It's also changed from "URL" to "Url" to match similar elements!