mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-05 05:00:03 +00:00
feat(historyV2): load workflows for images (#6384)
## Summary Hooked up the "Load Workflow" action to our `history_v2` API. Note: Our cloud envs were being stress tested right now so images are loading at time of recording. Images were loading for me during development before I had time to create the video. ## Screenshots 📷 https://github.com/user-attachments/assets/02145504-ceae-497b-9049-553796d698da ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6384-Feat-history-v2-workflows-29b6d73d365081bcb706fe799b8ce66a) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -13,11 +13,6 @@
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import type { TaskItem } from '@/schemas/apiSchema'
|
||||
|
||||
interface ReconciliationResult {
|
||||
/** All items to display, sorted by queueIndex descending (newest first) */
|
||||
items: TaskItem[]
|
||||
}
|
||||
|
||||
/**
|
||||
* V1 reconciliation: QueueIndex-based filtering works because V1 has stable,
|
||||
* monotonically increasing queue indices.
|
||||
@@ -25,13 +20,15 @@ interface ReconciliationResult {
|
||||
* Sort order: Sorts serverHistory by queueIndex descending (newest first) to ensure
|
||||
* consistent ordering. JavaScript .filter() maintains iteration order, so filtered
|
||||
* results remain sorted. clientHistory is assumed already sorted from previous update.
|
||||
*
|
||||
* @returns All items to display, sorted by queueIndex descending (newest first)
|
||||
*/
|
||||
function reconcileHistoryV1(
|
||||
serverHistory: TaskItem[],
|
||||
clientHistory: TaskItem[],
|
||||
maxItems: number,
|
||||
lastKnownQueueIndex: number | undefined
|
||||
): ReconciliationResult {
|
||||
): TaskItem[] {
|
||||
const sortedServerHistory = serverHistory.sort(
|
||||
(a, b) => b.prompt[0] - a.prompt[0]
|
||||
)
|
||||
@@ -53,13 +50,9 @@ function reconcileHistoryV1(
|
||||
)
|
||||
|
||||
// Merge new and reused items, sort by queueIndex descending, limit to maxItems
|
||||
const allItems = [...itemsAddedSinceLastSync, ...clientItemsStillOnServer]
|
||||
return [...itemsAddedSinceLastSync, ...clientItemsStillOnServer]
|
||||
.sort((a, b) => b.prompt[0] - a.prompt[0])
|
||||
.slice(0, maxItems)
|
||||
|
||||
return {
|
||||
items: allItems
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,12 +62,14 @@ function reconcileHistoryV1(
|
||||
* Sort order: Sorts serverHistory by queueIndex descending (newest first) to ensure
|
||||
* consistent ordering. JavaScript .filter() maintains iteration order, so filtered
|
||||
* results remain sorted. clientHistory is assumed already sorted from previous update.
|
||||
*
|
||||
* @returns All items to display, sorted by queueIndex descending (newest first)
|
||||
*/
|
||||
function reconcileHistoryV2(
|
||||
serverHistory: TaskItem[],
|
||||
clientHistory: TaskItem[],
|
||||
maxItems: number
|
||||
): ReconciliationResult {
|
||||
): TaskItem[] {
|
||||
const sortedServerHistory = serverHistory.sort(
|
||||
(a, b) => b.prompt[0] - a.prompt[0]
|
||||
)
|
||||
@@ -84,29 +79,18 @@ function reconcileHistoryV2(
|
||||
)
|
||||
const clientPromptIds = new Set(clientHistory.map((item) => item.prompt[1]))
|
||||
|
||||
const newPromptIds = new Set(
|
||||
[...serverPromptIds].filter((id) => !clientPromptIds.has(id))
|
||||
const newItems = sortedServerHistory.filter(
|
||||
(item) => !clientPromptIds.has(item.prompt[1])
|
||||
)
|
||||
|
||||
const newItems = sortedServerHistory.filter((item) =>
|
||||
newPromptIds.has(item.prompt[1])
|
||||
)
|
||||
|
||||
const retainedPromptIds = new Set(
|
||||
[...serverPromptIds].filter((id) => clientPromptIds.has(id))
|
||||
)
|
||||
const clientItemsStillOnServer = clientHistory.filter((item) =>
|
||||
retainedPromptIds.has(item.prompt[1])
|
||||
serverPromptIds.has(item.prompt[1])
|
||||
)
|
||||
|
||||
// Merge new and reused items, sort by queueIndex descending, limit to maxItems
|
||||
const allItems = [...newItems, ...clientItemsStillOnServer]
|
||||
return [...newItems, ...clientItemsStillOnServer]
|
||||
.sort((a, b) => b.prompt[0] - a.prompt[0])
|
||||
.slice(0, maxItems)
|
||||
|
||||
return {
|
||||
items: allItems
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +109,7 @@ export function reconcileHistory(
|
||||
clientHistory: TaskItem[],
|
||||
maxItems: number,
|
||||
lastKnownQueueIndex?: number
|
||||
): ReconciliationResult {
|
||||
): TaskItem[] {
|
||||
if (isCloud) {
|
||||
return reconcileHistoryV2(serverHistory, clientHistory, maxItems)
|
||||
}
|
||||
|
||||
21
src/platform/workflow/cloud/getWorkflowFromHistory.ts
Normal file
21
src/platform/workflow/cloud/getWorkflowFromHistory.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema'
|
||||
import type { PromptId } from '@/schemas/apiSchema'
|
||||
|
||||
export async function getWorkflowFromHistory(
|
||||
fetchApi: (url: string) => Promise<Response>,
|
||||
promptId: PromptId
|
||||
): Promise<ComfyWorkflowJSON | undefined> {
|
||||
try {
|
||||
const res = await fetchApi(`/history_v2/${promptId}`)
|
||||
const json = await res.json()
|
||||
|
||||
const historyItem = json[promptId]
|
||||
if (!historyItem) return undefined
|
||||
|
||||
const workflow = historyItem.prompt?.extra_data?.extra_pnginfo?.workflow
|
||||
return workflow ?? undefined
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch workflow for prompt ${promptId}:`, error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
10
src/platform/workflow/cloud/index.ts
Normal file
10
src/platform/workflow/cloud/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Cloud: Fetches workflow by prompt_id. Desktop: Returns undefined (workflows already in history).
|
||||
*/
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
|
||||
import { getWorkflowFromHistory as cloudImpl } from './getWorkflowFromHistory'
|
||||
|
||||
export const getWorkflowFromHistory = isCloud
|
||||
? cloudImpl
|
||||
: async () => undefined
|
||||
Reference in New Issue
Block a user