-
Notifications
You must be signed in to change notification settings - Fork 678
feat: accept chunks as arguments to chat.{start,append,stop}Stream methods #2467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat-ai-apps-thinking-steps
Are you sure you want to change the base?
Changes from all commits
e3d7b9b
2601199
160cfb7
81140cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,106 @@ | ||||||
| /** | ||||||
| * Base interface for streaming message chunks. | ||||||
| * https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming | ||||||
| */ | ||||||
| export interface Chunk { | ||||||
| type: string; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Used for streaming text content with markdown formatting support. | ||||||
| * https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming | ||||||
| */ | ||||||
| export interface MarkdownTextChunk extends Chunk { | ||||||
| type: 'markdown_text'; | ||||||
| text: string; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * URL source for task update chunks. | ||||||
| */ | ||||||
| export interface URLSource { | ||||||
| type: 'url'; | ||||||
| url: string; | ||||||
| text: string; | ||||||
| icon_url?: string; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * An updated title of plans for task and tool calls. | ||||||
| * https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming | ||||||
| */ | ||||||
| export interface PlanUpdateChunk extends Chunk { | ||||||
| type: 'plan_update'; | ||||||
| title: string; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Used for displaying tool execution progress in a timeline-style UI. | ||||||
| * https://docs.slack.dev/messaging/sending-and-scheduling-messages#text-streaming | ||||||
| */ | ||||||
| export interface TaskUpdateChunk extends Chunk { | ||||||
| type: 'task_update'; | ||||||
| id: string; | ||||||
| title: string; | ||||||
| status: 'pending' | 'in_progress' | 'complete' | 'error'; | ||||||
| details?: string; | ||||||
| output?: string; | ||||||
| sources?: URLSource[]; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Union type of all possible chunk types | ||||||
| */ | ||||||
| export type AnyChunk = MarkdownTextChunk | PlanUpdateChunk | TaskUpdateChunk; | ||||||
|
|
||||||
| /** | ||||||
| * Parse a chunk object and return the appropriate typed chunk. | ||||||
| * Returns null if the chunk is invalid or unknown. | ||||||
| */ | ||||||
| export function parseChunk(chunk: unknown): AnyChunk | null { | ||||||
| if (!chunk || typeof chunk !== 'object') { | ||||||
| return null; | ||||||
| } | ||||||
|
|
||||||
| 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); | ||||||
| return null; | ||||||
| } | ||||||
|
|
||||||
| const { type } = chunkObj; | ||||||
|
|
||||||
| if (type === 'markdown_text') { | ||||||
| if (typeof chunkObj.text === 'string') { | ||||||
| return chunkObj as unknown as MarkdownTextChunk; | ||||||
| } | ||||||
| console.warn('Invalid MarkdownTextChunk (missing text property)', chunk); | ||||||
| return null; | ||||||
| } | ||||||
|
|
||||||
| if(type === 'plan_update') { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
👁️🗨️ issue: This is causing the linter to error and packages to not build as expected! 🔗 https://github.com/slackapi/node-slack-sdk/actions/runs/21079717525/job/60630237979#step:9:13 |
||||||
| if (typeof chunkObj.title === 'string') { | ||||||
| return chunkObj as unknown as PlanUpdateChunk; | ||||||
| } | ||||||
| console.warn('Invalid PlanUpdateChunk (missing title property)', chunk); | ||||||
| return null; | ||||||
| } | ||||||
|
Comment on lines
+82
to
+88
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
|
|
||||||
| if (type === 'task_update') { | ||||||
| const taskChunk = chunkObj as Partial<TaskUpdateChunk>; | ||||||
| if ( | ||||||
| typeof taskChunk.id === 'string' && | ||||||
| typeof taskChunk.title === 'string' && | ||||||
| typeof taskChunk.status === 'string' && | ||||||
| ['pending', 'in_progress', 'complete', 'error'].includes(taskChunk.status) | ||||||
| ) { | ||||||
| return chunkObj as unknown as TaskUpdateChunk; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👾 thought: Morphing to 📚 https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-in-operator-narrowing |
||||||
| } | ||||||
| console.warn('Invalid TaskUpdateChunk (missing required properties)', chunk); | ||||||
| return null; | ||||||
| } | ||||||
|
|
||||||
| console.warn(`Unknown chunk type detected and skipped: ${type}`, chunk); | ||||||
| return null; | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ export * from './block-kit/blocks'; | |
| export * from './block-kit/composition-objects'; | ||
| export * from './block-kit/extensions'; | ||
| export * from './calls'; | ||
| export * from './chunk'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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! |
||
| export * from './dialog'; | ||
| export * from './events'; | ||
| export * from './message-attachments'; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -32,6 +32,30 @@ expectAssignable<Parameters<typeof web.chat.appendStream>>([ | |||||||||||||||||||||||||||||||||||
| markdown_text: 'hello', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||
| expectAssignable<Parameters<typeof web.chat.appendStream>>([ | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| channel: 'C1234', | ||||||||||||||||||||||||||||||||||||
| ts: '1234.56', | ||||||||||||||||||||||||||||||||||||
| markdown_text: 'hello', | ||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
🪓 issue: Let's remove this to match expected API behavior! |
||||||||||||||||||||||||||||||||||||
| 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...', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // chat.delete | ||||||||||||||||||||||||||||||||||||
| // -- sad path | ||||||||||||||||||||||||||||||||||||
|
|
@@ -631,11 +655,51 @@ expectAssignable<Parameters<typeof web.chat.startStream>>([ | |||||||||||||||||||||||||||||||||||
| markdown_text: 'hello', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||
| expectAssignable<Parameters<typeof web.chat.startStream>>([ | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| channel: 'C1234', | ||||||||||||||||||||||||||||||||||||
| thread_ts: '1234.56', | ||||||||||||||||||||||||||||||||||||
| 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...', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||
| expectAssignable<Parameters<typeof web.chat.startStream>>([ | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| 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...', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+686
to
+702
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
🪓 issue: Similar to the above, I'm not sure if we should error in |
||||||||||||||||||||||||||||||||||||
| recipient_team_id: 'T1234', | ||||||||||||||||||||||||||||||||||||
| recipient_user_id: 'U1234', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
|
|
@@ -670,6 +734,30 @@ expectAssignable<Parameters<typeof web.chat.stopStream>>([ | |||||||||||||||||||||||||||||||||||
| blocks: [], | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||
| expectAssignable<Parameters<typeof web.chat.stopStream>>([ | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| channel: 'C1234', | ||||||||||||||||||||||||||||||||||||
| ts: '1234.56', | ||||||||||||||||||||||||||||||||||||
| 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...', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||
| blocks: [], | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // chat.unfurl | ||||||||||||||||||||||||||||||||||||
| // -- sad path | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
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/loggerpackage for these outputs!