diff --git a/packages/web-api/src/WebClient.spec.ts b/packages/web-api/src/WebClient.spec.ts index 15dcb3fbe..c0c326297 100644 --- a/packages/web-api/src/WebClient.spec.ts +++ b/packages/web-api/src/WebClient.spec.ts @@ -1228,7 +1228,11 @@ describe('WebClient', () => { ok: true, ts: '123.123', }) - .post('/api/chat.stopStream', { channel: 'C0123456789', ts: '123.123', markdown_text: 'nice!' }) + .post('/api/chat.stopStream', { + channel: 'C0123456789', + ts: '123.123', + chunks: JSON.stringify([{ type: 'markdown_text', text: 'nice!' }]), + }) .reply(200, { ok: true, }); @@ -1279,7 +1283,7 @@ describe('WebClient', () => { const scope = nock('https://slack.com') .post('/api/chat.startStream', { channel: 'C0123456789', - markdown_text: '**this messag', + chunks: JSON.stringify([{ type: 'markdown_text', text: '**this messag' }]), recipient_team_id: 'T0123456789', recipient_user_id: 'U0123456789', thread_ts: '123.000', @@ -1290,7 +1294,7 @@ describe('WebClient', () => { }) .post('/api/chat.appendStream', { channel: 'C0123456789', - markdown_text: 'e is bold!', + chunks: JSON.stringify([{ type: 'markdown_text', text: 'e is bold!' }]), token: 'xoxb-updated-1', ts: '123.123', }) @@ -1300,7 +1304,7 @@ describe('WebClient', () => { .post('/api/chat.stopStream', { blocks: JSON.stringify([contextActionsBlock]), channel: 'C0123456789', - markdown_text: '**', + chunks: JSON.stringify([{ type: 'markdown_text', text: '**' }]), token: 'xoxb-updated-2', ts: '123.123', }) @@ -1370,7 +1374,11 @@ describe('WebClient', () => { ok: true, ts: '123.123', }) - .post('/api/chat.stopStream', { channel: 'C0123456789', ts: '123.123', markdown_text: 'nice!' }) + .post('/api/chat.stopStream', { + channel: 'C0123456789', + ts: '123.123', + chunks: JSON.stringify([{ type: 'markdown_text', text: 'nice!' }]), + }) .reply(200, { ok: true, }); diff --git a/packages/web-api/src/chat-stream.ts b/packages/web-api/src/chat-stream.ts index 695100b14..779aee80d 100644 --- a/packages/web-api/src/chat-stream.ts +++ b/packages/web-api/src/chat-stream.ts @@ -1,4 +1,5 @@ import type { Logger } from '@slack/logger'; +import type { AnyChunk } from '@slack/types'; import type { ChatAppendStreamArguments, ChatStartStreamArguments, ChatStopStreamArguments } from './types/request'; import type { ChatAppendStreamResponse, ChatStartStreamResponse, ChatStopStreamResponse } from './types/response'; import type WebClient from './WebClient'; @@ -89,8 +90,11 @@ export class ChatStreamer { if (args.token) { this.token = args.token; } - this.buffer += args.markdown_text; - if (this.buffer.length >= this.options.buffer_size) { + if (args?.markdown_text) { + this.buffer += args.markdown_text; + args.markdown_text = undefined; + } + if (this.buffer.length >= this.options.buffer_size || args?.chunks) { return await this.flushBuffer(args); } const details = { @@ -132,6 +136,7 @@ export class ChatStreamer { } if (args?.markdown_text) { this.buffer += args.markdown_text; + args.markdown_text = undefined; } if (!this.streamTs) { const response = await this.client.chat.startStream({ @@ -144,12 +149,25 @@ export class ChatStreamer { this.streamTs = response.ts; this.state = 'in_progress'; } + + const flushings: AnyChunk[] = []; + + if (this.buffer.length > 0) { + flushings.push({ + type: 'markdown_text', + text: this.buffer, + }); + } + if (args?.chunks) { + flushings.push(...args.chunks); + } + const response = await this.client.chat.stopStream({ token: this.token, channel: this.streamArgs.channel, ts: this.streamTs, + chunks: flushings, ...args, - markdown_text: this.buffer, }); this.state = 'completed'; return response; @@ -158,12 +176,24 @@ export class ChatStreamer { private async flushBuffer( args: Omit, ): Promise { + const flushings: AnyChunk[] = []; + + if (this.buffer.length > 0) { + flushings.push({ + type: 'markdown_text', + text: this.buffer, + }); + } + if (args?.chunks) { + flushings.push(...args.chunks); + } + if (!this.streamTs) { const response = await this.client.chat.startStream({ ...this.streamArgs, token: this.token, + chunks: flushings, ...args, - markdown_text: this.buffer, }); this.buffer = ''; this.streamTs = response.ts; @@ -174,8 +204,8 @@ export class ChatStreamer { token: this.token, channel: this.streamArgs.channel, ts: this.streamTs, + chunks: flushings, ...args, - markdown_text: this.buffer, }); this.buffer = ''; return response; diff --git a/packages/web-api/test/types/methods/chat.test-d.ts b/packages/web-api/test/types/methods/chat.test-d.ts index 419ec7486..a73e40249 100644 --- a/packages/web-api/test/types/methods/chat.test-d.ts +++ b/packages/web-api/test/types/methods/chat.test-d.ts @@ -676,7 +676,23 @@ expectAssignable>([ { channel: 'C1234', thread_ts: '1234.56', - markdown_text: 'hello', + 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...', + }, + ], recipient_team_id: 'T1234', recipient_user_id: 'U1234', },