Skip to content

Commit 8d237be

Browse files
srtaalejmwbrookszimeg
authored
feat: accept chunks as arguments to chat stream helper (#2470)
Co-authored-by: Michael Brooks <mbrooks@slack-corp.com> Co-authored-by: Eden Zimbelman <eden.zimbelman@salesforce.com>
1 parent f4d678a commit 8d237be

3 files changed

Lines changed: 71 additions & 28 deletions

File tree

packages/web-api/src/WebClient.spec.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,11 @@ describe('WebClient', () => {
12281228
ok: true,
12291229
ts: '123.123',
12301230
})
1231-
.post('/api/chat.stopStream', { channel: 'C0123456789', ts: '123.123', markdown_text: 'nice!' })
1231+
.post('/api/chat.stopStream', {
1232+
channel: 'C0123456789',
1233+
ts: '123.123',
1234+
chunks: JSON.stringify([{ type: 'markdown_text', text: 'nice!' }]),
1235+
})
12321236
.reply(200, {
12331237
ok: true,
12341238
});
@@ -1279,7 +1283,7 @@ describe('WebClient', () => {
12791283
const scope = nock('https://slack.com')
12801284
.post('/api/chat.startStream', {
12811285
channel: 'C0123456789',
1282-
markdown_text: '**this messag',
1286+
chunks: JSON.stringify([{ type: 'markdown_text', text: '**this messag' }]),
12831287
recipient_team_id: 'T0123456789',
12841288
recipient_user_id: 'U0123456789',
12851289
thread_ts: '123.000',
@@ -1290,7 +1294,7 @@ describe('WebClient', () => {
12901294
})
12911295
.post('/api/chat.appendStream', {
12921296
channel: 'C0123456789',
1293-
markdown_text: 'e is bold!',
1297+
chunks: JSON.stringify([{ type: 'markdown_text', text: 'e is bold!' }]),
12941298
token: 'xoxb-updated-1',
12951299
ts: '123.123',
12961300
})
@@ -1300,7 +1304,7 @@ describe('WebClient', () => {
13001304
.post('/api/chat.stopStream', {
13011305
blocks: JSON.stringify([contextActionsBlock]),
13021306
channel: 'C0123456789',
1303-
markdown_text: '**',
1307+
chunks: JSON.stringify([{ type: 'markdown_text', text: '**' }]),
13041308
token: 'xoxb-updated-2',
13051309
ts: '123.123',
13061310
})
@@ -1370,7 +1374,11 @@ describe('WebClient', () => {
13701374
ok: true,
13711375
ts: '123.123',
13721376
})
1373-
.post('/api/chat.stopStream', { channel: 'C0123456789', ts: '123.123', markdown_text: 'nice!' })
1377+
.post('/api/chat.stopStream', {
1378+
channel: 'C0123456789',
1379+
ts: '123.123',
1380+
chunks: JSON.stringify([{ type: 'markdown_text', text: 'nice!' }]),
1381+
})
13741382
.reply(200, {
13751383
ok: true,
13761384
});

packages/web-api/src/chat-stream.ts

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Logger } from '@slack/logger';
2+
import type { AnyChunk } from '@slack/types';
23
import type { ChatAppendStreamArguments, ChatStartStreamArguments, ChatStopStreamArguments } from './types/request';
34
import type { ChatAppendStreamResponse, ChatStartStreamResponse, ChatStopStreamResponse } from './types/response';
45
import type WebClient from './WebClient';
@@ -13,19 +14,12 @@ export interface ChatStreamerOptions {
1314

1415
export class ChatStreamer {
1516
private buffer = '';
16-
1717
private client: WebClient;
18-
1918
private logger: Logger;
20-
2119
private options: Required<ChatStreamerOptions>;
22-
2320
private state: 'starting' | 'in_progress' | 'completed';
24-
2521
private streamArgs: ChatStartStreamArguments;
26-
2722
private streamTs: string | undefined;
28-
2923
private token: string | undefined;
3024

3125
/**
@@ -86,12 +80,15 @@ export class ChatStreamer {
8680
if (this.state === 'completed') {
8781
throw new Error(`failed to append stream: stream state is ${this.state}`);
8882
}
89-
if (args.token) {
90-
this.token = args.token;
83+
const { markdown_text, chunks, ...opts } = args;
84+
if (opts.token) {
85+
this.token = opts.token;
9186
}
92-
this.buffer += args.markdown_text;
93-
if (this.buffer.length >= this.options.buffer_size) {
94-
return await this.flushBuffer(args);
87+
if (markdown_text) {
88+
this.buffer += markdown_text;
89+
}
90+
if (this.buffer.length >= this.options.buffer_size || chunks) {
91+
return await this.flushBuffer({ chunks, ...opts });
9592
}
9693
const details = {
9794
bufferLength: this.buffer.length,
@@ -127,11 +124,12 @@ export class ChatStreamer {
127124
if (this.state === 'completed') {
128125
throw new Error(`failed to stop stream: stream state is ${this.state}`);
129126
}
130-
if (args?.token) {
131-
this.token = args.token;
127+
const { markdown_text, chunks, ...opts } = args ?? {};
128+
if (opts.token) {
129+
this.token = opts.token;
132130
}
133-
if (args?.markdown_text) {
134-
this.buffer += args.markdown_text;
131+
if (markdown_text) {
132+
this.buffer += markdown_text;
135133
}
136134
if (!this.streamTs) {
137135
const response = await this.client.chat.startStream({
@@ -144,12 +142,22 @@ export class ChatStreamer {
144142
this.streamTs = response.ts;
145143
this.state = 'in_progress';
146144
}
145+
const chunksToFlush: AnyChunk[] = [];
146+
if (this.buffer.length > 0) {
147+
chunksToFlush.push({
148+
type: 'markdown_text',
149+
text: this.buffer,
150+
});
151+
}
152+
if (chunks) {
153+
chunksToFlush.push(...chunks);
154+
}
147155
const response = await this.client.chat.stopStream({
148156
token: this.token,
149157
channel: this.streamArgs.channel,
150158
ts: this.streamTs,
151-
...args,
152-
markdown_text: this.buffer,
159+
chunks: chunksToFlush,
160+
...opts,
153161
});
154162
this.state = 'completed';
155163
return response;
@@ -158,12 +166,23 @@ export class ChatStreamer {
158166
private async flushBuffer(
159167
args: Omit<ChatStartStreamArguments | ChatAppendStreamArguments, 'channel' | 'ts'>,
160168
): Promise<ChatStartStreamResponse | ChatAppendStreamResponse> {
169+
const { chunks, ...opts } = args ?? {};
170+
const chunksToFlush: AnyChunk[] = [];
171+
if (this.buffer.length > 0) {
172+
chunksToFlush.push({
173+
type: 'markdown_text',
174+
text: this.buffer,
175+
});
176+
}
177+
if (chunks) {
178+
chunksToFlush.push(...chunks);
179+
}
161180
if (!this.streamTs) {
162181
const response = await this.client.chat.startStream({
163182
...this.streamArgs,
164183
token: this.token,
165-
...args,
166-
markdown_text: this.buffer,
184+
chunks: chunksToFlush,
185+
...opts,
167186
});
168187
this.buffer = '';
169188
this.streamTs = response.ts;
@@ -174,8 +193,8 @@ export class ChatStreamer {
174193
token: this.token,
175194
channel: this.streamArgs.channel,
176195
ts: this.streamTs,
177-
...args,
178-
markdown_text: this.buffer,
196+
chunks: chunksToFlush,
197+
...opts,
179198
});
180199
this.buffer = '';
181200
return response;

packages/web-api/test/types/methods/chat.test-d.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,23 @@ expectAssignable<Parameters<typeof web.chat.startStream>>([
676676
{
677677
channel: 'C1234',
678678
thread_ts: '1234.56',
679-
markdown_text: 'hello',
679+
chunks: [
680+
{
681+
type: 'markdown_text',
682+
text: 'Hello world',
683+
},
684+
{
685+
type: 'plan_update',
686+
title: 'Analyzing request',
687+
},
688+
{
689+
type: 'task_update',
690+
id: 'task-1',
691+
title: 'Processing request',
692+
status: 'in_progress',
693+
details: 'Working on it...',
694+
},
695+
],
680696
recipient_team_id: 'T1234',
681697
recipient_user_id: 'U1234',
682698
},

0 commit comments

Comments
 (0)