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 @@
*,
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 @@
"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 @@
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 @@
"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 @@
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 @@
"markdown_text": markdown_text,
"blocks": blocks,
"metadata": metadata,
+ "chunks": chunks,
}
)
_parse_web_class_objects(kwargs)
@@ -3060,6 +3070,7 @@
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 @@
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 @@
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
-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
+
+
+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 @@
@@ -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
-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 @@
*,
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 @@
"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 @@
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 @@
"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 @@
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 @@
"markdown_text": markdown_text,
"blocks": blocks,
"metadata": metadata,
+ "chunks": chunks,
}
)
_parse_web_class_objects(kwargs)
@@ -10080,7 +10090,7 @@ Methods
-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 @@
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
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
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
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
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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: