Prompt serializer and test fixes

This commit is contained in:
space-nuko
2023-05-20 21:42:38 -05:00
parent 8d031120f7
commit 09e806bd3e
17 changed files with 196 additions and 106 deletions

View File

@@ -8,6 +8,7 @@ import { v4 as uuidv4 } from "uuid";
import type { ComfyWidgetNode } from '$lib/nodes/widgets';
import type { ComfyWorkflow, WorkflowInstID } from '$lib/components/ComfyApp';
import type ComfyGraph from '$lib/ComfyGraph';
import type { WorkflowAttributes } from './workflowState';
function isComfyWidgetNode(node: LGraphNode): node is ComfyWidgetNode {
return "svelteComponentType" in node
@@ -31,24 +32,6 @@ type DragItemEntry = {
parent: IDragItem | null
}
/*
* Global workflow attributes
*/
export type LayoutAttributes = {
/*
* Name of the "Queue Prompt" button. Set to blank to hide the button.
*/
queuePromptButtonName: string,
/*
* If true, clicking the "Queue Prompt" button will run the default
* subgraph. Set this to false if you need special behavior before running
* any subgraphs, and instead use the `onDefaultQueueAction` event of the
* Comfy.QueueEvents node.
*/
queuePromptButtonRunWorkflow: boolean,
}
/*
* Keeps track of the tree of UI components - widgets and the containers that
* group them together.
@@ -82,11 +65,6 @@ export type LayoutState = {
* If true, the right-click context menu is open
*/
isMenuOpen: boolean,
/*
* Global workflow attributes
*/
attrs: LayoutAttributes
}
/**
@@ -185,7 +163,7 @@ export type AttributesSpec = {
* - "widget": inside IDragNode.attrs
* - "nodeProps": inside LGraphNode.properties
* - "nodeVars": an instance variable directly on an LGraphNode
* - "workflow": inside $layoutState.attrs
* - "workflow": inside $workflowState.activeWorkflow.attrs
*/
location: "widget" | "nodeProps" | "nodeVars" | "workflow"
@@ -601,7 +579,7 @@ export { ALL_ATTRIBUTES };
// TODO Should be nested by category for name uniqueness?
const defaultWidgetAttributes: Attributes = {} as any
const defaultWorkflowAttributes: LayoutAttributes = {} as any
export const defaultWorkflowAttributes: WorkflowAttributes = {} as any
for (const cat of Object.values(ALL_ATTRIBUTES)) {
for (const spec of Object.values(cat.specs)) {
if (spec.defaultValue != null) {
@@ -697,7 +675,6 @@ type LayoutStateOps = {
export type SerializedLayoutState = {
root: DragItemID | null,
allItems: Record<DragItemID, SerializedDragEntry>,
attrs: LayoutAttributes
}
export type SerializedDragEntry = {
@@ -726,9 +703,6 @@ function create(workflow: ComfyWorkflow): WritableLayoutStateStore {
allItemsByNode: {},
isMenuOpen: false,
isConfiguring: true,
attrs: {
...defaultWorkflowAttributes
}
})
function clear() {
@@ -738,9 +712,6 @@ function create(workflow: ComfyWorkflow): WritableLayoutStateStore {
allItemsByNode: {},
isMenuOpen: false,
isConfiguring: true,
attrs: {
...defaultWorkflowAttributes
}
})
}
@@ -1063,9 +1034,6 @@ function create(workflow: ComfyWorkflow): WritableLayoutStateStore {
allItemsByNode: {},
isMenuOpen: false,
isConfiguring: false,
attrs: {
...defaultWorkflowAttributes
}
})
const root = addContainer(null, { direction: "horizontal", title: "" });
@@ -1100,7 +1068,6 @@ function create(workflow: ComfyWorkflow): WritableLayoutStateStore {
return {
root: state.root?.id,
allItems,
attrs: state.attrs
}
}
@@ -1156,7 +1123,6 @@ function create(workflow: ComfyWorkflow): WritableLayoutStateStore {
allItemsByNode,
isMenuOpen: false,
isConfiguring: false,
attrs: { ...defaultWorkflowAttributes, ...data.attrs }
}
console.debug("[layoutState] deserialize", data, state, defaultWorkflowAttributes)

View File

@@ -1,8 +1,8 @@
import type { SerializedGraphCanvasState } from '$lib/ComfyGraphCanvas';
import { clamp, type LGraphCanvas, type NodeID, type SerializedLGraph, type UUID } from '@litegraph-ts/core';
import { clamp, LGraphNode, type LGraphCanvas, type NodeID, type SerializedLGraph, type UUID, LGraph } from '@litegraph-ts/core';
import { get, writable } from 'svelte/store';
import type { Readable, Writable } from 'svelte/store';
import type { SerializedLayoutState, WritableLayoutStateStore } from './layoutStates';
import { defaultWorkflowAttributes, type SerializedLayoutState, type WritableLayoutStateStore } from './layoutStates';
import ComfyGraph from '$lib/ComfyGraph';
import layoutStates from './layoutStates';
import { v4 as uuidv4 } from "uuid";
@@ -18,7 +18,8 @@ type ActiveCanvas = {
export type SerializedWorkflowState = {
graph: SerializedLGraph,
layout: SerializedLayoutState
layout: SerializedLayoutState,
attrs: WorkflowAttributes
}
/*
@@ -31,22 +32,45 @@ export type SerializedWorkflowState = {
*/
export type WorkflowInstID = UUID;
/*
* Global workflow attributes
*/
export type WorkflowAttributes = {
/*
* Title of the workflow.
*/
title: string,
/*
* Name of the "Queue Prompt" button. Set to blank to hide the button.
*/
queuePromptButtonName: string,
/*
* If true, clicking the "Queue Prompt" button will run the default
* subgraph. Set this to false if you need special behavior before running
* any subgraphs, and instead use the `onDefaultQueueAction` event of the
* Comfy.QueueEvents node.
*/
queuePromptButtonRunWorkflow: boolean,
}
export class ComfyWorkflow {
/*
* Used for uniquely identifying the instance of the opened workflow in the frontend.
*/
id: WorkflowInstID;
/*
* Human-readable name on the tab
*/
title: string;
/*
* Graph of this workflow, whose nodes are bound to the UI layout
*/
graph: ComfyGraph;
/*
* Global workflow attributes
*/
attrs: WorkflowAttributes
get layout(): WritableLayoutStateStore | null {
return layoutStates.getLayout(this.id)
}
@@ -58,7 +82,10 @@ export class ComfyWorkflow {
constructor(title: string) {
this.id = uuidv4();
this.title = title;
this.attrs = {
...defaultWorkflowAttributes,
title,
}
this.graph = new ComfyGraph(this.id);
}
@@ -115,7 +142,8 @@ export class ComfyWorkflow {
return {
graph: serializedGraph,
layout: serializedLayout
layout: serializedLayout,
attrs: this.attrs
}
}
@@ -147,6 +175,8 @@ export class ComfyWorkflow {
// this.#invokeExtensions("loadedGraphNode", node);
}
this.attrs = data.attrs;
// Now restore the layout
// Subsequent added nodes will add the UI data to layoutState
// TODO
@@ -163,6 +193,8 @@ export type WorkflowState = {
type WorkflowStateOps = {
getWorkflow: (id: WorkflowInstID) => ComfyWorkflow | null
getWorkflowByGraph: (graph: LGraph) => ComfyWorkflow | null
getWorkflowByNode: (node: LGraphNode) => ComfyWorkflow | null
getWorkflowByNodeID: (id: NodeID) => ComfyWorkflow | null
getActiveWorkflow: () => ComfyWorkflow | null
createNewWorkflow: (canvas: ComfyGraphCanvas, title?: string, setActive?: boolean) => ComfyWorkflow,
@@ -185,6 +217,16 @@ function getWorkflow(id: WorkflowInstID): ComfyWorkflow | null {
return get(store).openedWorkflowsByID[id];
}
function getWorkflowByGraph(graph: LGraph): ComfyWorkflow | null {
if ("workflowID" in graph && graph.workflowID != null)
return getWorkflow((graph as ComfyGraph).workflowID);
return null;
}
function getWorkflowByNode(node: LGraphNode): ComfyWorkflow | null {
return getWorkflowByGraph(node.graph);
}
function getWorkflowByNodeID(id: NodeID): ComfyWorkflow | null {
return Object.values(get(store).openedWorkflows).find(w => {
return w.graph.getNodeByIdRecursive(id) != null
@@ -216,8 +258,8 @@ function createNewWorkflow(canvas: ComfyGraphCanvas, title: string = "New Workfl
}
function openWorkflow(canvas: ComfyGraphCanvas, data: SerializedAppState): ComfyWorkflow {
const [workflow, layoutState] = ComfyWorkflow.create(data.workflowName || "Workflow")
workflow.deserialize(layoutState, { graph: data.workflow, layout: data.layout })
const [workflow, layoutState] = ComfyWorkflow.create("Workflow")
workflow.deserialize(layoutState, { graph: data.workflow, layout: data.layout, attrs: data.attrs })
const state = get(store);
state.openedWorkflows.push(workflow);
@@ -285,6 +327,8 @@ const workflowStateStore: WritableWorkflowStateStore =
{
...store,
getWorkflow,
getWorkflowByGraph,
getWorkflowByNode,
getWorkflowByNodeID,
getActiveWorkflow,
createNewWorkflow,