Skip to content

feat(web-api): expose public ts property on ChatStream#2611

Merged
srtaalej merged 4 commits into
mainfrom
ale-make-ts-public
Jun 1, 2026
Merged

feat(web-api): expose public ts property on ChatStream#2611
srtaalej merged 4 commits into
mainfrom
ale-make-ts-public

Conversation

@srtaalej
Copy link
Copy Markdown
Contributor

Summary

This PR adds a public read-only ts getter to ChatStreamer, enabling users to call chat.update as a fallback when the server closes a stream due to undocumented timeouts.

Background

When Slack's server-side timeout kills a stream, both chat.appendStream and chat.stopStream return message_not_in_streaming_state. The message still exists but is stuck as a broken pill in the UI. The only recovery path is chat.update({ ts: ... }), but ts was previously a private field (streamTs).

Changes

  • packages/web-api/src/chat-stream.ts: Added ts getter (read-only, returns string | undefined)
  • packages/web-api/src/WebClient.test.ts: Added test verifying ts is undefined before flush and set after
code snippet
  import { WebClient } from '@slack/web-api';

  const client = new WebClient(token);

  async function sendStreaming(channel: string, threadTs: string, teamId: string, userId: string, 
  chunks: AsyncIterable<string>) {
    const streamer = client.chatStream({
      channel,
      thread_ts: threadTs,
      recipient_team_id: teamId,
      recipient_user_id: userId,
    });

    let fullText = '';
    let streamAlive = true;

    for await (const chunk of chunks) {
      fullText += chunk;

      if (streamAlive) {
        try {
          await streamer.append({ markdown_text: chunk });
        } catch (error) {
          if (error.data?.error === 'message_not_in_streaming_state') {
            streamAlive = false;
          } else {
            throw error;
          }
        }
      }

      if (!streamAlive) {
        await client.chat.update({ channel, ts: streamer.ts, text: fullText });
      }
    }

    if (streamAlive) {
      await streamer.stop();
    } else {
      await client.chat.update({ channel, ts: streamer.ts, text: fullText });
    }
  }

Requirements

@srtaalej srtaalej self-assigned this May 29, 2026
@srtaalej srtaalej requested a review from a team as a code owner May 29, 2026 23:02
@srtaalej srtaalej added semver:minor enhancement M-T: A feature request for new functionality pkg:web-api applies to `@slack/web-api` labels May 29, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 29, 2026

🦋 Changeset detected

Latest commit: d12828f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@slack/web-api Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.88%. Comparing base (f430ae8) to head (d12828f).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2611      +/-   ##
==========================================
+ Coverage   88.86%   88.88%   +0.01%     
==========================================
  Files          62       62              
  Lines       10230    10239       +9     
  Branches      450      451       +1     
==========================================
+ Hits         9091     9101      +10     
+ Misses       1117     1116       -1     
  Partials       22       22              
Flag Coverage Δ
cli-hooks 88.88% <100.00%> (+0.01%) ⬆️
cli-test 88.88% <100.00%> (+0.01%) ⬆️
logger 88.88% <100.00%> (+0.01%) ⬆️
oauth 88.88% <100.00%> (+0.01%) ⬆️
socket-mode 88.88% <100.00%> (+0.01%) ⬆️
web-api 88.88% <100.00%> (+0.01%) ⬆️
webhook 88.88% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@WilliamBergamin WilliamBergamin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work 💯 changes seem good to me! I left one addressable non blocking comment

* stream expires server-side.
* @see {@link https://docs.slack.dev/reference/methods/chat.update}
*/
get ts(): string | undefined {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is one of the rare times we use the get operator in this project 🤔 I think it makes sense to use it here, it should give us the flexibly to add a setter if we ever need to and exposes the property as readonly

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes i agree - best to keep it readonly!

Comment thread packages/web-api/src/chat-stream.ts Outdated
srtaalej and others added 2 commits June 1, 2026 10:45
@srtaalej srtaalej merged commit 2085900 into main Jun 1, 2026
12 checks passed
@srtaalej srtaalej deleted the ale-make-ts-public branch June 1, 2026 16:43
@zimeg zimeg added this to the web-api@next milestone Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement M-T: A feature request for new functionality pkg:web-api applies to `@slack/web-api` semver:minor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants