Add prompt_id support to progress_text WS messages (#9002)

## Summary

Add frontend support for `prompt_id` in `progress_text` binary WS
messages, enabling parallel workflow execution to route progress text to
the correct active prompt.

Backend PR: https://github.com/Comfy-Org/ComfyUI/pull/12540

## Changes

- Advertise `supports_progress_text_metadata` in client feature flags
- Decode `prompt_id` from new binary format when flag is active
- Add optional `prompt_id` to `zProgressTextWsMessage` schema
- Filter `progress_text` events by `activePromptId` — skip messages for
non-active prompts

## Deployment

Can be deployed independently in any order — feature flag negotiation
ensures graceful degradation.

Part of COM-12671

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9002-Add-prompt_id-support-to-progress_text-WS-messages-30d6d73d365081acabbcdac939e0c751)
by [Unito](https://www.unito.io)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Progress text updates can include optional metadata so richer context
is available.
* **Bug Fixes / Improvements**
* Progress updates are now filtered to show only the currently active
prompt, reducing cross-talk from concurrent operations and improving
update accuracy.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Christian Byrne
2026-03-13 07:55:05 -07:00
committed by GitHub
parent 31a33a0ba2
commit de866a15d2
4 changed files with 47 additions and 11 deletions

View File

@@ -1,4 +1,5 @@
{
"supports_preview_metadata": true,
"supports_manager_v4_ui": true
"supports_manager_v4_ui": true,
"supports_progress_text_metadata": true
}

View File

@@ -112,7 +112,8 @@ const zExecutionErrorWsMessage = zExecutionWsMessageBase.extend({
const zProgressTextWsMessage = z.object({
nodeId: zNodeId,
text: z.string()
text: z.string(),
prompt_id: z.string().optional()
})
const zNotificationWsMessage = z.object({

View File

@@ -623,15 +623,44 @@ export class ComfyApi extends EventTarget {
let imageMime
switch (eventType) {
case 3:
const decoder = new TextDecoder()
const data = event.data.slice(4)
const nodeIdLength = view.getUint32(4)
this.dispatchCustomEvent('progress_text', {
nodeId: decoder.decode(data.slice(4, 4 + nodeIdLength)),
text: decoder.decode(data.slice(4 + nodeIdLength))
})
case 3: {
try {
const decoder3 = new TextDecoder()
const rawData = event.data.slice(4)
const rawView = new DataView(rawData)
let offset = 0
let promptId: string | undefined
if (
this.getClientFeatureFlags()?.supports_progress_text_metadata
) {
const promptIdLength = rawView.getUint32(offset)
offset += 4
promptId = decoder3.decode(
rawData.slice(offset, offset + promptIdLength)
)
offset += promptIdLength
}
const nodeIdLength = rawView.getUint32(offset)
offset += 4
const nodeId = decoder3.decode(
rawData.slice(offset, offset + nodeIdLength)
)
offset += nodeIdLength
const text = decoder3.decode(rawData.slice(offset))
this.dispatchCustomEvent('progress_text', {
nodeId,
text,
...(promptId !== undefined && { prompt_id: promptId })
})
} catch (e) {
console.warn('Failed to parse progress_text binary message', e)
}
break
}
case 1:
const imageType = view.getUint32(4)
const imageData = event.data.slice(8)

View File

@@ -517,11 +517,16 @@ export const useExecutionStore = defineStore('execution', () => {
}
function handleProgressText(e: CustomEvent<ProgressTextWsMessage>) {
const { nodeId, text } = e.detail
const { nodeId, text, prompt_id } = e.detail
if (!text || !nodeId) return
// Filter: only accept progress for the active prompt
if (prompt_id && activeJobId.value && prompt_id !== activeJobId.value)
return
// Handle execution node IDs for subgraphs
const currentId = getNodeIdIfExecuting(nodeId)
if (!currentId) return
const node = canvasStore.getCanvas().graph?.getNodeById(currentId)
if (!node) return