-
Notifications
You must be signed in to change notification settings - Fork 674
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
Changes from 8 commits
e3d7b9b
2601199
160cfb7
81140cc
dbca9c9
1d480f6
e6ece09
77d3986
c6c52c8
1486d3f
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,109 @@ | ||
| import { ConsoleLogger, LogLevel } from '@slack/logger'; | ||
|
|
||
| const logger = new ConsoleLogger(); | ||
| logger.setLevel(LogLevel.DEBUG); | ||
|
|
||
| /** | ||
| * 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 { | ||
|
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. suggestion: This is a nice implementation, but I don't think we need it for the
Contributor
Author
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. ahh okay thank you for the clarification 🙌 |
||
| if (!chunk || typeof chunk !== 'object') { | ||
| return null; | ||
| } | ||
|
|
||
| if (!('type' in chunk) || typeof chunk.type !== 'string') { | ||
| logger.debug('Unknown chunk detected and skipped (missing type)', chunk); | ||
| return null; | ||
| } | ||
|
|
||
| const type = chunk.type; | ||
|
|
||
| if (type === 'markdown_text') { | ||
| if ('text' in chunk && typeof chunk.text === 'string') { | ||
| return chunk as MarkdownTextChunk; | ||
| } | ||
| logger.debug('Invalid MarkdownTextChunk (missing text property)', chunk); | ||
| return null; | ||
| } | ||
|
|
||
| if (type === 'plan_update') { | ||
| if ('title' in chunk && typeof chunk.title === 'string') { | ||
| return chunk as PlanUpdateChunk; | ||
| } | ||
| logger.debug('Invalid PlanUpdateChunk (missing title property)', chunk); | ||
| return null; | ||
| } | ||
|
|
||
| if (type === 'task_update') { | ||
| const taskChunk = chunk 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 chunk as TaskUpdateChunk; | ||
| } | ||
| logger.debug('Invalid TaskUpdateChunk (missing required properties)', chunk); | ||
| return null; | ||
| } | ||
|
|
||
| logger.debug(`Unknown chunk type detected and skipped: ${type}`, chunk); | ||
| return null; | ||
| } | ||
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.
suggestion: If we remove the
parseChunkmethod, then we can also remove this dependency 🎉