From 1c84f7f77472700badaed9e1c880098fcc0ab81b Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 16 Jan 2026 15:04:48 -0800 Subject: [PATCH 1/8] feat: accept chunks as arguments to chat.{start,append,stop}Stream methods (#1806) --- slack_sdk/models/messages/chunk.py | 155 +++++++++++++++++++++ slack_sdk/web/async_client.py | 11 +- slack_sdk/web/client.py | 11 +- slack_sdk/web/internal_utils.py | 14 +- slack_sdk/web/legacy_client.py | 11 +- tests/slack_sdk/models/test_chunks.py | 72 ++++++++++ tests/slack_sdk/web/test_internal_utils.py | 31 ++++- 7 files changed, 295 insertions(+), 10 deletions(-) create mode 100644 slack_sdk/models/messages/chunk.py create mode 100644 tests/slack_sdk/models/test_chunks.py diff --git a/slack_sdk/models/messages/chunk.py b/slack_sdk/models/messages/chunk.py new file mode 100644 index 000000000..837714af0 --- /dev/null +++ b/slack_sdk/models/messages/chunk.py @@ -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" + 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)}") diff --git a/slack_sdk/web/async_client.py b/slack_sdk/web/async_client.py index ca163da98..0a9f702b9 100644 --- a/slack_sdk/web/async_client.py +++ b/slack_sdk/web/async_client.py @@ -17,12 +17,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.async_chat_stream import AsyncChatStream 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 .async_base_client import AsyncBaseClient, AsyncSlackResponse from .internal_utils import ( _parse_web_class_objects, @@ -2631,6 +2632,7 @@ async def chat_appendStream( channel: str, ts: str, markdown_text: str, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> AsyncSlackResponse: """Appends text to an existing streaming conversation. @@ -2641,8 +2643,10 @@ async def chat_appendStream( "channel": channel, "ts": ts, "markdown_text": markdown_text, + "chunks": chunks, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return await self.api_call("chat.appendStream", json=kwargs) @@ -2884,6 +2888,7 @@ async 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, ) -> AsyncSlackResponse: """Starts a new streaming conversation. @@ -2896,8 +2901,10 @@ async 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 await self.api_call("chat.startStream", json=kwargs) @@ -2909,6 +2916,7 @@ async 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, ) -> AsyncSlackResponse: """Stops a streaming conversation. @@ -2921,6 +2929,7 @@ async def chat_stopStream( "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) diff --git a/slack_sdk/web/client.py b/slack_sdk/web/client.py index dfa771832..1a70681a4 100644 --- a/slack_sdk/web/client.py +++ b/slack_sdk/web/client.py @@ -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, **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) diff --git a/slack_sdk/web/internal_utils.py b/slack_sdk/web/internal_utils.py index 87139559c..ad23f87f8 100644 --- a/slack_sdk/web/internal_utils.py +++ b/slack_sdk/web/internal_utils.py @@ -11,13 +11,14 @@ from ssl import SSLContext from typing import Any, Dict, Optional, Sequence, Union from urllib.parse import urljoin -from urllib.request import OpenerDirector, ProxyHandler, HTTPSHandler, Request, urlopen +from urllib.request import HTTPSHandler, OpenerDirector, ProxyHandler, Request, urlopen from slack_sdk import version from slack_sdk.errors import SlackRequestError from slack_sdk.models.attachments import Attachment from slack_sdk.models.blocks import Block -from slack_sdk.models.metadata import Metadata, EventAndEntityMetadata, EntityMetadata +from slack_sdk.models.messages.chunk import Chunk +from slack_sdk.models.metadata import EntityMetadata, EventAndEntityMetadata, Metadata def convert_bool_to_0_or_1(params: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: @@ -187,11 +188,13 @@ def _build_req_args( def _parse_web_class_objects(kwargs) -> None: - def to_dict(obj: Union[Dict, Block, Attachment, Metadata, EventAndEntityMetadata, EntityMetadata]): + def to_dict(obj: Union[Dict, Block, Attachment, Chunk, Metadata, EventAndEntityMetadata, EntityMetadata]): if isinstance(obj, Block): return obj.to_dict() if isinstance(obj, Attachment): return obj.to_dict() + if isinstance(obj, Chunk): + return obj.to_dict() if isinstance(obj, Metadata): return obj.to_dict() if isinstance(obj, EventAndEntityMetadata): @@ -211,6 +214,11 @@ def to_dict(obj: Union[Dict, Block, Attachment, Metadata, EventAndEntityMetadata dict_attachments = [to_dict(a) for a in attachments] kwargs.update({"attachments": dict_attachments}) + chunks = kwargs.get("chunks", None) + if chunks is not None and isinstance(chunks, Sequence) and (not isinstance(chunks, str)): + dict_chunks = [to_dict(c) for c in chunks] + kwargs.update({"chunks": dict_chunks}) + metadata = kwargs.get("metadata", None) if metadata is not None and ( isinstance(metadata, Metadata) diff --git a/slack_sdk/web/legacy_client.py b/slack_sdk/web/legacy_client.py index df2bcc370..f11bbc495 100644 --- a/slack_sdk/web/legacy_client.py +++ b/slack_sdk/web/legacy_client.py @@ -19,11 +19,12 @@ 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 ..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 .legacy_base_client import LegacyBaseClient, SlackResponse from .internal_utils import ( _parse_web_class_objects, @@ -2632,6 +2633,7 @@ def chat_appendStream( channel: str, ts: str, markdown_text: str, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Appends text to an existing streaming conversation. @@ -2642,8 +2644,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) @@ -2885,6 +2889,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, ) -> Union[Future, SlackResponse]: """Starts a new streaming conversation. @@ -2897,8 +2902,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) @@ -2910,6 +2917,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, ) -> Union[Future, SlackResponse]: """Stops a streaming conversation. @@ -2922,6 +2930,7 @@ def chat_stopStream( "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) diff --git a/tests/slack_sdk/models/test_chunks.py b/tests/slack_sdk/models/test_chunks.py new file mode 100644 index 000000000..1b8b58c96 --- /dev/null +++ b/tests/slack_sdk/models/test_chunks.py @@ -0,0 +1,72 @@ +import unittest + +from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk, URLSource + + +class MarkdownTextChunkTests(unittest.TestCase): + def test_json(self): + self.assertDictEqual( + MarkdownTextChunk(text="greetings!").to_dict(), + { + "type": "markdown_text", + "text": "greetings!", + }, + ) + + +class TaskUpdateChunkTests(unittest.TestCase): + def test_json(self): + self.assertDictEqual( + TaskUpdateChunk(id="001", title="Waiting...", status="pending").to_dict(), + { + "type": "task_update", + "id": "001", + "title": "Waiting...", + "status": "pending", + }, + ) + self.assertDictEqual( + TaskUpdateChunk( + id="002", + title="Wondering...", + status="in_progress", + details="- Gathering information...", + ).to_dict(), + { + "type": "task_update", + "id": "002", + "title": "Wondering...", + "status": "in_progress", + "details": "- Gathering information...", + }, + ) + self.assertDictEqual( + TaskUpdateChunk( + id="003", + title="Answering...", + status="complete", + output="Found a solution", + sources=[ + URLSource( + text="The Free Encyclopedia", + url="https://wikipedia.org", + icon_url="https://example.com/globe.png", + ), + ], + ).to_dict(), + { + "type": "task_update", + "id": "003", + "title": "Answering...", + "status": "complete", + "output": "Found a solution", + "sources": [ + { + "type": "url", + "text": "The Free Encyclopedia", + "url": "https://wikipedia.org", + "icon_url": "https://example.com/globe.png", + }, + ], + }, + ) diff --git a/tests/slack_sdk/web/test_internal_utils.py b/tests/slack_sdk/web/test_internal_utils.py index ac7704b30..fc6574aab 100644 --- a/tests/slack_sdk/web/test_internal_utils.py +++ b/tests/slack_sdk/web/test_internal_utils.py @@ -2,18 +2,18 @@ import unittest from io import BytesIO from pathlib import Path -from typing import Dict, Sequence, Union +from typing import Dict -import pytest from slack_sdk.models.attachments import Attachment from slack_sdk.models.blocks import Block, DividerBlock +from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk from slack_sdk.web.internal_utils import ( _build_unexpected_body_error_message, + _get_url, + _next_cursor_is_present, _parse_web_class_objects, _to_v2_file_upload_item, - _next_cursor_is_present, - _get_url, ) @@ -57,6 +57,20 @@ def test_can_parse_sequence_of_attachments(self): for attachment in kwargs["attachments"]: assert isinstance(attachment, Dict) + def test_can_parse_sequence_of_chunks(self): + for chunks in [ + [MarkdownTextChunk(text="fiz"), TaskUpdateChunk(id="001", title="baz", status="complete")], # list + ( + MarkdownTextChunk(text="fiz"), + TaskUpdateChunk(id="001", title="baz", status="complete"), + ), # tuple + ]: + kwargs = {"chunks": chunks} + _parse_web_class_objects(kwargs) + assert kwargs["chunks"] + for chunks in kwargs["chunks"]: + assert isinstance(chunks, Dict) + def test_can_parse_str_blocks(self): input = json.dumps([Block(block_id="42").to_dict(), Block(block_id="24").to_dict()]) kwargs = {"blocks": input} @@ -71,6 +85,15 @@ def test_can_parse_str_attachments(self): assert isinstance(kwargs["attachments"], str) assert input == kwargs["attachments"] + def test_can_parse_str_chunks(self): + input = json.dumps( + [MarkdownTextChunk(text="fiz").to_dict(), TaskUpdateChunk(id="001", title="baz", status="complete").to_dict()] + ) + kwargs = {"chunks": input} + _parse_web_class_objects(kwargs) + assert isinstance(kwargs["chunks"], str) + assert input == kwargs["chunks"] + def test_can_parse_user_auth_blocks(self): kwargs = { "channel": "C12345", From f4c0182be7daf7c1c14552763dd204c33f2b64d6 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 16 Jan 2026 15:25:46 -0800 Subject: [PATCH 2/8] feat: support and flush chunks in the chat stream helper (#1809) --- slack_sdk/web/async_chat_stream.py | 36 +++++--- slack_sdk/web/async_client.py | 2 +- slack_sdk/web/chat_stream.py | 36 +++++--- slack_sdk/web/client.py | 2 +- slack_sdk/web/legacy_client.py | 2 +- tests/slack_sdk/web/test_chat_stream.py | 82 +++++++++++++++++- .../web/test_async_chat_stream.py | 83 ++++++++++++++++++- 7 files changed, 212 insertions(+), 31 deletions(-) diff --git a/slack_sdk/web/async_chat_stream.py b/slack_sdk/web/async_chat_stream.py index 4661f19dd..550902182 100644 --- a/slack_sdk/web/async_chat_stream.py +++ b/slack_sdk/web/async_chat_stream.py @@ -10,10 +10,11 @@ import json import logging -from typing import TYPE_CHECKING, Dict, Optional, Sequence, Union +from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Union import slack_sdk.errors as e from slack_sdk.models.blocks.blocks import Block +from slack_sdk.models.messages.chunk import Chunk, MarkdownTextChunk from slack_sdk.models.metadata import Metadata from slack_sdk.web.async_slack_response import AsyncSlackResponse @@ -75,7 +76,8 @@ def __init__( async def append( self, *, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> Optional[AsyncSlackResponse]: """Append to the stream. @@ -84,6 +86,7 @@ async def append( is stopped this method cannot be called. Args: + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -111,9 +114,10 @@ async def append( raise e.SlackRequestError(f"Cannot append to stream: stream state is {self._state}") if kwargs.get("token"): self._token = kwargs.pop("token") - self._buffer += markdown_text - if len(self._buffer) >= self._buffer_size: - return await self._flush_buffer(**kwargs) + if markdown_text is not None: + self._buffer += markdown_text + if len(self._buffer) >= self._buffer_size or chunks is not None: + return await self._flush_buffer(chunks=chunks, **kwargs) details = { "buffer_length": len(self._buffer), "buffer_size": self._buffer_size, @@ -129,6 +133,7 @@ async def stop( self, *, markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, metadata: Optional[Union[Dict, Metadata]] = None, **kwargs, @@ -137,6 +142,7 @@ async def stop( Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -177,26 +183,36 @@ async def stop( raise e.SlackRequestError("Failed to stop stream: stream not started") self._stream_ts = str(response["ts"]) self._state = "in_progress" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) response = await self._client.chat_stopStream( token=self._token, channel=self._stream_args["channel"], ts=self._stream_ts, blocks=blocks, - markdown_text=self._buffer, + chunks=flushings, metadata=metadata, **kwargs, ) self._state = "completed" return response - async def _flush_buffer(self, **kwargs) -> AsyncSlackResponse: - """Flush the internal buffer by making appropriate API calls.""" + async def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs) -> AsyncSlackResponse: + """Flush the internal buffer with chunks by making appropriate API calls.""" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) if not self._stream_ts: response = await self._client.chat_startStream( **self._stream_args, token=self._token, **kwargs, - markdown_text=self._buffer, + chunks=flushings, ) self._stream_ts = response.get("ts") self._state = "in_progress" @@ -206,7 +222,7 @@ async def _flush_buffer(self, **kwargs) -> AsyncSlackResponse: channel=self._stream_args["channel"], ts=self._stream_ts, **kwargs, - markdown_text=self._buffer, + chunks=flushings, ) self._buffer = "" return response diff --git a/slack_sdk/web/async_client.py b/slack_sdk/web/async_client.py index 0a9f702b9..5aaa2c610 100644 --- a/slack_sdk/web/async_client.py +++ b/slack_sdk/web/async_client.py @@ -2631,7 +2631,7 @@ async def chat_appendStream( *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> AsyncSlackResponse: diff --git a/slack_sdk/web/chat_stream.py b/slack_sdk/web/chat_stream.py index 1a379c9cb..acdac728a 100644 --- a/slack_sdk/web/chat_stream.py +++ b/slack_sdk/web/chat_stream.py @@ -1,9 +1,10 @@ import json import logging -from typing import TYPE_CHECKING, Dict, Optional, Sequence, Union +from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Union import slack_sdk.errors as e from slack_sdk.models.blocks.blocks import Block +from slack_sdk.models.messages.chunk import Chunk, MarkdownTextChunk from slack_sdk.models.metadata import Metadata from slack_sdk.web.slack_response import SlackResponse @@ -65,7 +66,8 @@ def __init__( def append( self, *, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> Optional[SlackResponse]: """Append to the stream. @@ -74,6 +76,7 @@ def append( is stopped this method cannot be called. Args: + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -101,9 +104,10 @@ def append( raise e.SlackRequestError(f"Cannot append to stream: stream state is {self._state}") if kwargs.get("token"): self._token = kwargs.pop("token") - self._buffer += markdown_text - if len(self._buffer) >= self._buffer_size: - return self._flush_buffer(**kwargs) + if markdown_text is not None: + self._buffer += markdown_text + if len(self._buffer) >= self._buffer_size or chunks is not None: + return self._flush_buffer(chunks=chunks, **kwargs) details = { "buffer_length": len(self._buffer), "buffer_size": self._buffer_size, @@ -119,6 +123,7 @@ def stop( self, *, markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, metadata: Optional[Union[Dict, Metadata]] = None, **kwargs, @@ -127,6 +132,7 @@ def stop( Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -167,26 +173,36 @@ def stop( raise e.SlackRequestError("Failed to stop stream: stream not started") self._stream_ts = str(response["ts"]) self._state = "in_progress" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) response = self._client.chat_stopStream( token=self._token, channel=self._stream_args["channel"], ts=self._stream_ts, blocks=blocks, - markdown_text=self._buffer, + chunks=flushings, metadata=metadata, **kwargs, ) self._state = "completed" return response - def _flush_buffer(self, **kwargs) -> SlackResponse: - """Flush the internal buffer by making appropriate API calls.""" + def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs) -> SlackResponse: + """Flush the internal buffer with chunks by making appropriate API calls.""" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) if not self._stream_ts: response = self._client.chat_startStream( **self._stream_args, token=self._token, **kwargs, - markdown_text=self._buffer, + chunks=flushings, ) self._stream_ts = response.get("ts") self._state = "in_progress" @@ -196,7 +212,7 @@ def _flush_buffer(self, **kwargs) -> SlackResponse: channel=self._stream_args["channel"], ts=self._stream_ts, **kwargs, - markdown_text=self._buffer, + chunks=flushings, ) self._buffer = "" return response diff --git a/slack_sdk/web/client.py b/slack_sdk/web/client.py index 1a70681a4..392a261ad 100644 --- a/slack_sdk/web/client.py +++ b/slack_sdk/web/client.py @@ -2621,7 +2621,7 @@ def chat_appendStream( *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> SlackResponse: diff --git a/slack_sdk/web/legacy_client.py b/slack_sdk/web/legacy_client.py index f11bbc495..7bb0609c5 100644 --- a/slack_sdk/web/legacy_client.py +++ b/slack_sdk/web/legacy_client.py @@ -2632,7 +2632,7 @@ def chat_appendStream( *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> Union[Future, SlackResponse]: diff --git a/tests/slack_sdk/web/test_chat_stream.py b/tests/slack_sdk/web/test_chat_stream.py index 75c13c8c2..a6d846769 100644 --- a/tests/slack_sdk/web/test_chat_stream.py +++ b/tests/slack_sdk/web/test_chat_stream.py @@ -7,6 +7,7 @@ from slack_sdk.models.blocks.basic_components import FeedbackButtonObject from slack_sdk.models.blocks.block_elements import FeedbackButtonsElement, IconButtonElement from slack_sdk.models.blocks.blocks import ContextActionsBlock +from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk from tests.mock_web_api_server import cleanup_mock_web_api_server, setup_mock_web_api_server from tests.slack_sdk.web.mock_web_api_handler import MockHandler @@ -105,7 +106,10 @@ def test_streams_a_short_message(self): stop_request = self.thread.server.chat_stream_requests.get("/chat.stopStream", {}) self.assertEqual(stop_request.get("channel"), "C0123456789") self.assertEqual(stop_request.get("ts"), "123.123") - self.assertEqual(stop_request.get("markdown_text"), "nice!") + self.assertEqual( + json.dumps(stop_request.get("chunks")), + '[{"text": "nice!", "type": "markdown_text"}]', + ) def test_streams_a_long_message(self): streamer = self.client.chat_stream( @@ -146,13 +150,19 @@ def test_streams_a_long_message(self): start_request = self.thread.server.chat_stream_requests.get("/chat.startStream", {}) self.assertEqual(start_request.get("channel"), "C0123456789") self.assertEqual(start_request.get("thread_ts"), "123.000") - self.assertEqual(start_request.get("markdown_text"), "**this messag") + self.assertEqual( + json.dumps(start_request.get("chunks")), + '[{"text": "**this messag", "type": "markdown_text"}]', + ) self.assertEqual(start_request.get("recipient_team_id"), "T0123456789") self.assertEqual(start_request.get("recipient_user_id"), "U0123456789") append_request = self.thread.server.chat_stream_requests.get("/chat.appendStream", {}) self.assertEqual(append_request.get("channel"), "C0123456789") - self.assertEqual(append_request.get("markdown_text"), "e is bold!") + self.assertEqual( + json.dumps(append_request.get("chunks")), + '[{"text": "e is bold!", "type": "markdown_text"}]', + ) self.assertEqual(append_request.get("token"), "xoxb-chat_stream_test_token1") self.assertEqual(append_request.get("ts"), "123.123") @@ -162,10 +172,74 @@ def test_streams_a_long_message(self): '[{"elements": [{"negative_button": {"text": {"emoji": true, "text": "bad", "type": "plain_text"}, "value": "-1"}, "positive_button": {"text": {"emoji": true, "text": "good", "type": "plain_text"}, "value": "+1"}, "type": "feedback_buttons"}, {"icon": "trash", "text": {"emoji": true, "text": "delete", "type": "plain_text"}, "type": "icon_button"}], "type": "context_actions"}]', ) self.assertEqual(stop_request.get("channel"), "C0123456789") - self.assertEqual(stop_request.get("markdown_text"), "**") + self.assertEqual( + json.dumps(stop_request.get("chunks")), + '[{"text": "**", "type": "markdown_text"}]', + ) self.assertEqual(stop_request.get("token"), "xoxb-chat_stream_test_token2") self.assertEqual(stop_request.get("ts"), "123.123") + def test_streams_a_chunk_message(self): + streamer = self.client.chat_stream( + channel="C0123456789", + recipient_team_id="T0123456789", + recipient_user_id="U0123456789", + thread_ts="123.000", + ) + streamer.append(markdown_text="**this is ") + streamer.append(markdown_text="buffered**") + streamer.append( + chunks=[ + TaskUpdateChunk( + id="001", + title="Counting...", + status="pending", + ), + ], + ) + streamer.append( + chunks=[ + MarkdownTextChunk(text="**this is unbuffered**"), + ], + ) + streamer.append(markdown_text="\n") + streamer.stop( + chunks=[ + MarkdownTextChunk(text=":space_invader:"), + ], + ) + + self.assertEqual(self.received_requests.get("/chat.startStream", 0), 1) + self.assertEqual(self.received_requests.get("/chat.appendStream", 0), 1) + self.assertEqual(self.received_requests.get("/chat.stopStream", 0), 1) + + if hasattr(self.thread.server, "chat_stream_requests"): + start_request = self.thread.server.chat_stream_requests.get("/chat.startStream", {}) + self.assertEqual(start_request.get("channel"), "C0123456789") + self.assertEqual(start_request.get("thread_ts"), "123.000") + self.assertEqual( + json.dumps(start_request.get("chunks")), + '[{"text": "**this is buffered**", "type": "markdown_text"}, {"id": "001", "status": "pending", "title": "Counting...", "type": "task_update"}]', + ) + self.assertEqual(start_request.get("recipient_team_id"), "T0123456789") + self.assertEqual(start_request.get("recipient_user_id"), "U0123456789") + + append_request = self.thread.server.chat_stream_requests.get("/chat.appendStream", {}) + self.assertEqual(append_request.get("channel"), "C0123456789") + self.assertEqual(append_request.get("ts"), "123.123") + self.assertEqual( + json.dumps(append_request.get("chunks")), + '[{"text": "**this is unbuffered**", "type": "markdown_text"}]', + ) + + stop_request = self.thread.server.chat_stream_requests.get("/chat.stopStream", {}) + self.assertEqual(stop_request.get("channel"), "C0123456789") + self.assertEqual(stop_request.get("ts"), "123.123") + self.assertEqual( + json.dumps(stop_request.get("chunks")), + '[{"text": "\\n", "type": "markdown_text"}, {"text": ":space_invader:", "type": "markdown_text"}]', + ) + def test_streams_errors_when_appending_to_an_unstarted_stream(self): streamer = self.client.chat_stream( channel="C0123456789", diff --git a/tests/slack_sdk_async/web/test_async_chat_stream.py b/tests/slack_sdk_async/web/test_async_chat_stream.py index 212fee1e2..2a4f5b931 100644 --- a/tests/slack_sdk_async/web/test_async_chat_stream.py +++ b/tests/slack_sdk_async/web/test_async_chat_stream.py @@ -6,6 +6,7 @@ from slack_sdk.models.blocks.basic_components import FeedbackButtonObject from slack_sdk.models.blocks.block_elements import FeedbackButtonsElement, IconButtonElement from slack_sdk.models.blocks.blocks import ContextActionsBlock +from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk from slack_sdk.web.async_client import AsyncWebClient from tests.mock_web_api_server import cleanup_mock_web_api_server, setup_mock_web_api_server from tests.slack_sdk.web.mock_web_api_handler import MockHandler @@ -107,7 +108,10 @@ async def test_streams_a_short_message(self): stop_request = self.thread.server.chat_stream_requests.get("/chat.stopStream", {}) self.assertEqual(stop_request.get("channel"), "C0123456789") self.assertEqual(stop_request.get("ts"), "123.123") - self.assertEqual(stop_request.get("markdown_text"), "nice!") + self.assertEqual( + json.dumps(stop_request.get("chunks")), + '[{"text": "nice!", "type": "markdown_text"}]', + ) @async_test async def test_streams_a_long_message(self): @@ -149,13 +153,19 @@ async def test_streams_a_long_message(self): start_request = self.thread.server.chat_stream_requests.get("/chat.startStream", {}) self.assertEqual(start_request.get("channel"), "C0123456789") self.assertEqual(start_request.get("thread_ts"), "123.000") - self.assertEqual(start_request.get("markdown_text"), "**this messag") + self.assertEqual( + json.dumps(start_request.get("chunks")), + '[{"text": "**this messag", "type": "markdown_text"}]', + ) self.assertEqual(start_request.get("recipient_team_id"), "T0123456789") self.assertEqual(start_request.get("recipient_user_id"), "U0123456789") append_request = self.thread.server.chat_stream_requests.get("/chat.appendStream", {}) self.assertEqual(append_request.get("channel"), "C0123456789") - self.assertEqual(append_request.get("markdown_text"), "e is bold!") + self.assertEqual( + json.dumps(append_request.get("chunks")), + '[{"text": "e is bold!", "type": "markdown_text"}]', + ) self.assertEqual(append_request.get("token"), "xoxb-chat_stream_test_token1") self.assertEqual(append_request.get("ts"), "123.123") @@ -165,10 +175,75 @@ async def test_streams_a_long_message(self): '[{"elements": [{"negative_button": {"text": {"emoji": true, "text": "bad", "type": "plain_text"}, "value": "-1"}, "positive_button": {"text": {"emoji": true, "text": "good", "type": "plain_text"}, "value": "+1"}, "type": "feedback_buttons"}, {"icon": "trash", "text": {"emoji": true, "text": "delete", "type": "plain_text"}, "type": "icon_button"}], "type": "context_actions"}]', ) self.assertEqual(stop_request.get("channel"), "C0123456789") - self.assertEqual(stop_request.get("markdown_text"), "**") + self.assertEqual( + json.dumps(stop_request.get("chunks")), + '[{"text": "**", "type": "markdown_text"}]', + ) self.assertEqual(stop_request.get("token"), "xoxb-chat_stream_test_token2") self.assertEqual(stop_request.get("ts"), "123.123") + @async_test + async def test_streams_a_chunk_message(self): + streamer = await self.client.chat_stream( + channel="C0123456789", + recipient_team_id="T0123456789", + recipient_user_id="U0123456789", + thread_ts="123.000", + ) + await streamer.append(markdown_text="**this is ") + await streamer.append(markdown_text="buffered**") + await streamer.append( + chunks=[ + TaskUpdateChunk( + id="001", + title="Counting...", + status="pending", + ), + ], + ) + await streamer.append( + chunks=[ + MarkdownTextChunk(text="**this is unbuffered**"), + ], + ) + await streamer.append(markdown_text="\n") + await streamer.stop( + chunks=[ + MarkdownTextChunk(text=":space_invader:"), + ], + ) + + self.assertEqual(self.received_requests.get("/chat.startStream", 0), 1) + self.assertEqual(self.received_requests.get("/chat.appendStream", 0), 1) + self.assertEqual(self.received_requests.get("/chat.stopStream", 0), 1) + + if hasattr(self.thread.server, "chat_stream_requests"): + start_request = self.thread.server.chat_stream_requests.get("/chat.startStream", {}) + self.assertEqual(start_request.get("channel"), "C0123456789") + self.assertEqual(start_request.get("thread_ts"), "123.000") + self.assertEqual( + json.dumps(start_request.get("chunks")), + '[{"text": "**this is buffered**", "type": "markdown_text"}, {"id": "001", "status": "pending", "title": "Counting...", "type": "task_update"}]', + ) + self.assertEqual(start_request.get("recipient_team_id"), "T0123456789") + self.assertEqual(start_request.get("recipient_user_id"), "U0123456789") + + append_request = self.thread.server.chat_stream_requests.get("/chat.appendStream", {}) + self.assertEqual(append_request.get("channel"), "C0123456789") + self.assertEqual(append_request.get("ts"), "123.123") + self.assertEqual( + json.dumps(append_request.get("chunks")), + '[{"text": "**this is unbuffered**", "type": "markdown_text"}]', + ) + + stop_request = self.thread.server.chat_stream_requests.get("/chat.stopStream", {}) + self.assertEqual(stop_request.get("channel"), "C0123456789") + self.assertEqual(stop_request.get("ts"), "123.123") + self.assertEqual( + json.dumps(stop_request.get("chunks")), + '[{"text": "\\n", "type": "markdown_text"}, {"text": ":space_invader:", "type": "markdown_text"}]', + ) + @async_test async def test_streams_errors_when_appending_to_an_unstarted_stream(self): streamer = await self.client.chat_stream( From b0311489b27f76e91d7bde515e163c110af2c7c1 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 16 Jan 2026 15:50:24 -0800 Subject: [PATCH 3/8] feat: add task_card and plan blocks (#1819) --- slack_sdk/models/blocks/__init__.py | 6 ++ slack_sdk/models/blocks/block_elements.py | 42 +++++++++ slack_sdk/models/blocks/blocks.py | 106 ++++++++++++++++++++++ slack_sdk/models/messages/chunk.py | 54 +---------- tests/slack_sdk/models/test_blocks.py | 83 +++++++++++++++++ tests/slack_sdk/models/test_chunks.py | 14 ++- 6 files changed, 253 insertions(+), 52 deletions(-) diff --git a/slack_sdk/models/blocks/__init__.py b/slack_sdk/models/blocks/__init__.py index d2776a9dc..b8592c2e9 100644 --- a/slack_sdk/models/blocks/__init__.py +++ b/slack_sdk/models/blocks/__init__.py @@ -55,6 +55,7 @@ StaticSelectElement, TimePickerElement, UrlInputElement, + UrlSourceElement, UserMultiSelectElement, UserSelectElement, ) @@ -70,9 +71,11 @@ ImageBlock, InputBlock, MarkdownBlock, + PlanBlock, RichTextBlock, SectionBlock, TableBlock, + TaskCardBlock, VideoBlock, ) @@ -111,6 +114,7 @@ "PlainTextInputElement", "EmailInputElement", "UrlInputElement", + "UrlSourceElement", "NumberInputElement", "RadioButtonsElement", "SelectElement", @@ -135,8 +139,10 @@ "ImageBlock", "InputBlock", "MarkdownBlock", + "PlanBlock", "SectionBlock", "TableBlock", + "TaskCardBlock", "VideoBlock", "RichTextBlock", ] diff --git a/slack_sdk/models/blocks/block_elements.py b/slack_sdk/models/blocks/block_elements.py index 89f0a7994..be683162b 100644 --- a/slack_sdk/models/blocks/block_elements.py +++ b/slack_sdk/models/blocks/block_elements.py @@ -1654,6 +1654,48 @@ def __init__( self.dispatch_action_config = dispatch_action_config +# ------------------------------------------------- +# Url Source Element +# ------------------------------------------------- + + +class UrlSourceElement(BlockElement): + type = "url" + + @property + def attributes(self) -> Set[str]: # type: ignore[override] + return super().attributes.union( + { + "url", + "text", + "icon_url", + } + ) + + def __init__( + self, + *, + url: str, + text: str, + icon_url: Optional[str] = None, + **others: Dict, + ): + """ + A URL source element to reference in a task card block. + https://docs.slack.dev/reference/block-kit/block-elements/url-source-element + + Args: + url (required): The URL type source. + text (required): Display text for the URL. + icon_url: Optional icon URL to display with the source. + """ + super().__init__(type=self.type) + show_unknown_key_warning(self, others) + self.url = url + self.text = text + self.icon_url = icon_url + + # ------------------------------------------------- # Number Input Element # ------------------------------------------------- diff --git a/slack_sdk/models/blocks/blocks.py b/slack_sdk/models/blocks/blocks.py index cac463c99..26c25d73f 100644 --- a/slack_sdk/models/blocks/blocks.py +++ b/slack_sdk/models/blocks/blocks.py @@ -16,6 +16,7 @@ InputInteractiveElement, InteractiveElement, RichTextElement, + UrlSourceElement, ) # ------------------------------------------------- @@ -97,6 +98,10 @@ def parse(cls, block: Union[dict, "Block"]) -> Optional["Block"]: return RichTextBlock(**block) elif type == TableBlock.type: return TableBlock(**block) + elif type == TaskCardBlock.type: + return TaskCardBlock(**block) + elif type == PlanBlock.type: + return PlanBlock(**block) else: cls.logger.warning(f"Unknown block detected and skipped ({block})") return None @@ -777,3 +782,104 @@ def __init__( @JsonValidator("rows attribute must be specified") def _validate_rows(self): return self.rows is not None and len(self.rows) > 0 + + +class TaskCardBlock(Block): + type = "task_card" + + @property + def attributes(self) -> Set[str]: # type: ignore[override] + return super().attributes.union( + { + "task_id", + "title", + "details", + "output", + "sources", + "status", + } + ) + + def __init__( + self, + *, + task_id: str, + title: str, + details: Optional[Union[RichTextBlock, dict]] = None, + output: Optional[Union[RichTextBlock, dict]] = None, + sources: Optional[Sequence[Union[UrlSourceElement, dict]]] = None, + status: str, # pending, in_progress, complete, error + block_id: Optional[str] = None, + **others: dict, + ): + """A discrete action or tool call. + https://docs.slack.dev/reference/block-kit/blocks/task-card-block/ + + Args: + block_id: A string acting as a unique identifier for a block. If not specified, one will be generated. + Maximum length for this field is 255 characters. + block_id should be unique for each message and each iteration of a message. + If a message is updated, use a new block_id. + task_id (required): ID for the task + title (required): Title of the task in plain text + details: Details of the task in the form of a single "rich_text" entity. + output: Output of the task in the form of a single "rich_text" entity. + sources: List of sources used to generate a response + status: The state of a task. Either "pending" or "in_progress" or "complete" or "error". + """ + super().__init__(type=self.type, block_id=block_id) + show_unknown_key_warning(self, others) + + self.task_id = task_id + self.title = title + self.details = details + self.output = output + self.sources = sources + self.status = status + + @JsonValidator("status must be an expected value (pending, in_progress, complete, or error)") + def _validate_rows(self): + return self.status in ["pending", "in_progress", "complete", "error"] + + +class PlanBlock(Block): + type = "plan" + + @property + def attributes(self) -> Set[str]: # type: ignore[override] + return super().attributes.union( + { + "plan_id", + "title", + "tasks", + } + ) + + def __init__( + self, + *, + plan_id: str, + title: str, + tasks: Optional[Sequence[Union[Dict, TaskCardBlock]]] = None, + block_id: Optional[str] = None, + **others: dict, + ): + """A collection of related tasks. + https://docs.slack.dev/reference/block-kit/blocks/plan-block/ + + Args: + block_id: A string acting as a unique identifier for a block. If not specified, one will be generated. + Maximum length for this field is 255 characters. + block_id should be unique for each message and each iteration of a message. + If a message is updated, use a new block_id. + plan_id (required): ID for the plan (May be removed / made optional, feel free to pass in a random UUID + for now) + title (required): Title of the plan in plain text + tasks: Details of the task in the form of a single "rich_text" entity. + """ + super().__init__(type=self.type, block_id=block_id) + show_unknown_key_warning(self, others) + + self.plan_id = plan_id + self.title = title + self.tasks = tasks diff --git a/slack_sdk/models/messages/chunk.py b/slack_sdk/models/messages/chunk.py index 837714af0..b00daebd1 100644 --- a/slack_sdk/models/messages/chunk.py +++ b/slack_sdk/models/messages/chunk.py @@ -1,9 +1,9 @@ import logging -from typing import Any, Dict, Optional, Sequence, Set, Union +from typing import 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 +from slack_sdk.models.blocks.block_elements import UrlSourceElement class Chunk(JsonObject): @@ -67,44 +67,6 @@ def __init__( 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" @@ -129,7 +91,7 @@ def __init__( status: str, # "pending", "in_progress", "complete", "error" details: Optional[str] = None, output: Optional[str] = None, - sources: Optional[Sequence[Union[Dict, URLSource]]] = None, + sources: Optional[Sequence[Union[Dict, UrlSourceElement]]] = None, **others: Dict, ): """Used for displaying tool execution progress in a timeline-style UI. @@ -144,12 +106,4 @@ def __init__( 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)}") + self.sources = sources diff --git a/tests/slack_sdk/models/test_blocks.py b/tests/slack_sdk/models/test_blocks.py index 6f3b9f141..daada60dd 100644 --- a/tests/slack_sdk/models/test_blocks.py +++ b/tests/slack_sdk/models/test_blocks.py @@ -21,6 +21,7 @@ Option, OverflowMenuElement, PlainTextObject, + PlanBlock, RawTextObject, RichTextBlock, RichTextElementParts, @@ -31,6 +32,7 @@ SectionBlock, StaticSelectElement, TableBlock, + TaskCardBlock, VideoBlock, ) from slack_sdk.models.blocks.basic_components import FeedbackButtonObject, SlackFile @@ -890,6 +892,87 @@ def test_text_length_12001(self): MarkdownBlock(**input).validate_json() +# ---------------------------------------------- +# Plan +# ---------------------------------------------- + + +class PlanBlockTests(unittest.TestCase): + def test_document(self): + input = { + "type": "plan", + "plan_id": "plan_1", + "title": "Thinking completed", + "tasks": [ + { + "task_id": "call_001", + "title": "Fetched user profile information", + "status": "in_progress", + "details": { + "type": "rich_text", + "elements": [ + {"type": "rich_text_section", "elements": [{"type": "text", "text": "Searched database..."}]} + ], + }, + "output": { + "type": "rich_text", + "elements": [ + {"type": "rich_text_section", "elements": [{"type": "text", "text": "Profile data loaded"}]} + ], + }, + }, + { + "task_id": "call_002", + "title": "Checked user permissions", + "status": "pending", + }, + { + "task_id": "call_003", + "title": "Generated comprehensive user report", + "status": "complete", + "output": { + "type": "rich_text", + "elements": [ + {"type": "rich_text_section", "elements": [{"type": "text", "text": "15 data points compiled"}]} + ], + }, + }, + ], + } + self.assertDictEqual(input, PlanBlock(**input).to_dict()) + self.assertDictEqual(input, Block.parse(input).to_dict()) + + +# ---------------------------------------------- +# Task card +# ---------------------------------------------- + + +class TaskCardBlockTests(unittest.TestCase): + def test_document(self): + input = { + "type": "task_card", + "task_id": "task_1", + "title": "Fetching weather data", + "status": "pending", + "output": { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [{"type": "text", "text": "Found weather data for Chicago from 2 sources"}], + } + ], + }, + "sources": [ + {"type": "url", "url": "https://weather.com/", "text": "weather.com"}, + {"type": "url", "url": "https://www.accuweather.com/", "text": "accuweather.com"}, + ], + } + self.assertDictEqual(input, TaskCardBlock(**input).to_dict()) + self.assertDictEqual(input, Block.parse(input).to_dict()) + + # ---------------------------------------------- # Video # ---------------------------------------------- diff --git a/tests/slack_sdk/models/test_chunks.py b/tests/slack_sdk/models/test_chunks.py index 1b8b58c96..202b4bf77 100644 --- a/tests/slack_sdk/models/test_chunks.py +++ b/tests/slack_sdk/models/test_chunks.py @@ -1,6 +1,7 @@ import unittest -from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk, URLSource +from slack_sdk.models.blocks.block_elements import UrlSourceElement +from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk class MarkdownTextChunkTests(unittest.TestCase): @@ -47,7 +48,11 @@ def test_json(self): status="complete", output="Found a solution", sources=[ - URLSource( + UrlSourceElement( + text="Discussion of Life's Questions", + url="https://www.answers.com", + ), + UrlSourceElement( text="The Free Encyclopedia", url="https://wikipedia.org", icon_url="https://example.com/globe.png", @@ -61,6 +66,11 @@ def test_json(self): "status": "complete", "output": "Found a solution", "sources": [ + { + "type": "url", + "text": "Discussion of Life's Questions", + "url": "https://www.answers.com", + }, { "type": "url", "text": "The Free Encyclopedia", From b1dc1990f6cad35d87d1ccf5e0eec2f502a0ad90 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 16 Jan 2026 16:03:59 -0800 Subject: [PATCH 4/8] feat: add task_display_mode option to the start of chat streams (#1820) Co-authored-by: Michael Brooks --- slack_sdk/web/async_chat_stream.py | 4 ++++ slack_sdk/web/async_client.py | 6 ++++++ slack_sdk/web/chat_stream.py | 4 ++++ slack_sdk/web/client.py | 6 ++++++ slack_sdk/web/legacy_client.py | 2 ++ tests/slack_sdk/web/test_chat_stream.py | 2 ++ 6 files changed, 24 insertions(+) diff --git a/slack_sdk/web/async_chat_stream.py b/slack_sdk/web/async_chat_stream.py index 550902182..7af774bbc 100644 --- a/slack_sdk/web/async_chat_stream.py +++ b/slack_sdk/web/async_chat_stream.py @@ -39,6 +39,7 @@ def __init__( buffer_size: int, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ): """Initialize a new ChatStream instance. @@ -54,6 +55,8 @@ def __init__( recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits. **kwargs: Additional arguments passed to the underlying API calls. @@ -66,6 +69,7 @@ def __init__( "thread_ts": thread_ts, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "task_display_mode": task_display_mode, **kwargs, } self._buffer = "" diff --git a/slack_sdk/web/async_client.py b/slack_sdk/web/async_client.py index 5aaa2c610..7464b754d 100644 --- a/slack_sdk/web/async_client.py +++ b/slack_sdk/web/async_client.py @@ -2889,6 +2889,7 @@ async def chat_startStream( recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> AsyncSlackResponse: """Starts a new streaming conversation. @@ -2902,6 +2903,7 @@ async def chat_startStream( "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, "chunks": chunks, + "task_display_mode": task_display_mode, } ) _parse_web_class_objects(kwargs) @@ -2944,6 +2946,7 @@ async def chat_stream( thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> AsyncChatStream: """Stream markdown text into a conversation. @@ -2970,6 +2973,8 @@ async def chat_stream( recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -2995,6 +3000,7 @@ async def chat_stream( thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, ) diff --git a/slack_sdk/web/chat_stream.py b/slack_sdk/web/chat_stream.py index acdac728a..580f7cacb 100644 --- a/slack_sdk/web/chat_stream.py +++ b/slack_sdk/web/chat_stream.py @@ -29,6 +29,7 @@ def __init__( buffer_size: int, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ): """Initialize a new ChatStream instance. @@ -44,6 +45,8 @@ def __init__( recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits. **kwargs: Additional arguments passed to the underlying API calls. @@ -56,6 +59,7 @@ def __init__( "thread_ts": thread_ts, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "task_display_mode": task_display_mode, **kwargs, } self._buffer = "" diff --git a/slack_sdk/web/client.py b/slack_sdk/web/client.py index 392a261ad..638b4ab67 100644 --- a/slack_sdk/web/client.py +++ b/slack_sdk/web/client.py @@ -2879,6 +2879,7 @@ def chat_startStream( recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> SlackResponse: """Starts a new streaming conversation. @@ -2892,6 +2893,7 @@ def chat_startStream( "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, "chunks": chunks, + "task_display_mode": task_display_mode, } ) _parse_web_class_objects(kwargs) @@ -2934,6 +2936,7 @@ def chat_stream( thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> ChatStream: """Stream markdown text into a conversation. @@ -2960,6 +2963,8 @@ def chat_stream( recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -2985,6 +2990,7 @@ def chat_stream( thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, ) diff --git a/slack_sdk/web/legacy_client.py b/slack_sdk/web/legacy_client.py index 7bb0609c5..061be7c85 100644 --- a/slack_sdk/web/legacy_client.py +++ b/slack_sdk/web/legacy_client.py @@ -2890,6 +2890,7 @@ def chat_startStream( recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> Union[Future, SlackResponse]: """Starts a new streaming conversation. @@ -2903,6 +2904,7 @@ def chat_startStream( "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, "chunks": chunks, + "task_display_mode": task_display_mode, } ) _parse_web_class_objects(kwargs) diff --git a/tests/slack_sdk/web/test_chat_stream.py b/tests/slack_sdk/web/test_chat_stream.py index a6d846769..0a11b9d53 100644 --- a/tests/slack_sdk/web/test_chat_stream.py +++ b/tests/slack_sdk/web/test_chat_stream.py @@ -185,6 +185,7 @@ def test_streams_a_chunk_message(self): recipient_team_id="T0123456789", recipient_user_id="U0123456789", thread_ts="123.000", + task_display_mode="timeline", ) streamer.append(markdown_text="**this is ") streamer.append(markdown_text="buffered**") @@ -223,6 +224,7 @@ def test_streams_a_chunk_message(self): ) self.assertEqual(start_request.get("recipient_team_id"), "T0123456789") self.assertEqual(start_request.get("recipient_user_id"), "U0123456789") + self.assertEqual(start_request.get("task_display_mode"), "timeline") append_request = self.thread.server.chat_stream_requests.get("/chat.appendStream", {}) self.assertEqual(append_request.get("channel"), "C0123456789") From 70327cad5c0121dfc28f0a403a1c0d09d11f215a Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Fri, 16 Jan 2026 16:28:04 -0800 Subject: [PATCH 5/8] feat: add plan_update chunk for chat streaming (#1821) Co-authored-by: Michael Brooks --- slack_sdk/models/messages/chunk.py | 25 ++++++++++++++++++++++ tests/slack_sdk/models/test_chunks.py | 13 ++++++++++- tests/slack_sdk/web/test_internal_utils.py | 16 ++++++++++---- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/slack_sdk/models/messages/chunk.py b/slack_sdk/models/messages/chunk.py index b00daebd1..4db35621b 100644 --- a/slack_sdk/models/messages/chunk.py +++ b/slack_sdk/models/messages/chunk.py @@ -34,6 +34,8 @@ def parse(cls, chunk: Union[Dict, "Chunk"]) -> Optional["Chunk"]: type = chunk["type"] if type == MarkdownTextChunk.type: return MarkdownTextChunk(**chunk) + elif type == PlanUpdateChunk.type: + return PlanUpdateChunk(**chunk) elif type == TaskUpdateChunk.type: return TaskUpdateChunk(**chunk) else: @@ -67,6 +69,29 @@ def __init__( self.text = text +class PlanUpdateChunk(Chunk): + type = "plan_update" + + @property + def attributes(self) -> Set[str]: # type: ignore[override] + return super().attributes.union({"title"}) + + def __init__( + self, + *, + title: str, + **others: Dict, + ): + """An updated title of plans for task and tool calls. + + https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming + """ + super().__init__(type=self.type) + show_unknown_key_warning(self, others) + + self.title = title + + class TaskUpdateChunk(Chunk): type = "task_update" diff --git a/tests/slack_sdk/models/test_chunks.py b/tests/slack_sdk/models/test_chunks.py index 202b4bf77..293f5acb2 100644 --- a/tests/slack_sdk/models/test_chunks.py +++ b/tests/slack_sdk/models/test_chunks.py @@ -1,7 +1,7 @@ import unittest from slack_sdk.models.blocks.block_elements import UrlSourceElement -from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk +from slack_sdk.models.messages.chunk import MarkdownTextChunk, PlanUpdateChunk, TaskUpdateChunk class MarkdownTextChunkTests(unittest.TestCase): @@ -15,6 +15,17 @@ def test_json(self): ) +class PlanUpdateChunkTests(unittest.TestCase): + def test_json(self): + self.assertDictEqual( + PlanUpdateChunk(title="Crunching numbers...").to_dict(), + { + "type": "plan_update", + "title": "Crunching numbers...", + }, + ) + + class TaskUpdateChunkTests(unittest.TestCase): def test_json(self): self.assertDictEqual( diff --git a/tests/slack_sdk/web/test_internal_utils.py b/tests/slack_sdk/web/test_internal_utils.py index fc6574aab..3e44f0c9c 100644 --- a/tests/slack_sdk/web/test_internal_utils.py +++ b/tests/slack_sdk/web/test_internal_utils.py @@ -4,10 +4,9 @@ from pathlib import Path from typing import Dict - from slack_sdk.models.attachments import Attachment from slack_sdk.models.blocks import Block, DividerBlock -from slack_sdk.models.messages.chunk import MarkdownTextChunk, TaskUpdateChunk +from slack_sdk.models.messages.chunk import MarkdownTextChunk, PlanUpdateChunk, TaskUpdateChunk from slack_sdk.web.internal_utils import ( _build_unexpected_body_error_message, _get_url, @@ -59,9 +58,14 @@ def test_can_parse_sequence_of_attachments(self): def test_can_parse_sequence_of_chunks(self): for chunks in [ - [MarkdownTextChunk(text="fiz"), TaskUpdateChunk(id="001", title="baz", status="complete")], # list + [ + MarkdownTextChunk(text="fiz"), + PlanUpdateChunk(title="fuz"), + TaskUpdateChunk(id="001", title="baz", status="complete"), + ], # list ( MarkdownTextChunk(text="fiz"), + PlanUpdateChunk(title="fuz"), TaskUpdateChunk(id="001", title="baz", status="complete"), ), # tuple ]: @@ -87,7 +91,11 @@ def test_can_parse_str_attachments(self): def test_can_parse_str_chunks(self): input = json.dumps( - [MarkdownTextChunk(text="fiz").to_dict(), TaskUpdateChunk(id="001", title="baz", status="complete").to_dict()] + [ + MarkdownTextChunk(text="fiz").to_dict(), + PlanUpdateChunk(title="fuz").to_dict(), + TaskUpdateChunk(id="001", title="baz", status="complete").to_dict(), + ] ) kwargs = {"chunks": input} _parse_web_class_objects(kwargs) From 610de5b0c649f929933546415f35f9a56558e83b Mon Sep 17 00:00:00 2001 From: Michael Brooks Date: Fri, 16 Jan 2026 16:33:33 -0800 Subject: [PATCH 6/8] chore(release): version 3.40.0.dev0 --- docs/reference/index.html | 43 +- docs/reference/models/basic_objects.html | 1 + .../models/blocks/block_elements.html | 112 +++++ docs/reference/models/blocks/blocks.html | 279 +++++++++++ docs/reference/models/blocks/index.html | 391 +++++++++++++++ docs/reference/models/index.html | 1 + docs/reference/models/messages/chunk.html | 447 ++++++++++++++++++ docs/reference/models/messages/index.html | 5 + .../oauth/installation_store/index.html | 16 +- .../oauth/installation_store/models/bot.html | 6 +- .../installation_store/models/index.html | 16 +- .../models/installation.html | 10 +- .../oauth/state_store/sqlalchemy/index.html | 16 +- docs/reference/web/async_chat_stream.html | 70 ++- docs/reference/web/async_client.html | 43 +- docs/reference/web/chat_stream.html | 70 ++- docs/reference/web/client.html | 43 +- docs/reference/web/index.html | 43 +- docs/reference/web/legacy_client.html | 30 +- slack_sdk/version.py | 2 +- 20 files changed, 1557 insertions(+), 87 deletions(-) create mode 100644 docs/reference/models/messages/chunk.html diff --git a/docs/reference/index.html b/docs/reference/index.html index 7cc7723c1..c2f518bcf 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -2755,7 +2755,8 @@

Classes

*, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> SlackResponse: """Appends text to an existing streaming conversation. @@ -2766,8 +2767,10 @@

Classes

"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) @@ -3009,6 +3012,8 @@

Classes

markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> SlackResponse: """Starts a new streaming conversation. @@ -3021,8 +3026,11 @@

Classes

"markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return self.api_call("chat.startStream", json=kwargs) @@ -3034,6 +3042,7 @@

Classes

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. @@ -3046,6 +3055,7 @@

Classes

"markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -3060,6 +3070,7 @@

Classes

thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> ChatStream: """Stream markdown text into a conversation. @@ -3086,6 +3097,8 @@

Classes

recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -3111,6 +3124,7 @@

Classes

thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, ) @@ -10248,7 +10262,7 @@

Methods

Unarchives a channel.

-def chat_appendStream(self, *, channel: str, ts: str, markdown_text: str, **kwargs) ‑> SlackResponse +def chat_appendStream(self,
*,
channel: str,
ts: str,
markdown_text: str | None = None,
chunks: Sequence[Dict | Chunk] | None = None,
**kwargs) ‑> SlackResponse
@@ -10260,7 +10274,8 @@

Methods

*, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> SlackResponse: """Appends text to an existing streaming conversation. @@ -10271,8 +10286,10 @@

Methods

"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)
@@ -10598,7 +10615,7 @@

Methods

https://docs.slack.dev/reference/methods/chat.scheduledMessages.list

-def chat_startStream(self,
*,
channel: str,
thread_ts: str,
markdown_text: str | None = None,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
**kwargs) ‑> SlackResponse
+def chat_startStream(self,
*,
channel: str,
thread_ts: str,
markdown_text: str | None = None,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
chunks: Sequence[Dict | Chunk] | None = None,
task_display_mode: str | None = None,
**kwargs) ‑> SlackResponse
@@ -10613,6 +10630,8 @@

Methods

markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> SlackResponse: """Starts a new streaming conversation. @@ -10625,8 +10644,11 @@

Methods

"markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return self.api_call("chat.startStream", json=kwargs)
@@ -10634,7 +10656,7 @@

Methods

https://docs.slack.dev/reference/methods/chat.startStream

-def chat_stopStream(self,
*,
channel: str,
ts: str,
markdown_text: str | None = None,
blocks: str | Sequence[Dict | Block] | None = None,
metadata: Dict | Metadata | None = None,
**kwargs) ‑> SlackResponse
+def chat_stopStream(self,
*,
channel: str,
ts: str,
markdown_text: str | None = None,
blocks: str | Sequence[Dict | Block] | None = None,
metadata: Dict | Metadata | None = None,
chunks: Sequence[Dict | Chunk] | None = None,
**kwargs) ‑> SlackResponse
@@ -10649,6 +10671,7 @@

Methods

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. @@ -10661,6 +10684,7 @@

Methods

"markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -10671,7 +10695,7 @@

Methods

https://docs.slack.dev/reference/methods/chat.stopStream

-def chat_stream(self,
*,
buffer_size: int = 256,
channel: str,
thread_ts: str,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
**kwargs) ‑> ChatStream
+def chat_stream(self,
*,
buffer_size: int = 256,
channel: str,
thread_ts: str,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
task_display_mode: str | None = None,
**kwargs) ‑> ChatStream
@@ -10686,6 +10710,7 @@

Methods

thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> ChatStream: """Stream markdown text into a conversation. @@ -10712,6 +10737,8 @@

Methods

recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10737,6 +10764,7 @@

Methods

thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, ) @@ -10769,6 +10797,9 @@

Args

streaming to channels.
recipient_user_id
The encoded ID of the user to receive the streaming text. Required when streaming to channels.
+
task_display_mode
+
Specifies how tasks are displayed in the message. A "timeline" displays individual tasks +interleaved with text and "plan" displays all tasks together.
**kwargs
Additional arguments passed to the underlying API calls.
diff --git a/docs/reference/models/basic_objects.html b/docs/reference/models/basic_objects.html index 193200f84..cda8d9c95 100644 --- a/docs/reference/models/basic_objects.html +++ b/docs/reference/models/basic_objects.html @@ -212,6 +212,7 @@

Subclasses

  • AbstractDialogSelector
  • DialogBuilder
  • DialogTextComponent
  • +
  • Chunk
  • Message
  • ContentItemEntityFields
  • EntityActionButton
  • diff --git a/docs/reference/models/blocks/block_elements.html b/docs/reference/models/blocks/block_elements.html index 375ee07ce..c7f1347fe 100644 --- a/docs/reference/models/blocks/block_elements.html +++ b/docs/reference/models/blocks/block_elements.html @@ -130,6 +130,7 @@

    Subclasses

  • ImageElement
  • InteractiveElement
  • RichTextElement
  • +
  • UrlSourceElement
  • Class variables

    @@ -4663,6 +4664,110 @@

    Inherited members

    +
    +class UrlSourceElement +(*, url: str, text: str, icon_url: str | None = None, **others: Dict) +
    +
    +
    + +Expand source code + +
    class UrlSourceElement(BlockElement):
    +    type = "url"
    +
    +    @property
    +    def attributes(self) -> Set[str]:  # type: ignore[override]
    +        return super().attributes.union(
    +            {
    +                "url",
    +                "text",
    +                "icon_url",
    +            }
    +        )
    +
    +    def __init__(
    +        self,
    +        *,
    +        url: str,
    +        text: str,
    +        icon_url: Optional[str] = None,
    +        **others: Dict,
    +    ):
    +        """
    +        A URL source element to reference in a task card block.
    +        https://docs.slack.dev/reference/block-kit/block-elements/url-source-element
    +
    +        Args:
    +            url (required): The URL type source.
    +            text (required): Display text for the URL.
    +            icon_url: Optional icon URL to display with the source.
    +        """
    +        super().__init__(type=self.type)
    +        show_unknown_key_warning(self, others)
    +        self.url = url
    +        self.text = text
    +        self.icon_url = icon_url
    +
    +

    Block Elements are things that exists inside of your Blocks. +https://docs.slack.dev/reference/block-kit/block-elements/

    +

    A URL source element to reference in a task card block. +https://docs.slack.dev/reference/block-kit/block-elements/url-source-element

    +

    Args

    +
    +
    url : required
    +
    The URL type source.
    +
    text : required
    +
    Display text for the URL.
    +
    icon_url
    +
    Optional icon URL to display with the source.
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var type
    +
    +

    The type of the None singleton.

    +
    +
    +

    Instance variables

    +
    +
    prop attributes : Set[str]
    +
    +
    + +Expand source code + +
    @property
    +def attributes(self) -> Set[str]:  # type: ignore[override]
    +    return super().attributes.union(
    +        {
    +            "url",
    +            "text",
    +            "icon_url",
    +        }
    +    )
    +
    +

    Build an unordered collection of unique elements.

    +
    +
    +

    Inherited members

    + +
    class UserMultiSelectElement (*,
    action_id: str | None = None,
    placeholder: str | dict | TextObject | None = None,
    initial_users: Sequence[str] | None = None,
    confirm: dict | ConfirmObject | None = None,
    max_selected_items: int | None = None,
    focus_on_load: bool | None = None,
    **others: dict)
    @@ -5319,6 +5424,13 @@

  • +

    UrlSourceElement

    + +
  • +
  • UserMultiSelectElement

    • attributes
    • diff --git a/docs/reference/models/blocks/blocks.html b/docs/reference/models/blocks/blocks.html index 722d12164..934dd977e 100644 --- a/docs/reference/models/blocks/blocks.html +++ b/docs/reference/models/blocks/blocks.html @@ -238,6 +238,10 @@

      Inherited members

      return RichTextBlock(**block) elif type == TableBlock.type: return TableBlock(**block) + elif type == TaskCardBlock.type: + return TaskCardBlock(**block) + elif type == PlanBlock.type: + return PlanBlock(**block) else: cls.logger.warning(f"Unknown block detected and skipped ({block})") return None @@ -269,9 +273,11 @@

      Subclasses

    • ImageBlock
    • InputBlock
    • MarkdownBlock
    • +
    • PlanBlock
    • RichTextBlock
    • SectionBlock
    • TableBlock
    • +
    • TaskCardBlock
    • VideoBlock

    Class variables

    @@ -1321,6 +1327,124 @@

    Inherited members

  • +
    +class PlanBlock +(*,
    plan_id: str,
    title: str,
    tasks: Sequence[Dict | TaskCardBlock] | None = None,
    block_id: str | None = None,
    **others: dict)
    +
    +
    +
    + +Expand source code + +
    class PlanBlock(Block):
    +    type = "plan"
    +
    +    @property
    +    def attributes(self) -> Set[str]:  # type: ignore[override]
    +        return super().attributes.union(
    +            {
    +                "plan_id",
    +                "title",
    +                "tasks",
    +            }
    +        )
    +
    +    def __init__(
    +        self,
    +        *,
    +        plan_id: str,
    +        title: str,
    +        tasks: Optional[Sequence[Union[Dict, TaskCardBlock]]] = None,
    +        block_id: Optional[str] = None,
    +        **others: dict,
    +    ):
    +        """A collection of related tasks.
    +        https://docs.slack.dev/reference/block-kit/blocks/plan-block/
    +
    +        Args:
    +            block_id: A string acting as a unique identifier for a block. If not specified, one will be generated.
    +                Maximum length for this field is 255 characters.
    +                block_id should be unique for each message and each iteration of a message.
    +                If a message is updated, use a new block_id.
    +            plan_id (required): ID for the plan (May be removed / made optional, feel free to pass in a random UUID
    +                for now)
    +            title (required): Title of the plan in plain text
    +            tasks: Details of the task in the form of a single "rich_text" entity.
    +        """
    +        super().__init__(type=self.type, block_id=block_id)
    +        show_unknown_key_warning(self, others)
    +
    +        self.plan_id = plan_id
    +        self.title = title
    +        self.tasks = tasks
    +
    +

    Blocks are a series of components that can be combined +to create visually rich and compellingly interactive messages. +https://docs.slack.dev/reference/block-kit/blocks

    +

    A collection of related tasks. +https://docs.slack.dev/reference/block-kit/blocks/plan-block/

    +

    Args

    +
    +
    block_id
    +
    A string acting as a unique identifier for a block. If not specified, one will be generated. +Maximum length for this field is 255 characters. +block_id should be unique for each message and each iteration of a message. +If a message is updated, use a new block_id.
    +
    plan_id : required
    +
    ID for the plan (May be removed / made optional, feel free to pass in a random UUID +for now)
    +
    title : required
    +
    Title of the plan in plain text
    +
    tasks
    +
    Details of the task in the form of a single "rich_text" entity.
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var type
    +
    +

    The type of the None singleton.

    +
    +
    +

    Instance variables

    +
    +
    prop attributes : Set[str]
    +
    +
    + +Expand source code + +
    @property
    +def attributes(self) -> Set[str]:  # type: ignore[override]
    +    return super().attributes.union(
    +        {
    +            "plan_id",
    +            "title",
    +            "tasks",
    +        }
    +    )
    +
    +

    Build an unordered collection of unique elements.

    +
    +
    +

    Inherited members

    + +
    class RichTextBlock (*,
    elements: Sequence[dict | RichTextElement],
    block_id: str | None = None,
    **others: dict)
    @@ -1700,6 +1824,147 @@

    Inherited members

    +
    +class TaskCardBlock +(*,
    task_id: str,
    title: str,
    details: RichTextBlock | dict | None = None,
    output: RichTextBlock | dict | None = None,
    sources: Sequence[UrlSourceElement | dict] | None = None,
    status: str,
    block_id: str | None = None,
    **others: dict)
    +
    +
    +
    + +Expand source code + +
    class TaskCardBlock(Block):
    +    type = "task_card"
    +
    +    @property
    +    def attributes(self) -> Set[str]:  # type: ignore[override]
    +        return super().attributes.union(
    +            {
    +                "task_id",
    +                "title",
    +                "details",
    +                "output",
    +                "sources",
    +                "status",
    +            }
    +        )
    +
    +    def __init__(
    +        self,
    +        *,
    +        task_id: str,
    +        title: str,
    +        details: Optional[Union[RichTextBlock, dict]] = None,
    +        output: Optional[Union[RichTextBlock, dict]] = None,
    +        sources: Optional[Sequence[Union[UrlSourceElement, dict]]] = None,
    +        status: str,  # pending, in_progress, complete, error
    +        block_id: Optional[str] = None,
    +        **others: dict,
    +    ):
    +        """A discrete action or tool call.
    +        https://docs.slack.dev/reference/block-kit/blocks/task-card-block/
    +
    +        Args:
    +            block_id: A string acting as a unique identifier for a block. If not specified, one will be generated.
    +                Maximum length for this field is 255 characters.
    +                block_id should be unique for each message and each iteration of a message.
    +                If a message is updated, use a new block_id.
    +            task_id (required): ID for the task
    +            title (required): Title of the task in plain text
    +            details: Details of the task in the form of a single "rich_text" entity.
    +            output: Output of the task in the form of a single "rich_text" entity.
    +            sources: List of sources used to generate a response
    +            status: The state of a task. Either "pending" or "in_progress" or "complete" or "error".
    +        """
    +        super().__init__(type=self.type, block_id=block_id)
    +        show_unknown_key_warning(self, others)
    +
    +        self.task_id = task_id
    +        self.title = title
    +        self.details = details
    +        self.output = output
    +        self.sources = sources
    +        self.status = status
    +
    +    @JsonValidator("status must be an expected value (pending, in_progress, complete, or error)")
    +    def _validate_rows(self):
    +        return self.status in ["pending", "in_progress", "complete", "error"]
    +
    +

    Blocks are a series of components that can be combined +to create visually rich and compellingly interactive messages. +https://docs.slack.dev/reference/block-kit/blocks

    +

    A discrete action or tool call. +https://docs.slack.dev/reference/block-kit/blocks/task-card-block/

    +

    Args

    +
    +
    block_id
    +
    A string acting as a unique identifier for a block. If not specified, one will be generated. +Maximum length for this field is 255 characters. +block_id should be unique for each message and each iteration of a message. +If a message is updated, use a new block_id.
    +
    task_id : required
    +
    ID for the task
    +
    title : required
    +
    Title of the task in plain text
    +
    details
    +
    Details of the task in the form of a single "rich_text" entity.
    +
    output
    +
    Output of the task in the form of a single "rich_text" entity.
    +
    sources
    +
    List of sources used to generate a response
    +
    status
    +
    The state of a task. Either "pending" or "in_progress" or "complete" or "error".
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var type
    +
    +

    The type of the None singleton.

    +
    +
    +

    Instance variables

    +
    +
    prop attributes : Set[str]
    +
    +
    + +Expand source code + +
    @property
    +def attributes(self) -> Set[str]:  # type: ignore[override]
    +    return super().attributes.union(
    +        {
    +            "task_id",
    +            "title",
    +            "details",
    +            "output",
    +            "sources",
    +            "status",
    +        }
    +    )
    +
    +

    Build an unordered collection of unique elements.

    +
    +
    +

    Inherited members

    + +
    class VideoBlock (*,
    block_id: str | None = None,
    alt_text: str | None = None,
    video_url: str | None = None,
    thumbnail_url: str | None = None,
    title: str | dict | PlainTextObject | None = None,
    title_url: str | None = None,
    description: str | dict | PlainTextObject | None = None,
    provider_icon_url: str | None = None,
    provider_name: str | None = None,
    author_name: str | None = None,
    **others: dict)
    @@ -2008,6 +2273,13 @@

    PlanBlock

    + + +
  • RichTextBlock

    Class variables

    @@ -5345,6 +5352,124 @@

    Inherited members

  • +
    +class PlanBlock +(*,
    plan_id: str,
    title: str,
    tasks: Sequence[Dict | TaskCardBlock] | None = None,
    block_id: str | None = None,
    **others: dict)
    +
    +
    +
    + +Expand source code + +
    class PlanBlock(Block):
    +    type = "plan"
    +
    +    @property
    +    def attributes(self) -> Set[str]:  # type: ignore[override]
    +        return super().attributes.union(
    +            {
    +                "plan_id",
    +                "title",
    +                "tasks",
    +            }
    +        )
    +
    +    def __init__(
    +        self,
    +        *,
    +        plan_id: str,
    +        title: str,
    +        tasks: Optional[Sequence[Union[Dict, TaskCardBlock]]] = None,
    +        block_id: Optional[str] = None,
    +        **others: dict,
    +    ):
    +        """A collection of related tasks.
    +        https://docs.slack.dev/reference/block-kit/blocks/plan-block/
    +
    +        Args:
    +            block_id: A string acting as a unique identifier for a block. If not specified, one will be generated.
    +                Maximum length for this field is 255 characters.
    +                block_id should be unique for each message and each iteration of a message.
    +                If a message is updated, use a new block_id.
    +            plan_id (required): ID for the plan (May be removed / made optional, feel free to pass in a random UUID
    +                for now)
    +            title (required): Title of the plan in plain text
    +            tasks: Details of the task in the form of a single "rich_text" entity.
    +        """
    +        super().__init__(type=self.type, block_id=block_id)
    +        show_unknown_key_warning(self, others)
    +
    +        self.plan_id = plan_id
    +        self.title = title
    +        self.tasks = tasks
    +
    +

    Blocks are a series of components that can be combined +to create visually rich and compellingly interactive messages. +https://docs.slack.dev/reference/block-kit/blocks

    +

    A collection of related tasks. +https://docs.slack.dev/reference/block-kit/blocks/plan-block/

    +

    Args

    +
    +
    block_id
    +
    A string acting as a unique identifier for a block. If not specified, one will be generated. +Maximum length for this field is 255 characters. +block_id should be unique for each message and each iteration of a message. +If a message is updated, use a new block_id.
    +
    plan_id : required
    +
    ID for the plan (May be removed / made optional, feel free to pass in a random UUID +for now)
    +
    title : required
    +
    Title of the plan in plain text
    +
    tasks
    +
    Details of the task in the form of a single "rich_text" entity.
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var type
    +
    +

    The type of the None singleton.

    +
    +
    +

    Instance variables

    +
    +
    prop attributes : Set[str]
    +
    +
    + +Expand source code + +
    @property
    +def attributes(self) -> Set[str]:  # type: ignore[override]
    +    return super().attributes.union(
    +        {
    +            "plan_id",
    +            "title",
    +            "tasks",
    +        }
    +    )
    +
    +

    Build an unordered collection of unique elements.

    +
    +
    +

    Inherited members

    + +
    class RadioButtonsElement (*,
    action_id: str | None = None,
    options: Sequence[dict | Option] | None = None,
    initial_option: dict | Option | None = None,
    confirm: dict | ConfirmObject | None = None,
    focus_on_load: bool | None = None,
    **others: dict)
    @@ -7196,6 +7321,147 @@

    Inherited members

    +
    +class TaskCardBlock +(*,
    task_id: str,
    title: str,
    details: RichTextBlock | dict | None = None,
    output: RichTextBlock | dict | None = None,
    sources: Sequence[UrlSourceElement | dict] | None = None,
    status: str,
    block_id: str | None = None,
    **others: dict)
    +
    +
    +
    + +Expand source code + +
    class TaskCardBlock(Block):
    +    type = "task_card"
    +
    +    @property
    +    def attributes(self) -> Set[str]:  # type: ignore[override]
    +        return super().attributes.union(
    +            {
    +                "task_id",
    +                "title",
    +                "details",
    +                "output",
    +                "sources",
    +                "status",
    +            }
    +        )
    +
    +    def __init__(
    +        self,
    +        *,
    +        task_id: str,
    +        title: str,
    +        details: Optional[Union[RichTextBlock, dict]] = None,
    +        output: Optional[Union[RichTextBlock, dict]] = None,
    +        sources: Optional[Sequence[Union[UrlSourceElement, dict]]] = None,
    +        status: str,  # pending, in_progress, complete, error
    +        block_id: Optional[str] = None,
    +        **others: dict,
    +    ):
    +        """A discrete action or tool call.
    +        https://docs.slack.dev/reference/block-kit/blocks/task-card-block/
    +
    +        Args:
    +            block_id: A string acting as a unique identifier for a block. If not specified, one will be generated.
    +                Maximum length for this field is 255 characters.
    +                block_id should be unique for each message and each iteration of a message.
    +                If a message is updated, use a new block_id.
    +            task_id (required): ID for the task
    +            title (required): Title of the task in plain text
    +            details: Details of the task in the form of a single "rich_text" entity.
    +            output: Output of the task in the form of a single "rich_text" entity.
    +            sources: List of sources used to generate a response
    +            status: The state of a task. Either "pending" or "in_progress" or "complete" or "error".
    +        """
    +        super().__init__(type=self.type, block_id=block_id)
    +        show_unknown_key_warning(self, others)
    +
    +        self.task_id = task_id
    +        self.title = title
    +        self.details = details
    +        self.output = output
    +        self.sources = sources
    +        self.status = status
    +
    +    @JsonValidator("status must be an expected value (pending, in_progress, complete, or error)")
    +    def _validate_rows(self):
    +        return self.status in ["pending", "in_progress", "complete", "error"]
    +
    +

    Blocks are a series of components that can be combined +to create visually rich and compellingly interactive messages. +https://docs.slack.dev/reference/block-kit/blocks

    +

    A discrete action or tool call. +https://docs.slack.dev/reference/block-kit/blocks/task-card-block/

    +

    Args

    +
    +
    block_id
    +
    A string acting as a unique identifier for a block. If not specified, one will be generated. +Maximum length for this field is 255 characters. +block_id should be unique for each message and each iteration of a message. +If a message is updated, use a new block_id.
    +
    task_id : required
    +
    ID for the task
    +
    title : required
    +
    Title of the task in plain text
    +
    details
    +
    Details of the task in the form of a single "rich_text" entity.
    +
    output
    +
    Output of the task in the form of a single "rich_text" entity.
    +
    sources
    +
    List of sources used to generate a response
    +
    status
    +
    The state of a task. Either "pending" or "in_progress" or "complete" or "error".
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var type
    +
    +

    The type of the None singleton.

    +
    +
    +

    Instance variables

    +
    +
    prop attributes : Set[str]
    +
    +
    + +Expand source code + +
    @property
    +def attributes(self) -> Set[str]:  # type: ignore[override]
    +    return super().attributes.union(
    +        {
    +            "task_id",
    +            "title",
    +            "details",
    +            "output",
    +            "sources",
    +            "status",
    +        }
    +    )
    +
    +

    Build an unordered collection of unique elements.

    +
    +
    +

    Inherited members

    + +
    class TextObject (text: str,
    type: str | None = None,
    subtype: str | None = None,
    emoji: bool | None = None,
    **kwargs)
    @@ -7595,6 +7861,110 @@

    Inherited members

    +
    +class UrlSourceElement +(*, url: str, text: str, icon_url: str | None = None, **others: Dict) +
    +
    +
    + +Expand source code + +
    class UrlSourceElement(BlockElement):
    +    type = "url"
    +
    +    @property
    +    def attributes(self) -> Set[str]:  # type: ignore[override]
    +        return super().attributes.union(
    +            {
    +                "url",
    +                "text",
    +                "icon_url",
    +            }
    +        )
    +
    +    def __init__(
    +        self,
    +        *,
    +        url: str,
    +        text: str,
    +        icon_url: Optional[str] = None,
    +        **others: Dict,
    +    ):
    +        """
    +        A URL source element to reference in a task card block.
    +        https://docs.slack.dev/reference/block-kit/block-elements/url-source-element
    +
    +        Args:
    +            url (required): The URL type source.
    +            text (required): Display text for the URL.
    +            icon_url: Optional icon URL to display with the source.
    +        """
    +        super().__init__(type=self.type)
    +        show_unknown_key_warning(self, others)
    +        self.url = url
    +        self.text = text
    +        self.icon_url = icon_url
    +
    +

    Block Elements are things that exists inside of your Blocks. +https://docs.slack.dev/reference/block-kit/block-elements/

    +

    A URL source element to reference in a task card block. +https://docs.slack.dev/reference/block-kit/block-elements/url-source-element

    +

    Args

    +
    +
    url : required
    +
    The URL type source.
    +
    text : required
    +
    Display text for the URL.
    +
    icon_url
    +
    Optional icon URL to display with the source.
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var type
    +
    +

    The type of the None singleton.

    +
    +
    +

    Instance variables

    +
    +
    prop attributes : Set[str]
    +
    +
    + +Expand source code + +
    @property
    +def attributes(self) -> Set[str]:  # type: ignore[override]
    +    return super().attributes.union(
    +        {
    +            "url",
    +            "text",
    +            "icon_url",
    +        }
    +    )
    +
    +

    Build an unordered collection of unique elements.

    +
    +
    +

    Inherited members

    + +
    class UserMultiSelectElement (*,
    action_id: str | None = None,
    placeholder: str | dict | TextObject | None = None,
    initial_users: Sequence[str] | None = None,
    confirm: dict | ConfirmObject | None = None,
    max_selected_items: int | None = None,
    focus_on_load: bool | None = None,
    **others: dict)
    @@ -8389,6 +8759,13 @@

    PlanBlock

    + + +
  • RadioButtonsElement

    • attributes
    • @@ -8509,6 +8886,13 @@

      TaskCardBlock

      + + +
    • TextObject

      • attributes
      • @@ -8532,6 +8916,13 @@

        UrlSourceElement

        + + +
      • UserMultiSelectElement

        • attributes
        • diff --git a/docs/reference/models/index.html b/docs/reference/models/index.html index d3670bfde..d18523ae7 100644 --- a/docs/reference/models/index.html +++ b/docs/reference/models/index.html @@ -316,6 +316,7 @@

          Subclasses

        • AbstractDialogSelector
        • DialogBuilder
        • DialogTextComponent
        • +
        • Chunk
        • Message
        • ContentItemEntityFields
        • EntityActionButton
        • diff --git a/docs/reference/models/messages/chunk.html b/docs/reference/models/messages/chunk.html new file mode 100644 index 000000000..722f018c9 --- /dev/null +++ b/docs/reference/models/messages/chunk.html @@ -0,0 +1,447 @@ + + + + + + +slack_sdk.models.messages.chunk API documentation + + + + + + + + + + + +
          +
          +
          +

          Module slack_sdk.models.messages.chunk

          +
          +
          +
          +
          +
          +
          +
          +
          +
          +
          +

          Classes

          +
          +
          +class Chunk +(*, type: str | None = None) +
          +
          +
          + +Expand source code + +
          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 == PlanUpdateChunk.type:
          +                    return PlanUpdateChunk(**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
          +
          + +

          Ancestors

          + +

          Subclasses

          + +

          Class variables

          +
          +
          var attributes
          +
          +

          The type of the None singleton.

          +
          +
          var logger
          +
          +

          The type of the None singleton.

          +
          +
          +

          Static methods

          +
          +
          +def parse(chunk: Dict | ForwardRef('Chunk')) ‑> Chunk | None +
          +
          +
          +
          +
          +

          Inherited members

          + +
          +
          +class MarkdownTextChunk +(*, text: str, **others: Dict) +
          +
          +
          + +Expand source code + +
          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
          +
          + +

          Ancestors

          + +

          Class variables

          +
          +
          var type
          +
          +

          The type of the None singleton.

          +
          +
          +

          Instance variables

          +
          +
          prop attributes : Set[str]
          +
          +
          + +Expand source code + +
          @property
          +def attributes(self) -> Set[str]:  # type: ignore[override]
          +    return super().attributes.union({"text"})
          +
          +

          Build an unordered collection of unique elements.

          +
          +
          +

          Inherited members

          + +
          +
          +class PlanUpdateChunk +(*, title: str, **others: Dict) +
          +
          +
          + +Expand source code + +
          class PlanUpdateChunk(Chunk):
          +    type = "plan_update"
          +
          +    @property
          +    def attributes(self) -> Set[str]:  # type: ignore[override]
          +        return super().attributes.union({"title"})
          +
          +    def __init__(
          +        self,
          +        *,
          +        title: str,
          +        **others: Dict,
          +    ):
          +        """An updated title of plans for task and tool calls.
          +
          +        https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming
          +        """
          +        super().__init__(type=self.type)
          +        show_unknown_key_warning(self, others)
          +
          +        self.title = title
          +
          + +

          Ancestors

          + +

          Class variables

          +
          +
          var type
          +
          +

          The type of the None singleton.

          +
          +
          +

          Instance variables

          +
          +
          prop attributes : Set[str]
          +
          +
          + +Expand source code + +
          @property
          +def attributes(self) -> Set[str]:  # type: ignore[override]
          +    return super().attributes.union({"title"})
          +
          +

          Build an unordered collection of unique elements.

          +
          +
          +

          Inherited members

          + +
          +
          +class TaskUpdateChunk +(*,
          id: str,
          title: str,
          status: str,
          details: str | None = None,
          output: str | None = None,
          sources: Sequence[Dict | UrlSourceElement] | None = None,
          **others: Dict)
          +
          +
          +
          + +Expand source code + +
          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"
          +        details: Optional[str] = None,
          +        output: Optional[str] = None,
          +        sources: Optional[Sequence[Union[Dict, UrlSourceElement]]] = 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
          +        self.sources = sources
          +
          + +

          Ancestors

          + +

          Class variables

          +
          +
          var type
          +
          +

          The type of the None singleton.

          +
          +
          +

          Instance variables

          +
          +
          prop attributes : Set[str]
          +
          +
          + +Expand source code + +
          @property
          +def attributes(self) -> Set[str]:  # type: ignore[override]
          +    return super().attributes.union(
          +        {
          +            "id",
          +            "title",
          +            "status",
          +            "details",
          +            "output",
          +            "sources",
          +        }
          +    )
          +
          +

          Build an unordered collection of unique elements.

          +
          +
          +

          Inherited members

          + +
          +
          +
          +
          + +
          + + + diff --git a/docs/reference/models/messages/index.html b/docs/reference/models/messages/index.html index 5d10ced1c..3139098be 100644 --- a/docs/reference/models/messages/index.html +++ b/docs/reference/models/messages/index.html @@ -40,6 +40,10 @@

          Module slack_sdk.models.messages

          Sub-modules

          +
          slack_sdk.models.messages.chunk
          +
          +
          +
          slack_sdk.models.messages.message
          @@ -262,6 +266,7 @@

          Class variables

        • Sub-modules

        • diff --git a/docs/reference/oauth/installation_store/index.html b/docs/reference/oauth/installation_store/index.html index 4f90fb1c5..8d95802d0 100644 --- a/docs/reference/oauth/installation_store/index.html +++ b/docs/reference/oauth/installation_store/index.html @@ -193,10 +193,12 @@

          Classes

          "bot_scopes": ",".join(self.bot_scopes) if self.bot_scopes else None, "bot_refresh_token": self.bot_refresh_token, "bot_token_expires_at": ( - datetime.utcfromtimestamp(self.bot_token_expires_at) if self.bot_token_expires_at is not None else None + datetime.fromtimestamp(self.bot_token_expires_at, tz=timezone.utc) + if self.bot_token_expires_at is not None + else None ), "is_enterprise_install": self.is_enterprise_install, - "installed_at": datetime.utcfromtimestamp(self.installed_at), + "installed_at": datetime.fromtimestamp(self.installed_at, tz=timezone.utc), } def to_dict_for_copying(self) -> Dict[str, Any]: @@ -850,14 +852,18 @@

          Inherited members

          "bot_scopes": ",".join(self.bot_scopes) if self.bot_scopes else None, "bot_refresh_token": self.bot_refresh_token, "bot_token_expires_at": ( - datetime.utcfromtimestamp(self.bot_token_expires_at) if self.bot_token_expires_at is not None else None + datetime.fromtimestamp(self.bot_token_expires_at, tz=timezone.utc) + if self.bot_token_expires_at is not None + else None ), "user_id": self.user_id, "user_token": self.user_token, "user_scopes": ",".join(self.user_scopes) if self.user_scopes else None, "user_refresh_token": self.user_refresh_token, "user_token_expires_at": ( - datetime.utcfromtimestamp(self.user_token_expires_at) if self.user_token_expires_at is not None else None + datetime.fromtimestamp(self.user_token_expires_at, tz=timezone.utc) + if self.user_token_expires_at is not None + else None ), "incoming_webhook_url": self.incoming_webhook_url, "incoming_webhook_channel": self.incoming_webhook_channel, @@ -865,7 +871,7 @@

          Inherited members

          "incoming_webhook_configuration_url": self.incoming_webhook_configuration_url, "is_enterprise_install": self.is_enterprise_install, "token_type": self.token_type, - "installed_at": datetime.utcfromtimestamp(self.installed_at), + "installed_at": datetime.fromtimestamp(self.installed_at, tz=timezone.utc), } def to_dict_for_copying(self) -> Dict[str, Any]: diff --git a/docs/reference/oauth/installation_store/models/bot.html b/docs/reference/oauth/installation_store/models/bot.html index bb6182df2..b27abfc7d 100644 --- a/docs/reference/oauth/installation_store/models/bot.html +++ b/docs/reference/oauth/installation_store/models/bot.html @@ -150,10 +150,12 @@

          Classes

          "bot_scopes": ",".join(self.bot_scopes) if self.bot_scopes else None, "bot_refresh_token": self.bot_refresh_token, "bot_token_expires_at": ( - datetime.utcfromtimestamp(self.bot_token_expires_at) if self.bot_token_expires_at is not None else None + datetime.fromtimestamp(self.bot_token_expires_at, tz=timezone.utc) + if self.bot_token_expires_at is not None + else None ), "is_enterprise_install": self.is_enterprise_install, - "installed_at": datetime.utcfromtimestamp(self.installed_at), + "installed_at": datetime.fromtimestamp(self.installed_at, tz=timezone.utc), } def to_dict_for_copying(self) -> Dict[str, Any]: diff --git a/docs/reference/oauth/installation_store/models/index.html b/docs/reference/oauth/installation_store/models/index.html index b96d16179..69e08affe 100644 --- a/docs/reference/oauth/installation_store/models/index.html +++ b/docs/reference/oauth/installation_store/models/index.html @@ -161,10 +161,12 @@

          Classes

          "bot_scopes": ",".join(self.bot_scopes) if self.bot_scopes else None, "bot_refresh_token": self.bot_refresh_token, "bot_token_expires_at": ( - datetime.utcfromtimestamp(self.bot_token_expires_at) if self.bot_token_expires_at is not None else None + datetime.fromtimestamp(self.bot_token_expires_at, tz=timezone.utc) + if self.bot_token_expires_at is not None + else None ), "is_enterprise_install": self.is_enterprise_install, - "installed_at": datetime.utcfromtimestamp(self.installed_at), + "installed_at": datetime.fromtimestamp(self.installed_at, tz=timezone.utc), } def to_dict_for_copying(self) -> Dict[str, Any]: @@ -469,14 +471,18 @@

          Methods

          "bot_scopes": ",".join(self.bot_scopes) if self.bot_scopes else None, "bot_refresh_token": self.bot_refresh_token, "bot_token_expires_at": ( - datetime.utcfromtimestamp(self.bot_token_expires_at) if self.bot_token_expires_at is not None else None + datetime.fromtimestamp(self.bot_token_expires_at, tz=timezone.utc) + if self.bot_token_expires_at is not None + else None ), "user_id": self.user_id, "user_token": self.user_token, "user_scopes": ",".join(self.user_scopes) if self.user_scopes else None, "user_refresh_token": self.user_refresh_token, "user_token_expires_at": ( - datetime.utcfromtimestamp(self.user_token_expires_at) if self.user_token_expires_at is not None else None + datetime.fromtimestamp(self.user_token_expires_at, tz=timezone.utc) + if self.user_token_expires_at is not None + else None ), "incoming_webhook_url": self.incoming_webhook_url, "incoming_webhook_channel": self.incoming_webhook_channel, @@ -484,7 +490,7 @@

          Methods

          "incoming_webhook_configuration_url": self.incoming_webhook_configuration_url, "is_enterprise_install": self.is_enterprise_install, "token_type": self.token_type, - "installed_at": datetime.utcfromtimestamp(self.installed_at), + "installed_at": datetime.fromtimestamp(self.installed_at, tz=timezone.utc), } def to_dict_for_copying(self) -> Dict[str, Any]: diff --git a/docs/reference/oauth/installation_store/models/installation.html b/docs/reference/oauth/installation_store/models/installation.html index c0de92807..3f47d901a 100644 --- a/docs/reference/oauth/installation_store/models/installation.html +++ b/docs/reference/oauth/installation_store/models/installation.html @@ -222,14 +222,18 @@

          Classes

          "bot_scopes": ",".join(self.bot_scopes) if self.bot_scopes else None, "bot_refresh_token": self.bot_refresh_token, "bot_token_expires_at": ( - datetime.utcfromtimestamp(self.bot_token_expires_at) if self.bot_token_expires_at is not None else None + datetime.fromtimestamp(self.bot_token_expires_at, tz=timezone.utc) + if self.bot_token_expires_at is not None + else None ), "user_id": self.user_id, "user_token": self.user_token, "user_scopes": ",".join(self.user_scopes) if self.user_scopes else None, "user_refresh_token": self.user_refresh_token, "user_token_expires_at": ( - datetime.utcfromtimestamp(self.user_token_expires_at) if self.user_token_expires_at is not None else None + datetime.fromtimestamp(self.user_token_expires_at, tz=timezone.utc) + if self.user_token_expires_at is not None + else None ), "incoming_webhook_url": self.incoming_webhook_url, "incoming_webhook_channel": self.incoming_webhook_channel, @@ -237,7 +241,7 @@

          Classes

          "incoming_webhook_configuration_url": self.incoming_webhook_configuration_url, "is_enterprise_install": self.is_enterprise_install, "token_type": self.token_type, - "installed_at": datetime.utcfromtimestamp(self.installed_at), + "installed_at": datetime.fromtimestamp(self.installed_at, tz=timezone.utc), } def to_dict_for_copying(self) -> Dict[str, Any]: diff --git a/docs/reference/oauth/state_store/sqlalchemy/index.html b/docs/reference/oauth/state_store/sqlalchemy/index.html index 29fe36884..a35fa3171 100644 --- a/docs/reference/oauth/state_store/sqlalchemy/index.html +++ b/docs/reference/oauth/state_store/sqlalchemy/index.html @@ -99,7 +99,7 @@

          Classes

          async def async_issue(self, *args, **kwargs) -> str: state: str = str(uuid4()) - now = datetime.utcfromtimestamp(time.time() + self.expiration_seconds) + now = datetime.fromtimestamp(time.time() + self.expiration_seconds, tz=timezone.utc) async with self.engine.begin() as conn: await conn.execute( self.oauth_states.insert(), @@ -111,7 +111,7 @@

          Classes

          try: async with self.engine.begin() as conn: c = self.oauth_states.c - query = self.oauth_states.select().where(and_(c.state == state, c.expire_at > datetime.utcnow())) + query = self.oauth_states.select().where(and_(c.state == state, c.expire_at > datetime.now(tz=timezone.utc))) result = await conn.execute(query) for row in result.mappings(): self.logger.debug(f"consume's query result: {row}") @@ -191,7 +191,7 @@

          Methods

          try: async with self.engine.begin() as conn: c = self.oauth_states.c - query = self.oauth_states.select().where(and_(c.state == state, c.expire_at > datetime.utcnow())) + query = self.oauth_states.select().where(and_(c.state == state, c.expire_at > datetime.now(tz=timezone.utc))) result = await conn.execute(query) for row in result.mappings(): self.logger.debug(f"consume's query result: {row}") @@ -215,7 +215,7 @@

          Methods

          async def async_issue(self, *args, **kwargs) -> str:
               state: str = str(uuid4())
          -    now = datetime.utcfromtimestamp(time.time() + self.expiration_seconds)
          +    now = datetime.fromtimestamp(time.time() + self.expiration_seconds, tz=timezone.utc)
               async with self.engine.begin() as conn:
                   await conn.execute(
                       self.oauth_states.insert(),
          @@ -293,7 +293,7 @@ 

          Methods

          def issue(self, *args, **kwargs) -> str: state: str = str(uuid4()) - now = datetime.utcfromtimestamp(time.time() + self.expiration_seconds) + now = datetime.fromtimestamp(time.time() + self.expiration_seconds, tz=timezone.utc) with self.engine.begin() as conn: conn.execute( self.oauth_states.insert(), @@ -305,7 +305,7 @@

          Methods

          try: with self.engine.begin() as conn: c = self.oauth_states.c - query = self.oauth_states.select().where(and_(c.state == state, c.expire_at > datetime.utcnow())) + query = self.oauth_states.select().where(and_(c.state == state, c.expire_at > datetime.now(tz=timezone.utc))) result = conn.execute(query) for row in result.mappings(): self.logger.debug(f"consume's query result: {row}") @@ -385,7 +385,7 @@

          Methods

          try: with self.engine.begin() as conn: c = self.oauth_states.c - query = self.oauth_states.select().where(and_(c.state == state, c.expire_at > datetime.utcnow())) + query = self.oauth_states.select().where(and_(c.state == state, c.expire_at > datetime.now(tz=timezone.utc))) result = conn.execute(query) for row in result.mappings(): self.logger.debug(f"consume's query result: {row}") @@ -422,7 +422,7 @@

          Methods

          def issue(self, *args, **kwargs) -> str:
               state: str = str(uuid4())
          -    now = datetime.utcfromtimestamp(time.time() + self.expiration_seconds)
          +    now = datetime.fromtimestamp(time.time() + self.expiration_seconds, tz=timezone.utc)
               with self.engine.begin() as conn:
                   conn.execute(
                       self.oauth_states.insert(),
          diff --git a/docs/reference/web/async_chat_stream.html b/docs/reference/web/async_chat_stream.html
          index ca7bf2506..994f7df4e 100644
          --- a/docs/reference/web/async_chat_stream.html
          +++ b/docs/reference/web/async_chat_stream.html
          @@ -48,7 +48,7 @@ 

          Classes

          class AsyncChatStream -(client: AsyncWebClient,
          *,
          channel: str,
          logger: logging.Logger,
          thread_ts: str,
          buffer_size: int,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs)
          +(client: AsyncWebClient,
          *,
          channel: str,
          logger: logging.Logger,
          thread_ts: str,
          buffer_size: int,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          task_display_mode: str | None = None,
          **kwargs)
          @@ -72,6 +72,7 @@

          Classes

          buffer_size: int, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ): """Initialize a new ChatStream instance. @@ -87,6 +88,8 @@

          Classes

          recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits. **kwargs: Additional arguments passed to the underlying API calls. @@ -99,6 +102,7 @@

          Classes

          "thread_ts": thread_ts, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "task_display_mode": task_display_mode, **kwargs, } self._buffer = "" @@ -109,7 +113,8 @@

          Classes

          async def append( self, *, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> Optional[AsyncSlackResponse]: """Append to the stream. @@ -118,6 +123,7 @@

          Classes

          is stopped this method cannot be called. Args: + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -145,9 +151,10 @@

          Classes

          raise e.SlackRequestError(f"Cannot append to stream: stream state is {self._state}") if kwargs.get("token"): self._token = kwargs.pop("token") - self._buffer += markdown_text - if len(self._buffer) >= self._buffer_size: - return await self._flush_buffer(**kwargs) + if markdown_text is not None: + self._buffer += markdown_text + if len(self._buffer) >= self._buffer_size or chunks is not None: + return await self._flush_buffer(chunks=chunks, **kwargs) details = { "buffer_length": len(self._buffer), "buffer_size": self._buffer_size, @@ -163,6 +170,7 @@

          Classes

          self, *, markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, metadata: Optional[Union[Dict, Metadata]] = None, **kwargs, @@ -171,6 +179,7 @@

          Classes

          Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -211,26 +220,36 @@

          Classes

          raise e.SlackRequestError("Failed to stop stream: stream not started") self._stream_ts = str(response["ts"]) self._state = "in_progress" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) response = await self._client.chat_stopStream( token=self._token, channel=self._stream_args["channel"], ts=self._stream_ts, blocks=blocks, - markdown_text=self._buffer, + chunks=flushings, metadata=metadata, **kwargs, ) self._state = "completed" return response - async def _flush_buffer(self, **kwargs) -> AsyncSlackResponse: - """Flush the internal buffer by making appropriate API calls.""" + async def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs) -> AsyncSlackResponse: + """Flush the internal buffer with chunks by making appropriate API calls.""" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) if not self._stream_ts: response = await self._client.chat_startStream( **self._stream_args, token=self._token, **kwargs, - markdown_text=self._buffer, + chunks=flushings, ) self._stream_ts = response.get("ts") self._state = "in_progress" @@ -240,7 +259,7 @@

          Classes

          channel=self._stream_args["channel"], ts=self._stream_ts, **kwargs, - markdown_text=self._buffer, + chunks=flushings, ) self._buffer = "" return response
          @@ -266,6 +285,9 @@

          Args

          streaming to channels.
          recipient_user_id
          The encoded ID of the user to receive the streaming text. Required when streaming to channels.
          +
          task_display_mode
          +
          Specifies how tasks are displayed in the message. A "timeline" displays individual tasks +interleaved with text and "plan" displays all tasks together.
          buffer_size
          The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits.
          @@ -275,7 +297,7 @@

          Args

          Methods

          -async def append(self, *, markdown_text: str, **kwargs) ‑> AsyncSlackResponse | None +async def append(self,
          *,
          markdown_text: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> AsyncSlackResponse | None
          @@ -285,7 +307,8 @@

          Methods

          async def append(
               self,
               *,
          -    markdown_text: str,
          +    markdown_text: Optional[str] = None,
          +    chunks: Optional[Sequence[Union[Dict, Chunk]]] = None,
               **kwargs,
           ) -> Optional[AsyncSlackResponse]:
               """Append to the stream.
          @@ -294,6 +317,7 @@ 

          Methods

          is stopped this method cannot be called. Args: + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -321,9 +345,10 @@

          Methods

          raise e.SlackRequestError(f"Cannot append to stream: stream state is {self._state}") if kwargs.get("token"): self._token = kwargs.pop("token") - self._buffer += markdown_text - if len(self._buffer) >= self._buffer_size: - return await self._flush_buffer(**kwargs) + if markdown_text is not None: + self._buffer += markdown_text + if len(self._buffer) >= self._buffer_size or chunks is not None: + return await self._flush_buffer(chunks=chunks, **kwargs) details = { "buffer_length": len(self._buffer), "buffer_size": self._buffer_size, @@ -340,6 +365,8 @@

          Methods

          is stopped this method cannot be called.

          Args

          +
          chunks
          +
          An array of streaming chunks that can contain either markdown text or task updates.
          markdown_text
          Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far.
          @@ -366,7 +393,7 @@

          Example

          -async def stop(self,
          *,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          **kwargs) ‑> AsyncSlackResponse
          +async def stop(self,
          *,
          markdown_text: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          **kwargs) ‑> AsyncSlackResponse
          @@ -377,6 +404,7 @@

          Example

          self, *, markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, metadata: Optional[Union[Dict, Metadata]] = None, **kwargs, @@ -385,6 +413,7 @@

          Example

          Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -425,12 +454,17 @@

          Example

          raise e.SlackRequestError("Failed to stop stream: stream not started") self._stream_ts = str(response["ts"]) self._state = "in_progress" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) response = await self._client.chat_stopStream( token=self._token, channel=self._stream_args["channel"], ts=self._stream_ts, blocks=blocks, - markdown_text=self._buffer, + chunks=flushings, metadata=metadata, **kwargs, ) @@ -442,6 +476,8 @@

          Args

          blocks
          A list of blocks that will be rendered at the bottom of the finalized message.
          +
          chunks
          +
          An array of streaming chunks that can contain either markdown text or task updates.
          markdown_text
          Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far.
          diff --git a/docs/reference/web/async_client.html b/docs/reference/web/async_client.html index 2ec1ba84a..6efcb62e5 100644 --- a/docs/reference/web/async_client.html +++ b/docs/reference/web/async_client.html @@ -2651,7 +2651,8 @@

          Classes

          *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> AsyncSlackResponse: """Appends text to an existing streaming conversation. @@ -2662,8 +2663,10 @@

          Classes

          "channel": channel, "ts": ts, "markdown_text": markdown_text, + "chunks": chunks, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return await self.api_call("chat.appendStream", json=kwargs) @@ -2905,6 +2908,8 @@

          Classes

          markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> AsyncSlackResponse: """Starts a new streaming conversation. @@ -2917,8 +2922,11 @@

          Classes

          "markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return await self.api_call("chat.startStream", json=kwargs) @@ -2930,6 +2938,7 @@

          Classes

          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, ) -> AsyncSlackResponse: """Stops a streaming conversation. @@ -2942,6 +2951,7 @@

          Classes

          "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -2956,6 +2966,7 @@

          Classes

          thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> AsyncChatStream: """Stream markdown text into a conversation. @@ -2982,6 +2993,8 @@

          Classes

          recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -3007,6 +3020,7 @@

          Classes

          thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, ) @@ -10144,7 +10158,7 @@

          Methods

          Unarchives a channel.

          -async def chat_appendStream(self, *, channel: str, ts: str, markdown_text: str, **kwargs) ‑> AsyncSlackResponse +async def chat_appendStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> AsyncSlackResponse
          @@ -10156,7 +10170,8 @@

          Methods

          *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> AsyncSlackResponse: """Appends text to an existing streaming conversation. @@ -10167,8 +10182,10 @@

          Methods

          "channel": channel, "ts": ts, "markdown_text": markdown_text, + "chunks": chunks, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return await self.api_call("chat.appendStream", json=kwargs)
          @@ -10494,7 +10511,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.scheduledMessages.list

          -async def chat_startStream(self,
          *,
          channel: str,
          thread_ts: str,
          markdown_text: str | None = None,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs) ‑> AsyncSlackResponse
          +async def chat_startStream(self,
          *,
          channel: str,
          thread_ts: str,
          markdown_text: str | None = None,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          task_display_mode: str | None = None,
          **kwargs) ‑> AsyncSlackResponse
          @@ -10509,6 +10526,8 @@

          Methods

          markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> AsyncSlackResponse: """Starts a new streaming conversation. @@ -10521,8 +10540,11 @@

          Methods

          "markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return await self.api_call("chat.startStream", json=kwargs)
          @@ -10530,7 +10552,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.startStream

          -async def chat_stopStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          **kwargs) ‑> AsyncSlackResponse
          +async def chat_stopStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> AsyncSlackResponse
          @@ -10545,6 +10567,7 @@

          Methods

          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, ) -> AsyncSlackResponse: """Stops a streaming conversation. @@ -10557,6 +10580,7 @@

          Methods

          "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -10567,7 +10591,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.stopStream

          -async def chat_stream(self,
          *,
          buffer_size: int = 256,
          channel: str,
          thread_ts: str,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs) ‑> AsyncChatStream
          +async def chat_stream(self,
          *,
          buffer_size: int = 256,
          channel: str,
          thread_ts: str,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          task_display_mode: str | None = None,
          **kwargs) ‑> AsyncChatStream
          @@ -10582,6 +10606,7 @@

          Methods

          thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> AsyncChatStream: """Stream markdown text into a conversation. @@ -10608,6 +10633,8 @@

          Methods

          recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10633,6 +10660,7 @@

          Methods

          thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, )
          @@ -10665,6 +10693,9 @@

          Args

          streaming to channels.
          recipient_user_id
          The encoded ID of the user to receive the streaming text. Required when streaming to channels.
          +
          task_display_mode
          +
          Specifies how tasks are displayed in the message. A "timeline" displays individual tasks +interleaved with text and "plan" displays all tasks together.
          **kwargs
          Additional arguments passed to the underlying API calls.
          diff --git a/docs/reference/web/chat_stream.html b/docs/reference/web/chat_stream.html index 94d96e5eb..4ac9750a5 100644 --- a/docs/reference/web/chat_stream.html +++ b/docs/reference/web/chat_stream.html @@ -48,7 +48,7 @@

          Classes

          class ChatStream -(client: WebClient,
          *,
          channel: str,
          logger: logging.Logger,
          thread_ts: str,
          buffer_size: int,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs)
          +(client: WebClient,
          *,
          channel: str,
          logger: logging.Logger,
          thread_ts: str,
          buffer_size: int,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          task_display_mode: str | None = None,
          **kwargs)
          @@ -72,6 +72,7 @@

          Classes

          buffer_size: int, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ): """Initialize a new ChatStream instance. @@ -87,6 +88,8 @@

          Classes

          recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits. **kwargs: Additional arguments passed to the underlying API calls. @@ -99,6 +102,7 @@

          Classes

          "thread_ts": thread_ts, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "task_display_mode": task_display_mode, **kwargs, } self._buffer = "" @@ -109,7 +113,8 @@

          Classes

          def append( self, *, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> Optional[SlackResponse]: """Append to the stream. @@ -118,6 +123,7 @@

          Classes

          is stopped this method cannot be called. Args: + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -145,9 +151,10 @@

          Classes

          raise e.SlackRequestError(f"Cannot append to stream: stream state is {self._state}") if kwargs.get("token"): self._token = kwargs.pop("token") - self._buffer += markdown_text - if len(self._buffer) >= self._buffer_size: - return self._flush_buffer(**kwargs) + if markdown_text is not None: + self._buffer += markdown_text + if len(self._buffer) >= self._buffer_size or chunks is not None: + return self._flush_buffer(chunks=chunks, **kwargs) details = { "buffer_length": len(self._buffer), "buffer_size": self._buffer_size, @@ -163,6 +170,7 @@

          Classes

          self, *, markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, metadata: Optional[Union[Dict, Metadata]] = None, **kwargs, @@ -171,6 +179,7 @@

          Classes

          Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -211,26 +220,36 @@

          Classes

          raise e.SlackRequestError("Failed to stop stream: stream not started") self._stream_ts = str(response["ts"]) self._state = "in_progress" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) response = self._client.chat_stopStream( token=self._token, channel=self._stream_args["channel"], ts=self._stream_ts, blocks=blocks, - markdown_text=self._buffer, + chunks=flushings, metadata=metadata, **kwargs, ) self._state = "completed" return response - def _flush_buffer(self, **kwargs) -> SlackResponse: - """Flush the internal buffer by making appropriate API calls.""" + def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs) -> SlackResponse: + """Flush the internal buffer with chunks by making appropriate API calls.""" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) if not self._stream_ts: response = self._client.chat_startStream( **self._stream_args, token=self._token, **kwargs, - markdown_text=self._buffer, + chunks=flushings, ) self._stream_ts = response.get("ts") self._state = "in_progress" @@ -240,7 +259,7 @@

          Classes

          channel=self._stream_args["channel"], ts=self._stream_ts, **kwargs, - markdown_text=self._buffer, + chunks=flushings, ) self._buffer = "" return response @@ -266,6 +285,9 @@

          Args

          streaming to channels.
          recipient_user_id
          The encoded ID of the user to receive the streaming text. Required when streaming to channels.
          +
          task_display_mode
          +
          Specifies how tasks are displayed in the message. A "timeline" displays individual tasks +interleaved with text and "plan" displays all tasks together.
          buffer_size
          The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits.
          @@ -275,7 +297,7 @@

          Args

          Methods

          -def append(self, *, markdown_text: str, **kwargs) ‑> SlackResponse | None +def append(self,
          *,
          markdown_text: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> SlackResponse | None
          @@ -285,7 +307,8 @@

          Methods

          def append(
               self,
               *,
          -    markdown_text: str,
          +    markdown_text: Optional[str] = None,
          +    chunks: Optional[Sequence[Union[Dict, Chunk]]] = None,
               **kwargs,
           ) -> Optional[SlackResponse]:
               """Append to the stream.
          @@ -294,6 +317,7 @@ 

          Methods

          is stopped this method cannot be called. Args: + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -321,9 +345,10 @@

          Methods

          raise e.SlackRequestError(f"Cannot append to stream: stream state is {self._state}") if kwargs.get("token"): self._token = kwargs.pop("token") - self._buffer += markdown_text - if len(self._buffer) >= self._buffer_size: - return self._flush_buffer(**kwargs) + if markdown_text is not None: + self._buffer += markdown_text + if len(self._buffer) >= self._buffer_size or chunks is not None: + return self._flush_buffer(chunks=chunks, **kwargs) details = { "buffer_length": len(self._buffer), "buffer_size": self._buffer_size, @@ -340,6 +365,8 @@

          Methods

          is stopped this method cannot be called.

          Args

          +
          chunks
          +
          An array of streaming chunks that can contain either markdown text or task updates.
          markdown_text
          Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far.
          @@ -366,7 +393,7 @@

          Example

          -def stop(self,
          *,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          **kwargs) ‑> SlackResponse
          +def stop(self,
          *,
          markdown_text: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          **kwargs) ‑> SlackResponse
          @@ -377,6 +404,7 @@

          Example

          self, *, markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, metadata: Optional[Union[Dict, Metadata]] = None, **kwargs, @@ -385,6 +413,7 @@

          Example

          Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. + chunks: An array of streaming chunks that can contain either markdown text or task updates. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -425,12 +454,17 @@

          Example

          raise e.SlackRequestError("Failed to stop stream: stream not started") self._stream_ts = str(response["ts"]) self._state = "in_progress" + flushings: List[Union[Dict, Chunk]] = [] + if len(self._buffer) != 0: + flushings.append(MarkdownTextChunk(text=self._buffer)) + if chunks is not None: + flushings.extend(chunks) response = self._client.chat_stopStream( token=self._token, channel=self._stream_args["channel"], ts=self._stream_ts, blocks=blocks, - markdown_text=self._buffer, + chunks=flushings, metadata=metadata, **kwargs, ) @@ -442,6 +476,8 @@

          Args

          blocks
          A list of blocks that will be rendered at the bottom of the finalized message.
          +
          chunks
          +
          An array of streaming chunks that can contain either markdown text or task updates.
          markdown_text
          Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far.
          diff --git a/docs/reference/web/client.html b/docs/reference/web/client.html index 6fded11e1..7431a0038 100644 --- a/docs/reference/web/client.html +++ b/docs/reference/web/client.html @@ -2651,7 +2651,8 @@

          Classes

          *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> SlackResponse: """Appends text to an existing streaming conversation. @@ -2662,8 +2663,10 @@

          Classes

          "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) @@ -2905,6 +2908,8 @@

          Classes

          markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> SlackResponse: """Starts a new streaming conversation. @@ -2917,8 +2922,11 @@

          Classes

          "markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return self.api_call("chat.startStream", json=kwargs) @@ -2930,6 +2938,7 @@

          Classes

          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. @@ -2942,6 +2951,7 @@

          Classes

          "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -2956,6 +2966,7 @@

          Classes

          thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> ChatStream: """Stream markdown text into a conversation. @@ -2982,6 +2993,8 @@

          Classes

          recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -3007,6 +3020,7 @@

          Classes

          thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, ) @@ -10144,7 +10158,7 @@

          Methods

          Unarchives a channel.

          -def chat_appendStream(self, *, channel: str, ts: str, markdown_text: str, **kwargs) ‑> SlackResponse +def chat_appendStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> SlackResponse
          @@ -10156,7 +10170,8 @@

          Methods

          *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> SlackResponse: """Appends text to an existing streaming conversation. @@ -10167,8 +10182,10 @@

          Methods

          "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)
          @@ -10494,7 +10511,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.scheduledMessages.list

          -def chat_startStream(self,
          *,
          channel: str,
          thread_ts: str,
          markdown_text: str | None = None,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs) ‑> SlackResponse
          +def chat_startStream(self,
          *,
          channel: str,
          thread_ts: str,
          markdown_text: str | None = None,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          task_display_mode: str | None = None,
          **kwargs) ‑> SlackResponse
          @@ -10509,6 +10526,8 @@

          Methods

          markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> SlackResponse: """Starts a new streaming conversation. @@ -10521,8 +10540,11 @@

          Methods

          "markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return self.api_call("chat.startStream", json=kwargs)
          @@ -10530,7 +10552,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.startStream

          -def chat_stopStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          **kwargs) ‑> SlackResponse
          +def chat_stopStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> SlackResponse
          @@ -10545,6 +10567,7 @@

          Methods

          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. @@ -10557,6 +10580,7 @@

          Methods

          "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -10567,7 +10591,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.stopStream

          -def chat_stream(self,
          *,
          buffer_size: int = 256,
          channel: str,
          thread_ts: str,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs) ‑> ChatStream
          +def chat_stream(self,
          *,
          buffer_size: int = 256,
          channel: str,
          thread_ts: str,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          task_display_mode: str | None = None,
          **kwargs) ‑> ChatStream
          @@ -10582,6 +10606,7 @@

          Methods

          thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> ChatStream: """Stream markdown text into a conversation. @@ -10608,6 +10633,8 @@

          Methods

          recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10633,6 +10660,7 @@

          Methods

          thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, )
          @@ -10665,6 +10693,9 @@

          Args

          streaming to channels.
          recipient_user_id
          The encoded ID of the user to receive the streaming text. Required when streaming to channels.
          +
          task_display_mode
          +
          Specifies how tasks are displayed in the message. A "timeline" displays individual tasks +interleaved with text and "plan" displays all tasks together.
          **kwargs
          Additional arguments passed to the underlying API calls.
          diff --git a/docs/reference/web/index.html b/docs/reference/web/index.html index 611a26b3b..5780f1f91 100644 --- a/docs/reference/web/index.html +++ b/docs/reference/web/index.html @@ -3020,7 +3020,8 @@

          Raises

          *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> SlackResponse: """Appends text to an existing streaming conversation. @@ -3031,8 +3032,10 @@

          Raises

          "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) @@ -3274,6 +3277,8 @@

          Raises

          markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> SlackResponse: """Starts a new streaming conversation. @@ -3286,8 +3291,11 @@

          Raises

          "markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return self.api_call("chat.startStream", json=kwargs) @@ -3299,6 +3307,7 @@

          Raises

          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. @@ -3311,6 +3320,7 @@

          Raises

          "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -3325,6 +3335,7 @@

          Raises

          thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> ChatStream: """Stream markdown text into a conversation. @@ -3351,6 +3362,8 @@

          Raises

          recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -3376,6 +3389,7 @@

          Raises

          thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, ) @@ -10513,7 +10527,7 @@

          Methods

          Unarchives a channel.

          -def chat_appendStream(self, *, channel: str, ts: str, markdown_text: str, **kwargs) ‑> SlackResponse +def chat_appendStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> SlackResponse
          @@ -10525,7 +10539,8 @@

          Methods

          *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> SlackResponse: """Appends text to an existing streaming conversation. @@ -10536,8 +10551,10 @@

          Methods

          "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)
          @@ -10863,7 +10880,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.scheduledMessages.list

          -def chat_startStream(self,
          *,
          channel: str,
          thread_ts: str,
          markdown_text: str | None = None,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs) ‑> SlackResponse
          +def chat_startStream(self,
          *,
          channel: str,
          thread_ts: str,
          markdown_text: str | None = None,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          task_display_mode: str | None = None,
          **kwargs) ‑> SlackResponse
          @@ -10878,6 +10895,8 @@

          Methods

          markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> SlackResponse: """Starts a new streaming conversation. @@ -10890,8 +10909,11 @@

          Methods

          "markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return self.api_call("chat.startStream", json=kwargs)
          @@ -10899,7 +10921,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.startStream

          -def chat_stopStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          **kwargs) ‑> SlackResponse
          +def chat_stopStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> SlackResponse
          @@ -10914,6 +10936,7 @@

          Methods

          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. @@ -10926,6 +10949,7 @@

          Methods

          "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -10936,7 +10960,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.stopStream

          -def chat_stream(self,
          *,
          buffer_size: int = 256,
          channel: str,
          thread_ts: str,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs) ‑> ChatStream
          +def chat_stream(self,
          *,
          buffer_size: int = 256,
          channel: str,
          thread_ts: str,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          task_display_mode: str | None = None,
          **kwargs) ‑> ChatStream
          @@ -10951,6 +10975,7 @@

          Methods

          thread_ts: str, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + task_display_mode: Optional[str] = None, **kwargs, ) -> ChatStream: """Stream markdown text into a conversation. @@ -10977,6 +11002,8 @@

          Methods

          recipient_team_id: The encoded ID of the team the user receiving the streaming text belongs to. Required when streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. + task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks + interleaved with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -11002,6 +11029,7 @@

          Methods

          thread_ts=thread_ts, recipient_team_id=recipient_team_id, recipient_user_id=recipient_user_id, + task_display_mode=task_display_mode, buffer_size=buffer_size, **kwargs, ) @@ -11034,6 +11062,9 @@

          Args

          streaming to channels.
          recipient_user_id
          The encoded ID of the user to receive the streaming text. Required when streaming to channels.
          +
          task_display_mode
          +
          Specifies how tasks are displayed in the message. A "timeline" displays individual tasks +interleaved with text and "plan" displays all tasks together.
          **kwargs
          Additional arguments passed to the underlying API calls.
          diff --git a/docs/reference/web/legacy_client.html b/docs/reference/web/legacy_client.html index d100178dc..86d9b1d0c 100644 --- a/docs/reference/web/legacy_client.html +++ b/docs/reference/web/legacy_client.html @@ -2650,7 +2650,8 @@

          Classes

          *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Appends text to an existing streaming conversation. @@ -2661,8 +2662,10 @@

          Classes

          "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) @@ -2904,6 +2907,8 @@

          Classes

          markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> Union[Future, SlackResponse]: """Starts a new streaming conversation. @@ -2916,8 +2921,11 @@

          Classes

          "markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return self.api_call("chat.startStream", json=kwargs) @@ -2929,6 +2937,7 @@

          Classes

          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, ) -> Union[Future, SlackResponse]: """Stops a streaming conversation. @@ -2941,6 +2950,7 @@

          Classes

          "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) @@ -10080,7 +10090,7 @@

          Methods

          Unarchives a channel.

          -def chat_appendStream(self, *, channel: str, ts: str, markdown_text: str, **kwargs) ‑> _asyncio.Future | LegacySlackResponse +def chat_appendStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> _asyncio.Future | LegacySlackResponse
          @@ -10092,7 +10102,8 @@

          Methods

          *, channel: str, ts: str, - markdown_text: str, + markdown_text: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Appends text to an existing streaming conversation. @@ -10103,8 +10114,10 @@

          Methods

          "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)
          @@ -10430,7 +10443,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.scheduledMessages.list

          -def chat_startStream(self,
          *,
          channel: str,
          thread_ts: str,
          markdown_text: str | None = None,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          **kwargs) ‑> _asyncio.Future | LegacySlackResponse
          +def chat_startStream(self,
          *,
          channel: str,
          thread_ts: str,
          markdown_text: str | None = None,
          recipient_team_id: str | None = None,
          recipient_user_id: str | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          task_display_mode: str | None = None,
          **kwargs) ‑> _asyncio.Future | LegacySlackResponse
          @@ -10445,6 +10458,8 @@

          Methods

          markdown_text: Optional[str] = None, recipient_team_id: Optional[str] = None, recipient_user_id: Optional[str] = None, + chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, + task_display_mode: Optional[str] = None, # timeline, plan **kwargs, ) -> Union[Future, SlackResponse]: """Starts a new streaming conversation. @@ -10457,8 +10472,11 @@

          Methods

          "markdown_text": markdown_text, "recipient_team_id": recipient_team_id, "recipient_user_id": recipient_user_id, + "chunks": chunks, + "task_display_mode": task_display_mode, } ) + _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) return self.api_call("chat.startStream", json=kwargs)
          @@ -10466,7 +10484,7 @@

          Methods

          https://docs.slack.dev/reference/methods/chat.startStream

          -def chat_stopStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          **kwargs) ‑> _asyncio.Future | LegacySlackResponse
          +def chat_stopStream(self,
          *,
          channel: str,
          ts: str,
          markdown_text: str | None = None,
          blocks: str | Sequence[Dict | Block] | None = None,
          metadata: Dict | Metadata | None = None,
          chunks: Sequence[Dict | Chunk] | None = None,
          **kwargs) ‑> _asyncio.Future | LegacySlackResponse
          @@ -10481,6 +10499,7 @@

          Methods

          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, ) -> Union[Future, SlackResponse]: """Stops a streaming conversation. @@ -10493,6 +10512,7 @@

          Methods

          "markdown_text": markdown_text, "blocks": blocks, "metadata": metadata, + "chunks": chunks, } ) _parse_web_class_objects(kwargs) diff --git a/slack_sdk/version.py b/slack_sdk/version.py index fb572e0ba..7f81a760a 100644 --- a/slack_sdk/version.py +++ b/slack_sdk/version.py @@ -1,3 +1,3 @@ """Check the latest version at https://pypi.org/project/slack-sdk/""" -__version__ = "3.39.0" +__version__ = "3.40.0.dev0" From 83bc1e857fe2ca460a5ab67a7949fa8aef317c0f Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Thu, 29 Jan 2026 10:41:45 -0800 Subject: [PATCH 7/8] fix: remove icon_url from url source block element and plan_id from plan block and update chat stream variable (#1822) --- slack_sdk/models/blocks/block_elements.py | 4 ---- slack_sdk/models/blocks/blocks.py | 5 ----- slack_sdk/web/async_chat_stream.py | 10 +++++----- slack_sdk/web/chat_stream.py | 10 +++++----- tests/slack_sdk/models/test_blocks.py | 1 - tests/slack_sdk/models/test_chunks.py | 2 -- 6 files changed, 10 insertions(+), 22 deletions(-) diff --git a/slack_sdk/models/blocks/block_elements.py b/slack_sdk/models/blocks/block_elements.py index be683162b..85a9742e4 100644 --- a/slack_sdk/models/blocks/block_elements.py +++ b/slack_sdk/models/blocks/block_elements.py @@ -1668,7 +1668,6 @@ def attributes(self) -> Set[str]: # type: ignore[override] { "url", "text", - "icon_url", } ) @@ -1677,7 +1676,6 @@ def __init__( *, url: str, text: str, - icon_url: Optional[str] = None, **others: Dict, ): """ @@ -1687,13 +1685,11 @@ def __init__( Args: url (required): The URL type source. text (required): Display text for the URL. - icon_url: Optional icon URL to display with the source. """ super().__init__(type=self.type) show_unknown_key_warning(self, others) self.url = url self.text = text - self.icon_url = icon_url # ------------------------------------------------- diff --git a/slack_sdk/models/blocks/blocks.py b/slack_sdk/models/blocks/blocks.py index 26c25d73f..56a274c8c 100644 --- a/slack_sdk/models/blocks/blocks.py +++ b/slack_sdk/models/blocks/blocks.py @@ -849,7 +849,6 @@ class PlanBlock(Block): def attributes(self) -> Set[str]: # type: ignore[override] return super().attributes.union( { - "plan_id", "title", "tasks", } @@ -858,7 +857,6 @@ def attributes(self) -> Set[str]: # type: ignore[override] def __init__( self, *, - plan_id: str, title: str, tasks: Optional[Sequence[Union[Dict, TaskCardBlock]]] = None, block_id: Optional[str] = None, @@ -872,14 +870,11 @@ def __init__( Maximum length for this field is 255 characters. block_id should be unique for each message and each iteration of a message. If a message is updated, use a new block_id. - plan_id (required): ID for the plan (May be removed / made optional, feel free to pass in a random UUID - for now) title (required): Title of the plan in plain text tasks: Details of the task in the form of a single "rich_text" entity. """ super().__init__(type=self.type, block_id=block_id) show_unknown_key_warning(self, others) - self.plan_id = plan_id self.title = title self.tasks = tasks diff --git a/slack_sdk/web/async_chat_stream.py b/slack_sdk/web/async_chat_stream.py index 7af774bbc..1d48042f6 100644 --- a/slack_sdk/web/async_chat_stream.py +++ b/slack_sdk/web/async_chat_stream.py @@ -206,17 +206,17 @@ async def stop( async def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs) -> AsyncSlackResponse: """Flush the internal buffer with chunks by making appropriate API calls.""" - flushings: List[Union[Dict, Chunk]] = [] + chunks_to_flush: List[Union[Dict, Chunk]] = [] if len(self._buffer) != 0: - flushings.append(MarkdownTextChunk(text=self._buffer)) + chunks_to_flush.append(MarkdownTextChunk(text=self._buffer)) if chunks is not None: - flushings.extend(chunks) + chunks_to_flush.extend(chunks) if not self._stream_ts: response = await self._client.chat_startStream( **self._stream_args, token=self._token, **kwargs, - chunks=flushings, + chunks=chunks_to_flush, ) self._stream_ts = response.get("ts") self._state = "in_progress" @@ -226,7 +226,7 @@ async def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = N channel=self._stream_args["channel"], ts=self._stream_ts, **kwargs, - chunks=flushings, + chunks=chunks_to_flush, ) self._buffer = "" return response diff --git a/slack_sdk/web/chat_stream.py b/slack_sdk/web/chat_stream.py index 580f7cacb..575aed8c4 100644 --- a/slack_sdk/web/chat_stream.py +++ b/slack_sdk/web/chat_stream.py @@ -196,17 +196,17 @@ def stop( def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs) -> SlackResponse: """Flush the internal buffer with chunks by making appropriate API calls.""" - flushings: List[Union[Dict, Chunk]] = [] + chunks_to_flush: List[Union[Dict, Chunk]] = [] if len(self._buffer) != 0: - flushings.append(MarkdownTextChunk(text=self._buffer)) + chunks_to_flush.append(MarkdownTextChunk(text=self._buffer)) if chunks is not None: - flushings.extend(chunks) + chunks_to_flush.extend(chunks) if not self._stream_ts: response = self._client.chat_startStream( **self._stream_args, token=self._token, **kwargs, - chunks=flushings, + chunks=chunks_to_flush, ) self._stream_ts = response.get("ts") self._state = "in_progress" @@ -216,7 +216,7 @@ def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, * channel=self._stream_args["channel"], ts=self._stream_ts, **kwargs, - chunks=flushings, + chunks=chunks_to_flush, ) self._buffer = "" return response diff --git a/tests/slack_sdk/models/test_blocks.py b/tests/slack_sdk/models/test_blocks.py index daada60dd..531ebe057 100644 --- a/tests/slack_sdk/models/test_blocks.py +++ b/tests/slack_sdk/models/test_blocks.py @@ -901,7 +901,6 @@ class PlanBlockTests(unittest.TestCase): def test_document(self): input = { "type": "plan", - "plan_id": "plan_1", "title": "Thinking completed", "tasks": [ { diff --git a/tests/slack_sdk/models/test_chunks.py b/tests/slack_sdk/models/test_chunks.py index 293f5acb2..78845b307 100644 --- a/tests/slack_sdk/models/test_chunks.py +++ b/tests/slack_sdk/models/test_chunks.py @@ -66,7 +66,6 @@ def test_json(self): UrlSourceElement( text="The Free Encyclopedia", url="https://wikipedia.org", - icon_url="https://example.com/globe.png", ), ], ).to_dict(), @@ -86,7 +85,6 @@ def test_json(self): "type": "url", "text": "The Free Encyclopedia", "url": "https://wikipedia.org", - "icon_url": "https://example.com/globe.png", }, ], }, From 6ae339fa77c04cd293d2b912f6b78d62dcc73a86 Mon Sep 17 00:00:00 2001 From: Luke Russell <31357343+lukegalbraithrussell@users.noreply.github.com> Date: Fri, 30 Jan 2026 10:21:05 -0800 Subject: [PATCH 8/8] docs: polishing source wording (#1825) --- docs/reference/index.html | 6 +- .../models/blocks/basic_components.html | 12 ++-- .../models/blocks/block_elements.html | 23 +++---- docs/reference/models/blocks/blocks.html | 31 ++++----- docs/reference/models/blocks/index.html | 64 +++++++------------ docs/reference/models/messages/chunk.html | 10 +-- docs/reference/models/views/index.html | 4 +- docs/reference/web/async_chat_stream.html | 26 ++++---- docs/reference/web/async_client.html | 6 +- docs/reference/web/chat_stream.html | 26 ++++---- docs/reference/web/client.html | 6 +- docs/reference/web/index.html | 6 +- slack_sdk/models/blocks/block_elements.py | 2 +- slack_sdk/models/blocks/blocks.py | 10 +-- slack_sdk/models/messages/chunk.py | 4 +- slack_sdk/web/async_chat_stream.py | 6 +- slack_sdk/web/async_client.py | 2 +- slack_sdk/web/chat_stream.py | 6 +- slack_sdk/web/client.py | 2 +- 19 files changed, 110 insertions(+), 142 deletions(-) diff --git a/docs/reference/index.html b/docs/reference/index.html index c2f518bcf..31b766b61 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -3098,7 +3098,7 @@

          Classes

          streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10738,7 +10738,7 @@

          Methods

          streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10799,7 +10799,7 @@

          Args

          The encoded ID of the user to receive the streaming text. Required when streaming to channels.
          task_display_mode
          Specifies how tasks are displayed in the message. A "timeline" displays individual tasks -interleaved with text and "plan" displays all tasks together.
          +with text and "plan" displays all tasks together.
          **kwargs
          Additional arguments passed to the underlying API calls.
          diff --git a/docs/reference/models/blocks/basic_components.html b/docs/reference/models/blocks/basic_components.html index 2821b6a4b..50554265d 100644 --- a/docs/reference/models/blocks/basic_components.html +++ b/docs/reference/models/blocks/basic_components.html @@ -188,7 +188,7 @@

          Class variables

          Static methods

          -def parse(confirm: ForwardRef('ConfirmObject') | Dict[str, Any]) +def parse(confirm: ConfirmObject | Dict[str, Any])
          @@ -324,7 +324,7 @@

          Class variables

          Static methods

          -def parse(config: ForwardRef('DispatchActionConfig') | Dict[str, Any]) +def parse(config: DispatchActionConfig | Dict[str, Any])
          @@ -446,7 +446,7 @@

          Class variables

          Static methods

          -def parse(feedback_button: ForwardRef('FeedbackButtonObject') | Dict[str, Any]) +def parse(feedback_button: FeedbackButtonObject | Dict[str, Any])
          @@ -907,7 +907,7 @@

          Static methods

          Creates a simple Option instance with the same value and label

          -def parse_all(options: Sequence[Dict[str, Any] | ForwardRef('Option')] | None) ‑> List[Option] | None +def parse_all(options: Sequence[Dict[str, Any] | Option] | None) ‑> List[Option] | None
          @@ -1105,7 +1105,7 @@

          Class variables

          Static methods

          -def parse_all(option_groups: Sequence[Dict[str, Any] | ForwardRef('OptionGroup')] | None) ‑> List[OptionGroup] | None +def parse_all(option_groups: Sequence[Dict[str, Any] | OptionGroup] | None) ‑> List[OptionGroup] | None
          @@ -1536,7 +1536,7 @@

          Class variables

          Static methods

          -def parse(text: str | Dict[str, Any] | ForwardRef('TextObject'),
          default_type: str = 'mrkdwn') ‑> TextObject | None
          +def parse(text: str | Dict[str, Any] | TextObject,
          default_type: str = 'mrkdwn') ‑> TextObject | None
          diff --git a/docs/reference/models/blocks/block_elements.html b/docs/reference/models/blocks/block_elements.html index c7f1347fe..e79ac10d1 100644 --- a/docs/reference/models/blocks/block_elements.html +++ b/docs/reference/models/blocks/block_elements.html @@ -146,13 +146,13 @@

          Class variables

          Static methods

          -def parse(block_element: dict | ForwardRef('BlockElement')) ‑> BlockElement | TextObject | None +def parse(block_element: dict | BlockElement) ‑> BlockElement | TextObject | None
          -def parse_all(block_elements: Sequence[dict | ForwardRef('BlockElement') | TextObject]) ‑> List[BlockElement | TextObject] +def parse_all(block_elements: Sequence[dict | BlockElement | TextObject]) ‑> List[BlockElement | TextObject]
          @@ -829,7 +829,7 @@

          Class variables

          Static methods

          -def parse(filter: dict | ForwardRef('ConversationFilter')) +def parse(filter: dict | ConversationFilter)
          @@ -3505,7 +3505,7 @@

          Class variables

          class RichTextInputElement -(*,
          action_id: str | None = None,
          placeholder: str | dict | TextObject | None = None,
          initial_value: Dict[str, Any] | ForwardRef('RichTextBlock') | None = None,
          dispatch_action_config: dict | DispatchActionConfig | None = None,
          focus_on_load: bool | None = None,
          **others: dict)
          +(*,
          action_id: str | None = None,
          placeholder: str | dict | TextObject | None = None,
          initial_value: Dict[str, Any] | RichTextBlock | None = None,
          dispatch_action_config: dict | DispatchActionConfig | None = None,
          focus_on_load: bool | None = None,
          **others: dict)
          @@ -4666,7 +4666,7 @@

          Inherited members

          class UrlSourceElement -(*, url: str, text: str, icon_url: str | None = None, **others: Dict) +(*, url: str, text: str, **others: Dict)
          @@ -4682,7 +4682,6 @@

          Inherited members

          { "url", "text", - "icon_url", } ) @@ -4691,27 +4690,24 @@

          Inherited members

          *, url: str, text: str, - icon_url: Optional[str] = None, **others: Dict, ): """ - A URL source element to reference in a task card block. + A URL source element that displays a URL source for referencing within a task card block. https://docs.slack.dev/reference/block-kit/block-elements/url-source-element Args: url (required): The URL type source. text (required): Display text for the URL. - icon_url: Optional icon URL to display with the source. """ super().__init__(type=self.type) show_unknown_key_warning(self, others) self.url = url - self.text = text - self.icon_url = icon_url + self.text = text

          Block Elements are things that exists inside of your Blocks. https://docs.slack.dev/reference/block-kit/block-elements/

          -

          A URL source element to reference in a task card block. +

          A URL source element that displays a URL source for referencing within a task card block. https://docs.slack.dev/reference/block-kit/block-elements/url-source-element

          Args

          @@ -4719,8 +4715,6 @@

          Args

          The URL type source.
          text : required
          Display text for the URL.
          -
          icon_url
          -
          Optional icon URL to display with the source.

          Ancestors

            @@ -4749,7 +4743,6 @@

            Instance variables

            { "url", "text", - "icon_url", } ) diff --git a/docs/reference/models/blocks/blocks.html b/docs/reference/models/blocks/blocks.html index 934dd977e..a4f511858 100644 --- a/docs/reference/models/blocks/blocks.html +++ b/docs/reference/models/blocks/blocks.html @@ -298,13 +298,13 @@

            Class variables

            Static methods

            -def parse(block: dict | ForwardRef('Block')) ‑> Block | None +def parse(block: dict | Block) ‑> Block | None
            -def parse_all(blocks: Sequence[dict | ForwardRef('Block')] | None) ‑> List[Block] +def parse_all(blocks: Sequence[dict | Block] | None) ‑> List[Block]
            @@ -1329,7 +1329,7 @@

            Inherited members

            class PlanBlock -(*,
            plan_id: str,
            title: str,
            tasks: Sequence[Dict | TaskCardBlock] | None = None,
            block_id: str | None = None,
            **others: dict)
            +(*,
            title: str,
            tasks: Sequence[Dict | TaskCardBlock] | None = None,
            block_id: str | None = None,
            **others: dict)
            @@ -1343,7 +1343,6 @@

            Inherited members

            def attributes(self) -> Set[str]: # type: ignore[override] return super().attributes.union( { - "plan_id", "title", "tasks", } @@ -1352,13 +1351,12 @@

            Inherited members

            def __init__( self, *, - plan_id: str, title: str, tasks: Optional[Sequence[Union[Dict, TaskCardBlock]]] = None, block_id: Optional[str] = None, **others: dict, ): - """A collection of related tasks. + """Displays a collection of related tasks. https://docs.slack.dev/reference/block-kit/blocks/plan-block/ Args: @@ -1366,22 +1364,19 @@

            Inherited members

            Maximum length for this field is 255 characters. block_id should be unique for each message and each iteration of a message. If a message is updated, use a new block_id. - plan_id (required): ID for the plan (May be removed / made optional, feel free to pass in a random UUID - for now) title (required): Title of the plan in plain text tasks: Details of the task in the form of a single "rich_text" entity. """ super().__init__(type=self.type, block_id=block_id) show_unknown_key_warning(self, others) - self.plan_id = plan_id self.title = title self.tasks = tasks

            Blocks are a series of components that can be combined to create visually rich and compellingly interactive messages. https://docs.slack.dev/reference/block-kit/blocks

            -

            A collection of related tasks. +

            Displays a collection of related tasks. https://docs.slack.dev/reference/block-kit/blocks/plan-block/

            Args

            @@ -1390,9 +1385,6 @@

            Args

            Maximum length for this field is 255 characters. block_id should be unique for each message and each iteration of a message. If a message is updated, use a new block_id.
            -
            plan_id : required
            -
            ID for the plan (May be removed / made optional, feel free to pass in a random UUID -for now)
            title : required
            Title of the plan in plain text
            tasks
            @@ -1423,7 +1415,6 @@

            Instance variables

            def attributes(self) -> Set[str]: # type: ignore[override] return super().attributes.union( { - "plan_id", "title", "tasks", } @@ -1861,7 +1852,7 @@

            Inherited members

            block_id: Optional[str] = None, **others: dict, ): - """A discrete action or tool call. + """Displays a single task, representing a single action. https://docs.slack.dev/reference/block-kit/blocks/task-card-block/ Args: @@ -1873,8 +1864,8 @@

            Inherited members

            title (required): Title of the task in plain text details: Details of the task in the form of a single "rich_text" entity. output: Output of the task in the form of a single "rich_text" entity. - sources: List of sources used to generate a response - status: The state of a task. Either "pending" or "in_progress" or "complete" or "error". + sources: Array of URL source elements used to generate a response. + status: The state of a task. Either "pending", "in_progress", "complete", or "error". """ super().__init__(type=self.type, block_id=block_id) show_unknown_key_warning(self, others) @@ -1893,7 +1884,7 @@

            Inherited members

            Blocks are a series of components that can be combined to create visually rich and compellingly interactive messages. https://docs.slack.dev/reference/block-kit/blocks

            -

            A discrete action or tool call. +

            Displays a single task, representing a single action. https://docs.slack.dev/reference/block-kit/blocks/task-card-block/

            Args

            @@ -1911,9 +1902,9 @@

            Args

            output
            Output of the task in the form of a single "rich_text" entity.
            sources
            -
            List of sources used to generate a response
            +
            Array of URL source elements used to generate a response.
            status
            -
            The state of a task. Either "pending" or "in_progress" or "complete" or "error".
            +
            The state of a task. Either "pending", "in_progress", "complete", or "error".

            Ancestors

              diff --git a/docs/reference/models/blocks/index.html b/docs/reference/models/blocks/index.html index 00d480aee..4444d208b 100644 --- a/docs/reference/models/blocks/index.html +++ b/docs/reference/models/blocks/index.html @@ -320,13 +320,13 @@

              Class variables

              Static methods

              -def parse(block: dict | ForwardRef('Block')) ‑> Block | None +def parse(block: dict | Block) ‑> Block | None
              -def parse_all(blocks: Sequence[dict | ForwardRef('Block')] | None) ‑> List[Block] +def parse_all(blocks: Sequence[dict | Block] | None) ‑> List[Block]
              @@ -458,13 +458,13 @@

              Class variables

              Static methods

              -def parse(block_element: dict | ForwardRef('BlockElement')) ‑> BlockElement | TextObject | None +def parse(block_element: dict | BlockElement) ‑> BlockElement | TextObject | None
              -def parse_all(block_elements: Sequence[dict | ForwardRef('BlockElement') | TextObject]) ‑> List[BlockElement | TextObject] +def parse_all(block_elements: Sequence[dict | BlockElement | TextObject]) ‑> List[BlockElement | TextObject]
              @@ -1278,7 +1278,7 @@

              Class variables

              Static methods

              -def parse(confirm: ForwardRef('ConfirmObject') | Dict[str, Any]) +def parse(confirm: ConfirmObject | Dict[str, Any])
              @@ -1650,7 +1650,7 @@

              Class variables

              Static methods

              -def parse(filter: dict | ForwardRef('ConversationFilter')) +def parse(filter: dict | ConversationFilter)
              @@ -2842,7 +2842,7 @@

              Class variables

              Static methods

              -def parse(feedback_button: ForwardRef('FeedbackButtonObject') | Dict[str, Any]) +def parse(feedback_button: FeedbackButtonObject | Dict[str, Any])
              @@ -4727,7 +4727,7 @@

              Static methods

              Creates a simple Option instance with the same value and label

              -def parse_all(options: Sequence[Dict[str, Any] | ForwardRef('Option')] | None) ‑> List[Option] | None +def parse_all(options: Sequence[Dict[str, Any] | Option] | None) ‑> List[Option] | None
              @@ -4925,7 +4925,7 @@

              Class variables

              Static methods

              -def parse_all(option_groups: Sequence[Dict[str, Any] | ForwardRef('OptionGroup')] | None) ‑> List[OptionGroup] | None +def parse_all(option_groups: Sequence[Dict[str, Any] | OptionGroup] | None) ‑> List[OptionGroup] | None
              @@ -5354,7 +5354,7 @@

              Inherited members

              class PlanBlock -(*,
              plan_id: str,
              title: str,
              tasks: Sequence[Dict | TaskCardBlock] | None = None,
              block_id: str | None = None,
              **others: dict)
              +(*,
              title: str,
              tasks: Sequence[Dict | TaskCardBlock] | None = None,
              block_id: str | None = None,
              **others: dict)
              @@ -5368,7 +5368,6 @@

              Inherited members

              def attributes(self) -> Set[str]: # type: ignore[override] return super().attributes.union( { - "plan_id", "title", "tasks", } @@ -5377,13 +5376,12 @@

              Inherited members

              def __init__( self, *, - plan_id: str, title: str, tasks: Optional[Sequence[Union[Dict, TaskCardBlock]]] = None, block_id: Optional[str] = None, **others: dict, ): - """A collection of related tasks. + """Displays a collection of related tasks. https://docs.slack.dev/reference/block-kit/blocks/plan-block/ Args: @@ -5391,22 +5389,19 @@

              Inherited members

              Maximum length for this field is 255 characters. block_id should be unique for each message and each iteration of a message. If a message is updated, use a new block_id. - plan_id (required): ID for the plan (May be removed / made optional, feel free to pass in a random UUID - for now) title (required): Title of the plan in plain text tasks: Details of the task in the form of a single "rich_text" entity. """ super().__init__(type=self.type, block_id=block_id) show_unknown_key_warning(self, others) - self.plan_id = plan_id self.title = title self.tasks = tasks

              Blocks are a series of components that can be combined to create visually rich and compellingly interactive messages. https://docs.slack.dev/reference/block-kit/blocks

              -

              A collection of related tasks. +

              Displays a collection of related tasks. https://docs.slack.dev/reference/block-kit/blocks/plan-block/

              Args

              @@ -5415,9 +5410,6 @@

              Args

              Maximum length for this field is 255 characters. block_id should be unique for each message and each iteration of a message. If a message is updated, use a new block_id.
              -
              plan_id : required
              -
              ID for the plan (May be removed / made optional, feel free to pass in a random UUID -for now)
              title : required
              Title of the plan in plain text
              tasks
              @@ -5448,7 +5440,6 @@

              Instance variables

              def attributes(self) -> Set[str]: # type: ignore[override] return super().attributes.union( { - "plan_id", "title", "tasks", } @@ -6152,7 +6143,7 @@

              Class variables

              class RichTextInputElement -(*,
              action_id: str | None = None,
              placeholder: str | dict | TextObject | None = None,
              initial_value: Dict[str, Any] | ForwardRef('RichTextBlock') | None = None,
              dispatch_action_config: dict | DispatchActionConfig | None = None,
              focus_on_load: bool | None = None,
              **others: dict)
              +(*,
              action_id: str | None = None,
              placeholder: str | dict | TextObject | None = None,
              initial_value: Dict[str, Any] | RichTextBlock | None = None,
              dispatch_action_config: dict | DispatchActionConfig | None = None,
              focus_on_load: bool | None = None,
              **others: dict)
              @@ -7358,7 +7349,7 @@

              Inherited members

              block_id: Optional[str] = None, **others: dict, ): - """A discrete action or tool call. + """Displays a single task, representing a single action. https://docs.slack.dev/reference/block-kit/blocks/task-card-block/ Args: @@ -7370,8 +7361,8 @@

              Inherited members

              title (required): Title of the task in plain text details: Details of the task in the form of a single "rich_text" entity. output: Output of the task in the form of a single "rich_text" entity. - sources: List of sources used to generate a response - status: The state of a task. Either "pending" or "in_progress" or "complete" or "error". + sources: Array of URL source elements used to generate a response. + status: The state of a task. Either "pending", "in_progress", "complete", or "error". """ super().__init__(type=self.type, block_id=block_id) show_unknown_key_warning(self, others) @@ -7390,7 +7381,7 @@

              Inherited members

              Blocks are a series of components that can be combined to create visually rich and compellingly interactive messages. https://docs.slack.dev/reference/block-kit/blocks

              -

              A discrete action or tool call. +

              Displays a single task, representing a single action. https://docs.slack.dev/reference/block-kit/blocks/task-card-block/

              Args

              @@ -7408,9 +7399,9 @@

              Args

              output
              Output of the task in the form of a single "rich_text" entity.
              sources
              -
              List of sources used to generate a response
              +
              Array of URL source elements used to generate a response.
              status
              -
              The state of a task. Either "pending" or "in_progress" or "complete" or "error".
              +
              The state of a task. Either "pending", "in_progress", "complete", or "error".

              Ancestors

                @@ -7556,7 +7547,7 @@

                Class variables

                Static methods

                -def parse(text: str | Dict[str, Any] | ForwardRef('TextObject'),
                default_type: str = 'mrkdwn') ‑> TextObject | None
                +def parse(text: str | Dict[str, Any] | TextObject,
                default_type: str = 'mrkdwn') ‑> TextObject | None
                @@ -7863,7 +7854,7 @@

                Inherited members

                class UrlSourceElement -(*, url: str, text: str, icon_url: str | None = None, **others: Dict) +(*, url: str, text: str, **others: Dict)
                @@ -7879,7 +7870,6 @@

                Inherited members

                { "url", "text", - "icon_url", } ) @@ -7888,27 +7878,24 @@

                Inherited members

                *, url: str, text: str, - icon_url: Optional[str] = None, **others: Dict, ): """ - A URL source element to reference in a task card block. + A URL source element that displays a URL source for referencing within a task card block. https://docs.slack.dev/reference/block-kit/block-elements/url-source-element Args: url (required): The URL type source. text (required): Display text for the URL. - icon_url: Optional icon URL to display with the source. """ super().__init__(type=self.type) show_unknown_key_warning(self, others) self.url = url - self.text = text - self.icon_url = icon_url + self.text = text

                Block Elements are things that exists inside of your Blocks. https://docs.slack.dev/reference/block-kit/block-elements/

                -

                A URL source element to reference in a task card block. +

                A URL source element that displays a URL source for referencing within a task card block. https://docs.slack.dev/reference/block-kit/block-elements/url-source-element

                Args

                @@ -7916,8 +7903,6 @@

                Args

                The URL type source.
                text : required
                Display text for the URL.
                -
                icon_url
                -
                Optional icon URL to display with the source.

                Ancestors

                  @@ -7946,7 +7931,6 @@

                  Instance variables

                  { "url", "text", - "icon_url", } )
              diff --git a/docs/reference/models/messages/chunk.html b/docs/reference/models/messages/chunk.html index 722f018c9..49c1ef1bc 100644 --- a/docs/reference/models/messages/chunk.html +++ b/docs/reference/models/messages/chunk.html @@ -121,7 +121,7 @@

              Class variables

              Static methods

              -def parse(chunk: Dict | ForwardRef('Chunk')) ‑> Chunk | None +def parse(chunk: Dict | Chunk) ‑> Chunk | None
              @@ -235,7 +235,7 @@

              Inherited members

              title: str, **others: Dict, ): - """An updated title of plans for task and tool calls. + """Used for displaying an updated title of a plan. https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming """ @@ -246,7 +246,7 @@

              Inherited members

              Chunk for streaming messages.

              https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming

              -

              An updated title of plans for task and tool calls.

              +

              Used for displaying an updated title of a plan.

              https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming

              Ancestors

                @@ -324,7 +324,7 @@

                Inherited members

                sources: Optional[Sequence[Union[Dict, UrlSourceElement]]] = None, **others: Dict, ): - """Used for displaying tool execution progress in a timeline-style UI. + """Used for displaying task progress in a timeline-style UI. https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming """ @@ -340,7 +340,7 @@

                Inherited members

                Chunk for streaming messages.

                https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming

                -

                Used for displaying tool execution progress in a timeline-style UI.

                +

                Used for displaying task progress in a timeline-style UI.

                https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming

                Ancestors

                  diff --git a/docs/reference/models/views/index.html b/docs/reference/models/views/index.html index d9e60359b..b7bad66bc 100644 --- a/docs/reference/models/views/index.html +++ b/docs/reference/models/views/index.html @@ -48,7 +48,7 @@

                  Classes

                  class View -(type: str,
                  id: str | None = None,
                  callback_id: str | None = None,
                  external_id: str | None = None,
                  team_id: str | None = None,
                  bot_id: str | None = None,
                  app_id: str | None = None,
                  root_view_id: str | None = None,
                  previous_view_id: str | None = None,
                  title: str | dict | PlainTextObject | None = None,
                  submit: str | dict | PlainTextObject | None = None,
                  close: str | dict | PlainTextObject | None = None,
                  blocks: Sequence[dict | Block] | None = None,
                  private_metadata: str | None = None,
                  state: dict | ForwardRef('ViewState') | None = None,
                  hash: str | None = None,
                  clear_on_close: bool | None = None,
                  notify_on_close: bool | None = None,
                  **kwargs)
                  +(type: str,
                  id: str | None = None,
                  callback_id: str | None = None,
                  external_id: str | None = None,
                  team_id: str | None = None,
                  bot_id: str | None = None,
                  app_id: str | None = None,
                  root_view_id: str | None = None,
                  previous_view_id: str | None = None,
                  title: str | dict | PlainTextObject | None = None,
                  submit: str | dict | PlainTextObject | None = None,
                  close: str | dict | PlainTextObject | None = None,
                  blocks: Sequence[dict | Block] | None = None,
                  private_metadata: str | None = None,
                  state: dict | ViewState | None = None,
                  hash: str | None = None,
                  clear_on_close: bool | None = None,
                  notify_on_close: bool | None = None,
                  **kwargs)
                  @@ -229,7 +229,7 @@

                  Inherited members

                  class ViewState -(*,
                  values: Dict[str, Dict[str, dict | ForwardRef('ViewStateValue')]])
                  +(*,
                  values: Dict[str, Dict[str, dict | ViewStateValue]])
                  diff --git a/docs/reference/web/async_chat_stream.html b/docs/reference/web/async_chat_stream.html index 994f7df4e..d8e4f5bfe 100644 --- a/docs/reference/web/async_chat_stream.html +++ b/docs/reference/web/async_chat_stream.html @@ -89,7 +89,7 @@

                  Classes

                  streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits. **kwargs: Additional arguments passed to the underlying API calls. @@ -123,7 +123,7 @@

                  Classes

                  is stopped this method cannot be called. Args: - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -179,7 +179,7 @@

                  Classes

                  Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -239,17 +239,17 @@

                  Classes

                  async def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs) -> AsyncSlackResponse: """Flush the internal buffer with chunks by making appropriate API calls.""" - flushings: List[Union[Dict, Chunk]] = [] + chunks_to_flush: List[Union[Dict, Chunk]] = [] if len(self._buffer) != 0: - flushings.append(MarkdownTextChunk(text=self._buffer)) + chunks_to_flush.append(MarkdownTextChunk(text=self._buffer)) if chunks is not None: - flushings.extend(chunks) + chunks_to_flush.extend(chunks) if not self._stream_ts: response = await self._client.chat_startStream( **self._stream_args, token=self._token, **kwargs, - chunks=flushings, + chunks=chunks_to_flush, ) self._stream_ts = response.get("ts") self._state = "in_progress" @@ -259,7 +259,7 @@

                  Classes

                  channel=self._stream_args["channel"], ts=self._stream_ts, **kwargs, - chunks=flushings, + chunks=chunks_to_flush, ) self._buffer = "" return response @@ -287,7 +287,7 @@

                  Args

                  The encoded ID of the user to receive the streaming text. Required when streaming to channels.
                  task_display_mode
                  Specifies how tasks are displayed in the message. A "timeline" displays individual tasks -interleaved with text and "plan" displays all tasks together.
                  +with text and "plan" displays all tasks together.
                  buffer_size
                  The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits.
                  @@ -317,7 +317,7 @@

                  Methods

                  is stopped this method cannot be called. Args: - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -366,7 +366,7 @@

                  Methods

                  Args

                  chunks
                  -
                  An array of streaming chunks that can contain either markdown text or task updates.
                  +
                  An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks.
                  markdown_text
                  Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far.
                  @@ -413,7 +413,7 @@

                  Example

                  Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -477,7 +477,7 @@

                  Args

                  blocks
                  A list of blocks that will be rendered at the bottom of the finalized message.
                  chunks
                  -
                  An array of streaming chunks that can contain either markdown text or task updates.
                  +
                  An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks.
                  markdown_text
                  Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far.
                  diff --git a/docs/reference/web/async_client.html b/docs/reference/web/async_client.html index 6efcb62e5..070de0e95 100644 --- a/docs/reference/web/async_client.html +++ b/docs/reference/web/async_client.html @@ -2994,7 +2994,7 @@

                  Classes

                  streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10634,7 +10634,7 @@

                  Methods

                  streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10695,7 +10695,7 @@

                  Args

                  The encoded ID of the user to receive the streaming text. Required when streaming to channels.
                  task_display_mode
                  Specifies how tasks are displayed in the message. A "timeline" displays individual tasks -interleaved with text and "plan" displays all tasks together.
                  +with text and "plan" displays all tasks together.
              **kwargs
              Additional arguments passed to the underlying API calls.
              diff --git a/docs/reference/web/chat_stream.html b/docs/reference/web/chat_stream.html index 4ac9750a5..59fcbbd84 100644 --- a/docs/reference/web/chat_stream.html +++ b/docs/reference/web/chat_stream.html @@ -89,7 +89,7 @@

              Classes

              streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits. **kwargs: Additional arguments passed to the underlying API calls. @@ -123,7 +123,7 @@

              Classes

              is stopped this method cannot be called. Args: - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -179,7 +179,7 @@

              Classes

              Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -239,17 +239,17 @@

              Classes

              def _flush_buffer(self, chunks: Optional[Sequence[Union[Dict, Chunk]]] = None, **kwargs) -> SlackResponse: """Flush the internal buffer with chunks by making appropriate API calls.""" - flushings: List[Union[Dict, Chunk]] = [] + chunks_to_flush: List[Union[Dict, Chunk]] = [] if len(self._buffer) != 0: - flushings.append(MarkdownTextChunk(text=self._buffer)) + chunks_to_flush.append(MarkdownTextChunk(text=self._buffer)) if chunks is not None: - flushings.extend(chunks) + chunks_to_flush.extend(chunks) if not self._stream_ts: response = self._client.chat_startStream( **self._stream_args, token=self._token, **kwargs, - chunks=flushings, + chunks=chunks_to_flush, ) self._stream_ts = response.get("ts") self._state = "in_progress" @@ -259,7 +259,7 @@

              Classes

              channel=self._stream_args["channel"], ts=self._stream_ts, **kwargs, - chunks=flushings, + chunks=chunks_to_flush, ) self._buffer = "" return response @@ -287,7 +287,7 @@

              Args

              The encoded ID of the user to receive the streaming text. Required when streaming to channels.
              task_display_mode
              Specifies how tasks are displayed in the message. A "timeline" displays individual tasks -interleaved with text and "plan" displays all tasks together.
              +with text and "plan" displays all tasks together.
              buffer_size
              The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits.
              @@ -317,7 +317,7 @@

              Methods

              is stopped this method cannot be called. Args: - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -366,7 +366,7 @@

              Methods

              Args

              chunks
              -
              An array of streaming chunks that can contain either markdown text or task updates.
              +
              An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks.
              markdown_text
              Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far.
              @@ -413,7 +413,7 @@

              Example

              Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you @@ -477,7 +477,7 @@

              Args

              blocks
              A list of blocks that will be rendered at the bottom of the finalized message.
              chunks
              -
              An array of streaming chunks that can contain either markdown text or task updates.
              +
              An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks.
              markdown_text
              Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far.
              diff --git a/docs/reference/web/client.html b/docs/reference/web/client.html index 7431a0038..fecd86b7c 100644 --- a/docs/reference/web/client.html +++ b/docs/reference/web/client.html @@ -2994,7 +2994,7 @@

              Classes

              streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10634,7 +10634,7 @@

              Methods

              streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -10695,7 +10695,7 @@

              Args

              The encoded ID of the user to receive the streaming text. Required when streaming to channels.
              task_display_mode
              Specifies how tasks are displayed in the message. A "timeline" displays individual tasks -interleaved with text and "plan" displays all tasks together.
              +with text and "plan" displays all tasks together.
              **kwargs
              Additional arguments passed to the underlying API calls.
              diff --git a/docs/reference/web/index.html b/docs/reference/web/index.html index 5780f1f91..bec63590c 100644 --- a/docs/reference/web/index.html +++ b/docs/reference/web/index.html @@ -3363,7 +3363,7 @@

              Raises

              streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -11003,7 +11003,7 @@

              Methods

              streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: @@ -11064,7 +11064,7 @@

              Args

              The encoded ID of the user to receive the streaming text. Required when streaming to channels.
              task_display_mode
              Specifies how tasks are displayed in the message. A "timeline" displays individual tasks -interleaved with text and "plan" displays all tasks together.
              +with text and "plan" displays all tasks together.
              **kwargs
              Additional arguments passed to the underlying API calls.
              diff --git a/slack_sdk/models/blocks/block_elements.py b/slack_sdk/models/blocks/block_elements.py index 85a9742e4..bcf7adfe0 100644 --- a/slack_sdk/models/blocks/block_elements.py +++ b/slack_sdk/models/blocks/block_elements.py @@ -1679,7 +1679,7 @@ def __init__( **others: Dict, ): """ - A URL source element to reference in a task card block. + A URL source element that displays a URL source for referencing within a task card block. https://docs.slack.dev/reference/block-kit/block-elements/url-source-element Args: diff --git a/slack_sdk/models/blocks/blocks.py b/slack_sdk/models/blocks/blocks.py index 56a274c8c..bcd7efd6e 100644 --- a/slack_sdk/models/blocks/blocks.py +++ b/slack_sdk/models/blocks/blocks.py @@ -812,7 +812,7 @@ def __init__( block_id: Optional[str] = None, **others: dict, ): - """A discrete action or tool call. + """Displays a single task, representing a single action. https://docs.slack.dev/reference/block-kit/blocks/task-card-block/ Args: @@ -824,8 +824,8 @@ def __init__( title (required): Title of the task in plain text details: Details of the task in the form of a single "rich_text" entity. output: Output of the task in the form of a single "rich_text" entity. - sources: List of sources used to generate a response - status: The state of a task. Either "pending" or "in_progress" or "complete" or "error". + sources: Array of URL source elements used to generate a response. + status: The state of a task. Either "pending", "in_progress", "complete", or "error". """ super().__init__(type=self.type, block_id=block_id) show_unknown_key_warning(self, others) @@ -862,7 +862,7 @@ def __init__( block_id: Optional[str] = None, **others: dict, ): - """A collection of related tasks. + """Displays a collection of related tasks. https://docs.slack.dev/reference/block-kit/blocks/plan-block/ Args: @@ -871,7 +871,7 @@ def __init__( block_id should be unique for each message and each iteration of a message. If a message is updated, use a new block_id. title (required): Title of the plan in plain text - tasks: Details of the task in the form of a single "rich_text" entity. + tasks: A sequence of task card blocks. Each task represents a single action within the plan. """ super().__init__(type=self.type, block_id=block_id) show_unknown_key_warning(self, others) diff --git a/slack_sdk/models/messages/chunk.py b/slack_sdk/models/messages/chunk.py index 4db35621b..657d95ae4 100644 --- a/slack_sdk/models/messages/chunk.py +++ b/slack_sdk/models/messages/chunk.py @@ -82,7 +82,7 @@ def __init__( title: str, **others: Dict, ): - """An updated title of plans for task and tool calls. + """Used for displaying an updated title of a plan. https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming """ @@ -119,7 +119,7 @@ def __init__( sources: Optional[Sequence[Union[Dict, UrlSourceElement]]] = None, **others: Dict, ): - """Used for displaying tool execution progress in a timeline-style UI. + """Used for displaying task progress in a timeline-style UI. https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming """ diff --git a/slack_sdk/web/async_chat_stream.py b/slack_sdk/web/async_chat_stream.py index 1d48042f6..7348b90bc 100644 --- a/slack_sdk/web/async_chat_stream.py +++ b/slack_sdk/web/async_chat_stream.py @@ -56,7 +56,7 @@ def __init__( streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits. **kwargs: Additional arguments passed to the underlying API calls. @@ -90,7 +90,7 @@ async def append( is stopped this method cannot be called. Args: - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -146,7 +146,7 @@ async def stop( Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you diff --git a/slack_sdk/web/async_client.py b/slack_sdk/web/async_client.py index 7464b754d..e96a4f6d5 100644 --- a/slack_sdk/web/async_client.py +++ b/slack_sdk/web/async_client.py @@ -2974,7 +2974,7 @@ async def chat_stream( streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: diff --git a/slack_sdk/web/chat_stream.py b/slack_sdk/web/chat_stream.py index 575aed8c4..683859490 100644 --- a/slack_sdk/web/chat_stream.py +++ b/slack_sdk/web/chat_stream.py @@ -46,7 +46,7 @@ def __init__( streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. buffer_size: The length of markdown_text to buffer in-memory before calling a method. Increasing this value decreases the number of method calls made for the same amount of text, which is useful to avoid rate limits. **kwargs: Additional arguments passed to the underlying API calls. @@ -80,7 +80,7 @@ def append( is stopped this method cannot be called. Args: - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. **kwargs: Additional arguments passed to the underlying API calls. @@ -136,7 +136,7 @@ def stop( Args: blocks: A list of blocks that will be rendered at the bottom of the finalized message. - chunks: An array of streaming chunks that can contain either markdown text or task updates. + chunks: An array of streaming chunks. Chunks can be markdown text, plan, or task update chunks. markdown_text: Accepts message text formatted in markdown. Limit this field to 12,000 characters. This text is what will be appended to the message received so far. metadata: JSON object with event_type and event_payload fields, presented as a URL-encoded string. Metadata you diff --git a/slack_sdk/web/client.py b/slack_sdk/web/client.py index 638b4ab67..200b216ff 100644 --- a/slack_sdk/web/client.py +++ b/slack_sdk/web/client.py @@ -2964,7 +2964,7 @@ def chat_stream( streaming to channels. recipient_user_id: The encoded ID of the user to receive the streaming text. Required when streaming to channels. task_display_mode: Specifies how tasks are displayed in the message. A "timeline" displays individual tasks - interleaved with text and "plan" displays all tasks together. + with text and "plan" displays all tasks together. **kwargs: Additional arguments passed to the underlying API calls. Returns: