Skip to content

Conversation

@srtaalej
Copy link
Contributor

@srtaalej srtaalej commented Jan 11, 2026

Summary

This PR introduces the chunks argument to the following methods:

chat.startStream
chat.appendStream
chat.stopStream

⚠️ This feature is experimental at the moment!

Code Snippet
const stream = new ChatStreamer(client, client.logger, {
      channel: CHANNEL_ID,
      thread_ts: threadTs,
      recipient_team_id: 'T09EX3FS2J3',
      recipient_user_id: 'U09G4FG3TRN',
    }, { buffer_size: 1 });

    await stream.append({
      chunks: [
        {
          type: 'markdown_text',
          text: '**Hello!** I am starting to process your request...\n\n'
        }]
    });
   
    await stream.append({
      chunks: [
        {
          type: 'plan_update',
          title: ''\nProcessing tasks...\n,
        },
        {
          type: 'task_update',
          id: 'task-1',
          title: 'Fetching data from API',
          status: 'complete',
          output: 'Successfully retrieved 42 records',
        },
        {
          type: 'task_update',
          id: 'task-2',
          title: 'Processing results',
          status: 'pending',
        },
      ],
    });
    
    await stream.append({
      chunks: [
        {
          type: 'task_update',
          id: 'task-2',
          title: 'Processing results',
          status: 'complete',
          output: 'Analysis complete!',
          sources: [
            {
              type: 'url',
              url: 'https://example.com/docs',
              text: 'Documentation',
            },
            {
              type: 'url',
              url: 'https://example.com/api',
              text: 'API Reference',
              icon_url: 'https://example.com/favicon.ico',
            },
          ],
        },
      ],
    });
   
     await stream.append({
      chunks: [
        {
          type: 'markdown_text',
          text: 'Hi Ale!\n\n',
        },
        {
          type: 'markdown_text',
          text: 'Here is what I found:\n\n',
        },
        {
          type: 'markdown_text',
          text: '- Item 1: *Important information*\n',
        },
        {
          type: 'markdown_text',
          text: '- Item 2: `Some code snippet`\n',
        },
      ],
    });

   
    await stream.stop({
      chunks: [
        {
          type: 'markdown_text',
          text: '\n\n---\n\n✅ **All tasks completed successfully!**\n',
        },
        {
          type: 'markdown_text',
          text: 'Thank you for using the streaming API with chunks.',
        },
      ],
    });

Requirements (place an x in each [ ])

@codecov
Copy link

codecov bot commented Jan 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.09%. Comparing base (b44cee1) to head (81140cc).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@                     Coverage Diff                      @@
##           feat-ai-apps-thinking-steps    #2467   +/-   ##
============================================================
  Coverage                        93.09%   93.09%           
============================================================
  Files                               40       40           
  Lines                            11240    11240           
  Branches                           713      713           
============================================================
  Hits                             10464    10464           
  Misses                             764      764           
  Partials                            12       12           
Flag Coverage Δ
cli-hooks 95.23% <ø> (ø)
cli-test 94.79% <ø> (ø)
webhook 96.66% <ø> (ø)

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.

@srtaalej srtaalej self-assigned this Jan 11, 2026
@srtaalej srtaalej added the enhancement M-T: A feature request for new functionality label Jan 11, 2026
@srtaalej srtaalej changed the base branch from main to feat-ai-apps-thinking-steps January 12, 2026 19:51
@srtaalej srtaalej marked this pull request as ready for review January 15, 2026 22:48
@srtaalej srtaalej requested review from a team as code owners January 15, 2026 22:48
Copy link
Member

@zimeg zimeg left a comment

Choose a reason for hiding this comment

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

@srtaalej Woooo! This'll be nice to land soon but I'm leaving a few comments on changes perhaps to make beforehand.

The tests are most confusing to me since I think all changes are contained in this PR... Am looking into this separate but do let me know if questions on these comments appear please!

export * from './block-kit/composition-objects';
export * from './block-kit/extensions';
export * from './calls';
export * from './chunk';
Copy link
Member

Choose a reason for hiding this comment

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

🧪 note: Right now I notice CI is failing for a missing export... Am curious if this is specific to our testing workflows or this PR, but will explore this adjacent!

const chunkObj = chunk as Record<string, unknown>;

if (!('type' in chunkObj) || typeof chunkObj.type !== 'string') {
console.warn('Unknown chunk detected and skipped (missing type)', chunk);
Copy link
Member

Choose a reason for hiding this comment

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

🪵 issue: We should prefer the @slack/logger package for these outputs!

Comment on lines +82 to +88
if(type === 'plan_update') {
if (typeof chunkObj.title === 'string') {
return chunkObj as unknown as PlanUpdateChunk;
}
console.warn('Invalid PlanUpdateChunk (missing title property)', chunk);
return null;
}
Copy link
Member

Choose a reason for hiding this comment

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

⚠️ suggestion: It might be preferable to let the API return an error for invalid chunks since these limitations might change in the future?

typeof taskChunk.status === 'string' &&
['pending', 'in_progress', 'complete', 'error'].includes(taskChunk.status)
) {
return chunkObj as unknown as TaskUpdateChunk;
Copy link
Member

Choose a reason for hiding this comment

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

👾 thought: Morphing to unknown then a type might have an alternative with type "narrowing"! IIRC @WilliamBergamin is most familiar with that approach and has shared these docs with me at a point:

📚 https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-in-operator-narrowing

{
channel: 'C1234',
ts: '1234.56',
markdown_text: 'hello',
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
markdown_text: 'hello',

🪓 issue: Let's remove this to match expected API behavior!

Comment on lines +686 to +702
chunks: [
{
type: 'markdown_text',
text: 'Hello world',
},
{
type: 'plan_update',
title: 'Analyzing request',
},
{
type: 'task_update',
id: 'task-1',
title: 'Processing request',
status: 'in_progress',
details: 'Working on it...',
},
],
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
chunks: [
{
type: 'markdown_text',
text: 'Hello world',
},
{
type: 'plan_update',
title: 'Analyzing request',
},
{
type: 'task_update',
id: 'task-1',
title: 'Processing request',
status: 'in_progress',
details: 'Working on it...',
},
],

🪓 issue: Similar to the above, I'm not sure if we should error in typescript if both "markdown_text" and "chunks" are provided, but let's not showcase that here IMHO

@zimeg zimeg added pkg:web-api applies to `@slack/web-api` pkg:types applies to `@slack/types` labels Jan 21, 2026
return null;
}

if(type === 'plan_update') {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if(type === 'plan_update') {
if (type === 'plan_update') {

👁️‍🗨️ issue: This is causing the linter to error and packages to not build as expected!

src/chunk.ts format ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  × Formatter would have printed the following content:
  
    82 │ ··if·(type·===·'plan_update')·{
Checked 48 files in 26ms. No fixes applied.
       │     +                          

Found 1 error.
check ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

🔗 https://github.com/slackapi/node-slack-sdk/actions/runs/21079717525/job/60630237979#step:9:13

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:types applies to `@slack/types` pkg:web-api applies to `@slack/web-api` semver:minor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants