-
Notifications
You must be signed in to change notification settings - Fork 2
feat: improve progress event handling and UI components #43
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 all commits
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -29,6 +29,29 @@ app/workflows/ | |||||
| └── workflow-output.tsx # Streaming output panel (bottom-right) | ||||||
| ``` | ||||||
|
|
||||||
| ## Progress Event Handling | ||||||
|
|
||||||
| ```mermaid | ||||||
| sequenceDiagram | ||||||
| participant Assistant as Assistant<br/>(Message) | ||||||
| participant Context as Workflow/Network<br/>Context | ||||||
| participant Extractor as Progress Event<br/>Extractor | ||||||
| participant State as Context State | ||||||
| participant Panel as Progress<br/>Panel/Dialog | ||||||
|
|
||||||
| Assistant->>Context: Receive message with<br/>data-tool-* parts | ||||||
| Context->>Extractor: Extract progress events<br/>from message parts | ||||||
| Extractor->>Extractor: Parse stage, status,<br/>message, agentId | ||||||
| Extractor->>State: Update progressEvents<br/>and suspendPayload | ||||||
| State->>Panel: Trigger re-render with<br/>new events | ||||||
| Panel->>Panel: Group by stage &<br/>render event items | ||||||
|
|
||||||
| Note over Panel: If suspendPayload exists<br/>& status="paused" | ||||||
| Panel->>Panel: Show SuspendDialog<br/>with approve/reject | ||||||
| Panel->>Context: User clicks Approve<br/>(calls approveWorkflow) | ||||||
| Context->>Context: Clear suspendPayload<br/>Resume workflow | ||||||
|
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. issue (typo): Consider adding punctuation or a conjunction between "Clear suspendPayload" and "Resume workflow" for grammatical clarity. Right now it reads like a run-on. Consider phrasing it as
Suggested change
|
||||||
| ``` | ||||||
|
|
||||||
| ## AI SDK Integration | ||||||
|
|
||||||
| Uses `useChat` from `@ai-sdk/react` with `DefaultChatTransport` to connect to Mastra's `/workflow/:workflowId` routes: | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -260,15 +260,15 @@ export function WorkflowProvider({ | |
|
|
||
| for (const message of messages) { | ||
| if (message.role === "assistant" && message.parts !== null) { | ||
| for (const part of message.parts) { | ||
| for (const [partIndex, part] of message.parts.entries()) { | ||
| // Handle workflow progress events (data-workflow, data-tool-workflow) | ||
| if (part.type === "data-workflow" || part.type === "data-tool-workflow") { | ||
| const workflowPart = part as { data?: { text?: string; status?: string; stepId?: string } } | ||
| const eventData = workflowPart.data | ||
|
|
||
| if (eventData && eventData.text !== null && typeof eventData.text === "string" && eventData.text.trim()) { | ||
| allProgressEvents.push({ | ||
| id: `${message.id}-${part.type}-${Date.now()}`, | ||
| id: `${message.id}-${part.type}-${partIndex}`, | ||
|
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. question (bug_risk): Deterministic IDs based on partIndex may collide across workflow progress updates. Using |
||
| stage: part.type.replace("data-", "").replace("-tool-", " "), | ||
| status: "in-progress", | ||
| message: eventData.text, | ||
|
|
@@ -303,7 +303,7 @@ export function WorkflowProvider({ | |
| if (eventData && eventData.status !== null && typeof eventData.status === "string" && | ||
| (eventData.status === "in-progress" || eventData.status === "done" || eventData.status === "error")) { | ||
| allProgressEvents.push({ | ||
| id: `${message.id}-${part.type}-${Date.now()}`, | ||
| id: `${message.id}-${part.type}-${partIndex}`, | ||
| stage: eventData.stage ?? "workflow", | ||
| status: eventData.status, | ||
| message: eventData.message ?? `${part.type} ${eventData.status}`, | ||
|
|
||
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.
question (bug_risk): Using partIndex instead of Date.now() might create duplicate IDs if messages are reprocessed or parts change order.
This makes IDs deterministic, but also means reprocessed messages or reordered/updated parts can emit progress events with the same ID. If these IDs are used as keys or for de-duplication, that can introduce subtle bugs. Consider adding another stable discriminator (e.g., a per-event sequence,
eventData.status, or some unique field from the part) to keep IDs both deterministic and distinct across logically separate events.