Start vanilla workflow conversion, better PNG parser based on catbox
userscript code
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { LiteGraph, LGraph, LGraphCanvas, LGraphNode, type LGraphNodeConstructor, type LGraphNodeExecutable, type SerializedLGraph, type SerializedLGraphGroup, type SerializedLGraphNode, type SerializedLLink, NodeMode, type Vector2, BuiltInSlotType, type INodeInputSlot, type NodeID, type NodeTypeSpec, type NodeTypeOpts, type SlotIndex, type UUID } from "@litegraph-ts/core";
|
||||
import type { LConnectionKind, INodeSlot } from "@litegraph-ts/core";
|
||||
import ComfyAPI, { type ComfyAPIStatusResponse, type ComfyBoxPromptExtraData, type ComfyPromptRequest, type ComfyNodeID, type PromptID } from "$lib/api"
|
||||
import { getPngMetadata, importA1111 } from "$lib/pnginfo";
|
||||
import { getPngMetadata, importA1111, parsePNGMetadata } from "$lib/pnginfo";
|
||||
import EventEmitter from "events";
|
||||
import type TypedEmitter from "typed-emitter";
|
||||
|
||||
@@ -44,6 +44,7 @@ import selectionState from "$lib/stores/selectionState";
|
||||
import layoutStates from "$lib/stores/layoutStates";
|
||||
import { ComfyWorkflow, type WorkflowAttributes, type WorkflowInstID } from "$lib/stores/workflowState";
|
||||
import workflowState from "$lib/stores/workflowState";
|
||||
import convertVanillaWorkflow from "$lib/convertVanillaWorkflow";
|
||||
|
||||
export const COMFYBOX_SERIAL_VERSION = 1;
|
||||
|
||||
@@ -72,8 +73,10 @@ export type A1111PromptAndInfo = {
|
||||
* Represents a single workflow that can be loaded into the program from JSON.
|
||||
*/
|
||||
export type SerializedAppState = {
|
||||
/** Program identifier, should always be "ComfyBox" */
|
||||
createdBy: "ComfyBox",
|
||||
/** For easy structural typing use */
|
||||
comfyBoxWorkflow: true,
|
||||
/** Program identifier, should be something like "ComfyBox" or "ComfyUI" */
|
||||
createdBy: string,
|
||||
/** Serial version, should be incremented on breaking changes */
|
||||
version: number,
|
||||
/** Commit hash if found */
|
||||
@@ -138,6 +141,14 @@ type CanvasState = {
|
||||
canvas: ComfyGraphCanvas,
|
||||
}
|
||||
|
||||
function isComfyBoxWorkflow(data: any): data is SerializedAppState {
|
||||
return data != null && (typeof data === "object") && data.comfyBoxWorkflow;
|
||||
}
|
||||
|
||||
function isVanillaWorkflow(data: any): data is SerializedLGraph {
|
||||
return data != null && (typeof data === "object") && data.last_node_id != null;
|
||||
}
|
||||
|
||||
export default class ComfyApp {
|
||||
api: ComfyAPI;
|
||||
|
||||
@@ -237,6 +248,7 @@ export default class ComfyApp {
|
||||
const canvas = this.lCanvas.serialize();
|
||||
|
||||
return {
|
||||
comfyBoxWorkflow: true,
|
||||
createdBy: "ComfyBox",
|
||||
version: COMFYBOX_SERIAL_VERSION,
|
||||
commitHash: __GIT_COMMIT_HASH__,
|
||||
@@ -399,7 +411,7 @@ export default class ComfyApp {
|
||||
} catch (error) { }
|
||||
}
|
||||
|
||||
if (workflow && workflow.createdBy === "ComfyBox") {
|
||||
if (workflow && typeof workflow.createdBy === "string") {
|
||||
this.openWorkflow(workflow);
|
||||
}
|
||||
else {
|
||||
@@ -537,6 +549,13 @@ export default class ComfyApp {
|
||||
return workflow;
|
||||
}
|
||||
|
||||
async openVanillaWorkflow(data: SerializedLGraph) {
|
||||
const converted = convertVanillaWorkflow(data)
|
||||
console.info("WORKFLWO", converted)
|
||||
notify("Converted ComfyUI workflow to ComfyBox format.", { type: "info" })
|
||||
// await this.openWorkflow(JSON.parse(pngInfo.workflow));
|
||||
}
|
||||
|
||||
setActiveWorkflow(id: WorkflowInstID) {
|
||||
const index = get(workflowState).openedWorkflows.findIndex(w => w.id === id)
|
||||
if (index === -1)
|
||||
@@ -695,7 +714,7 @@ export default class ComfyApp {
|
||||
}
|
||||
|
||||
const p = this.graphToPrompt(workflow, tag);
|
||||
const l = workflow.layout.serialize();
|
||||
const wf = this.serialize(workflow)
|
||||
console.debug(graphToGraphVis(workflow.graph))
|
||||
console.debug(promptToGraphVis(p))
|
||||
|
||||
@@ -704,9 +723,10 @@ export default class ComfyApp {
|
||||
|
||||
const extraData: ComfyBoxPromptExtraData = {
|
||||
extra_pnginfo: {
|
||||
workflow: p.workflow,
|
||||
comfyBoxLayout: l,
|
||||
comfyBoxSubgraphs: [tag],
|
||||
comfyBoxWorkflow: wf,
|
||||
comfyBoxPrompt: {
|
||||
subgraphs: [tag]
|
||||
}
|
||||
},
|
||||
thumbnails
|
||||
}
|
||||
@@ -761,10 +781,14 @@ export default class ComfyApp {
|
||||
*/
|
||||
async handleFile(file: File) {
|
||||
if (file.type === "image/png") {
|
||||
const pngInfo = await getPngMetadata(file);
|
||||
const buffer = await file.arrayBuffer();
|
||||
const pngInfo = await parsePNGMetadata(buffer);
|
||||
if (pngInfo) {
|
||||
if (pngInfo.comfyBoxConfig) {
|
||||
await this.openWorkflow(JSON.parse(pngInfo.comfyBoxConfig));
|
||||
if (pngInfo.comfyBoxWorkflow) {
|
||||
await this.openWorkflow(JSON.parse(pngInfo.comfyBoxWorkflow));
|
||||
} else if (pngInfo.workflow) {
|
||||
const workflow = JSON.parse(pngInfo.workflow);
|
||||
await this.openVanillaWorkflow(workflow);
|
||||
} else if (pngInfo.parameters) {
|
||||
const parsed = parseA1111(pngInfo.parameters)
|
||||
if ("error" in parsed) {
|
||||
@@ -787,7 +811,13 @@ export default class ComfyApp {
|
||||
} else if (file.type === "application/json" || file.name.endsWith(".json")) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
await this.openWorkflow(JSON.parse(reader.result as string));
|
||||
const result = JSON.parse(reader.result as string)
|
||||
if (isComfyBoxWorkflow(result)) {
|
||||
await this.openWorkflow(result);
|
||||
}
|
||||
else if (isVanillaWorkflow(result)) {
|
||||
await this.openVanillaWorkflow(result);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
dateStr = formatDate(date);
|
||||
}
|
||||
|
||||
const subgraphs: string[] | null = entry.extraData?.extra_pnginfo?.comfyBoxSubgraphs;
|
||||
const subgraphs: string[] | null = entry.extraData?.extra_pnginfo?.comfyBoxPrompt?.subgraphs;
|
||||
|
||||
let message = "Prompt";
|
||||
if (entry.workflowID != null) {
|
||||
@@ -208,7 +208,7 @@
|
||||
</Modal>
|
||||
|
||||
<div class="queue">
|
||||
<DropZone {app} />
|
||||
<!-- <DropZone {app} /> -->
|
||||
<div class="queue-entries {mode}-mode" bind:this={queueList}>
|
||||
{#if _entries.length > 0}
|
||||
{#each _entries as entry}
|
||||
@@ -305,8 +305,9 @@
|
||||
<style lang="scss">
|
||||
$pending-height: 200px;
|
||||
$bottom-bar-height: 70px;
|
||||
$workflow-tabs-height: 2.5rem;
|
||||
$mode-buttons-height: 30px;
|
||||
$queue-height: calc(100vh - #{$pending-height} - #{$mode-buttons-height} - #{$bottom-bar-height});
|
||||
$queue-height: calc(100vh - #{$pending-height} - #{$mode-buttons-height} - #{$bottom-bar-height} - #{$workflow-tabs-height} - 0.9rem);
|
||||
|
||||
.prompt-modal-header {
|
||||
padding-left: 0.2rem;
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
{#if $workflowState.activeWorkflow != null}
|
||||
<ComfyWorkflowView {app} workflow={$workflowState.activeWorkflow} />
|
||||
{:else}
|
||||
<span>No workflow loaded</span>
|
||||
<span style:color="var(--body-text-color)">No workflow loaded</span>
|
||||
{/if}
|
||||
</Pane>
|
||||
<Pane bind:size={graphSize}>
|
||||
@@ -313,7 +313,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input bind:this={fileInput} id="comfy-file-input" type="file" accept=".json" on:change={loadWorkflow} />
|
||||
<input bind:this={fileInput} id="comfy-file-input" type="file" accept="application/json,image/png" on:change={loadWorkflow} />
|
||||
|
||||
{#if appSetupPromise}
|
||||
{#await appSetupPromise}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
let galleryStyle: Styles = {
|
||||
grid_cols: [2],
|
||||
object_fit: "cover",
|
||||
object_fit: "contain",
|
||||
height: "var(--size-96)"
|
||||
}
|
||||
|
||||
@@ -165,6 +165,11 @@
|
||||
|
||||
> :global(.block) {
|
||||
height: 100%;
|
||||
|
||||
:global(> .preview) {
|
||||
height: 100%;
|
||||
max-height: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user