Support as-yet-released error API

upp
This commit is contained in:
space-nuko
2023-05-26 23:04:25 -05:00
parent 1da8dc35ec
commit 72af089eab
14 changed files with 758 additions and 87 deletions

View File

@@ -1,12 +1,14 @@
import type { ComfyAPIHistoryEntry, ComfyAPIHistoryItem, ComfyAPIHistoryResponse, ComfyAPIQueueResponse, ComfyAPIStatusResponse, ComfyBoxPromptExtraData, ComfyNodeID, PromptID, QueueItemType } from "$lib/api";
import type { Progress, SerializedPromptInputsAll, SerializedPromptOutputs, WorkflowInstID } from "$lib/components/ComfyApp";
import type { ComfyAPIHistoryEntry, ComfyAPIHistoryItem, ComfyAPIHistoryResponse, ComfyAPIQueueResponse, ComfyAPIStatusResponse, ComfyBoxPromptExtraData, ComfyExecutionError, ComfyNodeID, PromptID, QueueItemType } from "$lib/api";
import type { ComfyAPIPromptErrorResponse } from "$lib/apiErrors";
import type { Progress, SerializedPrompt, SerializedPromptInputsAll, SerializedPromptOutputs, } from "$lib/components/ComfyApp";
import type { ComfyExecutionResult } from "$lib/nodes/ComfyWidgetNodes";
import notify from "$lib/notify";
import { get, writable, type Writable } from "svelte/store";
import workflowState from "./workflowState";
import { playSound } from "$lib/utils";
import { get, writable, type Writable } from "svelte/store";
import { v4 as uuidv4 } from "uuid";
import workflowState, { type WorkflowError, type WorkflowExecutionError, type WorkflowInstID, type WorkflowValidationError } from "./workflowState";
export type QueueEntryStatus = "success" | "error" | "interrupted" | "all_cached" | "unknown";
export type QueueEntryStatus = "success" | "validation_failed" | "error" | "interrupted" | "all_cached" | "unknown";
type QueueStateOps = {
queueUpdated: (resp: ComfyAPIQueueResponse) => void,
@@ -15,13 +17,14 @@ type QueueStateOps = {
executionStart: (promptID: PromptID) => void,
executingUpdated: (promptID: PromptID | null, runningNodeID: ComfyNodeID | null) => QueueEntry | null;
executionCached: (promptID: PromptID, nodes: ComfyNodeID[]) => void,
executionError: (promptID: PromptID, message: string) => void,
executionError: (error: ComfyExecutionError) => CompletedQueueEntry | null,
progressUpdated: (progress: Progress) => void
getQueueEntry: (promptID: PromptID) => QueueEntry | null;
afterQueued: (workflowID: WorkflowInstID, promptID: PromptID, number: number, prompt: SerializedPromptInputsAll, extraData: any) => void
queueItemDeleted: (type: QueueItemType, id: PromptID) => void;
queueCleared: (type: QueueItemType) => void;
onExecuted: (promptID: PromptID, nodeID: ComfyNodeID, output: ComfyExecutionResult) => QueueEntry | null
promptError: (id: WorkflowInstID, error: ComfyAPIPromptErrorResponse, prompt: SerializedPrompt, extraData: ComfyBoxPromptExtraData) => PromptID
}
/*
@@ -34,6 +37,10 @@ export type QueueEntry = {
number: number,
queuedAt?: Date,
finishedAt?: Date,
/*
* Can also be generated by the frontend if prompt validation fails
* (the backend won't send back a prompt ID in that case)
*/
promptID: PromptID,
prompt: SerializedPromptInputsAll,
extraData: ComfyBoxPromptExtraData,
@@ -46,7 +53,7 @@ export type QueueEntry = {
/* Nodes of the workflow that have finished running so far. */
nodesRan: Set<ComfyNodeID>,
/* Nodes of the workflow the backend reported as cached. */
cachedNodes: Set<ComfyNodeID>
cachedNodes: Set<ComfyNodeID>,
}
/*
@@ -61,7 +68,7 @@ export type CompletedQueueEntry = {
/** Message to display in the frontend */
message?: string,
/** Detailed error/stacktrace, perhaps inspectible with a popup */
error?: string,
error?: WorkflowError
}
/*
@@ -229,21 +236,32 @@ function moveToRunning(index: number, queue: Writable<QueueEntry[]>) {
store.set(state)
}
function moveToCompleted(index: number, queue: Writable<QueueEntry[]>, status: QueueEntryStatus, message?: string, error?: string) {
function moveToCompleted(index: number, queue: Writable<QueueEntry[]>, status: QueueEntryStatus, message?: string, error?: ComfyExecutionError): CompletedQueueEntry {
const state = get(store)
const entry = get(queue)[index];
let workflowError: WorkflowExecutionError | null = null;
if (error) {
workflowError = {
type: "execution",
error
}
entry.nodesRan = new Set(error.executed);
}
console.debug("[queueState] Move to completed", entry.promptID, index, status, message, error)
entry.finishedAt = new Date() // Now
queue.update(qp => { qp.splice(index, 1); return qp });
const completed: CompletedQueueEntry = { entry, status, message, error: workflowError }
state.queueCompleted.update(qc => {
const completed: CompletedQueueEntry = { entry, status, message, error }
qc.push(completed)
return qc
})
state.isInterrupting = false;
store.set(state)
return completed;
}
function executingUpdated(promptID: PromptID, runningNodeID: ComfyNodeID | null): QueueEntry | null {
@@ -314,20 +332,22 @@ function executionCached(promptID: PromptID, nodes: ComfyNodeID[]) {
})
}
function executionError(promptID: PromptID, message: string) {
console.debug("[queueState] executionError", promptID, message)
function executionError(error: ComfyExecutionError): CompletedQueueEntry | null {
console.debug("[queueState] executionError", error)
let entry_ = null;
store.update(s => {
const [index, entry, queue] = findEntryInPending(promptID);
const [index, entry, queue] = findEntryInPending(error.prompt_id);
if (entry != null) {
moveToCompleted(index, queue, "error", "Error executing", message)
entry_ = moveToCompleted(index, queue, "error", "Error executing", error)
}
else {
console.error("[queueState] Could not find in pending! (executionError)", promptID)
console.error("[queueState] Could not find in pending! (executionError)", error.prompt_id)
}
s.progress = null;
s.runningNodeID = null;
return s
})
return entry_;
}
function createNewQueueEntry(promptID: PromptID, number: number = -1, prompt: SerializedPromptInputsAll = {}, extraData: any = {}): QueueEntry {
@@ -432,6 +452,43 @@ function queueCleared(type: QueueItemType) {
})
}
function promptError(workflowID: WorkflowInstID, error: ComfyAPIPromptErrorResponse, prompt: SerializedPrompt, extraData: ComfyBoxPromptExtraData): PromptID {
const workflowError: WorkflowValidationError = {
type: "validation",
workflowID,
error,
prompt,
extraData
}
const entry: QueueEntry = {
number: 0,
queuedAt: new Date(), // Now
finishedAt: new Date(),
promptID: uuidv4(), // Just for keeping track
prompt: prompt.output,
extraData,
goodOutputs: [],
outputs: {},
nodesRan: new Set(),
cachedNodes: new Set(),
}
const completedEntry: CompletedQueueEntry = {
entry,
status: "validation_failed",
message: "Validation failed",
error: workflowError
}
store.update(s => {
s.queueCompleted.update(qc => { qc.push(completedEntry); return qc })
return s;
})
return entry.promptID;
}
const queueStateStore: WritableQueueStateStore =
{
...store,
@@ -447,6 +504,7 @@ const queueStateStore: WritableQueueStateStore =
queueItemDeleted,
queueCleared,
getQueueEntry,
onExecuted
onExecuted,
promptError,
}
export default queueStateStore;