Spaces:
Configuration error
Configuration error
| import { app } from "../../../../scripts/app.js"; | |
| function links_with(p, node_id, down, up) { | |
| const links_with = []; | |
| p.workflow.links.forEach((l) => { | |
| if (down && l[1]===node_id && !links_with.includes(l[3])) links_with.push(l[3]) | |
| if (up && l[3]===node_id && !links_with.includes(l[1])) links_with.push(l[1]) | |
| }); | |
| return links_with; | |
| } | |
| function _all_v_nodes(p, here_id) { | |
| /* | |
| Make a list of all downstream nodes. | |
| */ | |
| const downstream = []; | |
| const to_process = [here_id] | |
| while(to_process.length>0) { | |
| const id = to_process.pop(); | |
| downstream.push(id); | |
| to_process.push( | |
| ...links_with(p,id,true,false).filter((nid)=>{ | |
| return !(downstream.includes(nid) || to_process.includes(nid)) | |
| }) | |
| ) | |
| } | |
| /* | |
| Now all upstream nodes from any of the downstream nodes (except us). | |
| Put us on the result list so we don't flow up through us | |
| */ | |
| to_process.push(...downstream.filter((n)=>{ return n!=here_id})); | |
| const back_upstream = [here_id]; | |
| while(to_process.length>0) { | |
| const id = to_process.pop(); | |
| back_upstream.push(id); | |
| to_process.push( | |
| ...links_with(p,id,false,true).filter((nid)=>{ | |
| return !(back_upstream.includes(nid) || to_process.includes(nid)) | |
| }) | |
| ) | |
| } | |
| const keep = []; | |
| keep.push(...downstream); | |
| keep.push(...back_upstream.filter((n)=>{return !keep.includes(n)})); | |
| console.log(`Nodes to keep: ${keep}`); | |
| return keep; | |
| } | |
| async function all_v_nodes(here_id) { | |
| const p = structuredClone(await app.graphToPrompt()); | |
| const all_nodes = []; | |
| p.workflow.nodes.forEach((node)=>{all_nodes.push(node.id)}) | |
| p.workflow.links = p.workflow.links.filter((l)=>{ return (all_nodes.includes(l[1]) && all_nodes.includes(l[3]))} ) | |
| return _all_v_nodes(p,here_id); | |
| } | |
| async function restart_from_here(here_id, go_down_to_chooser=false) { | |
| const p = structuredClone(await app.graphToPrompt()); | |
| /* | |
| Make a list of all nodes, and filter out links that are no longer valid | |
| */ | |
| const all_nodes = []; | |
| p.workflow.nodes.forEach((node)=>{all_nodes.push(node.id)}) | |
| p.workflow.links = p.workflow.links.filter((l)=>{ return (all_nodes.includes(l[1]) && all_nodes.includes(l[3]))} ) | |
| /* Move downstream to a chooser */ | |
| if (go_down_to_chooser) { | |
| while (!app.graph._nodes_by_id[here_id].isChooser) { | |
| here_id = links_with(p, here_id, true, false)[0]; | |
| } | |
| } | |
| const keep = _all_v_nodes(p, here_id); | |
| /* | |
| Filter p.workflow.nodes and p.workflow.links | |
| */ | |
| p.workflow.nodes = p.workflow.nodes.filter((node) => { | |
| if (node.id===here_id) node.inputs.forEach((i)=>{i.link=null}) // remove our upstream links | |
| return (keep.includes(node.id)) // only keep keepers | |
| }) | |
| p.workflow.links = p.workflow.links.filter((l) => {return (keep.includes(l[1]) && keep.includes(l[3]))}) | |
| /* | |
| Filter the p.output object to only include nodes we're keeping | |
| */ | |
| const new_output = {} | |
| for (const [key, value] of Object.entries(p.output)) { | |
| if (keep.includes(parseInt(key))) new_output[key] = value; | |
| } | |
| /* | |
| Filter the p.output entry for the start node to remove any list (ie link) inputs | |
| */ | |
| const new_inputs = {}; | |
| for (const [key, value] of Object.entries(new_output[here_id.toString()].inputs)) { | |
| if (!Array.isArray(value)) new_inputs[key] = value; | |
| } | |
| new_output[here_id.toString()].inputs = new_inputs; | |
| p.output = new_output; | |
| // temporarily hijack graph_to_prompt with a version that restores the old one but returns this prompt | |
| const gtp_was = app.graphToPrompt; | |
| app.graphToPrompt = () => { | |
| app.graphToPrompt = gtp_was; | |
| return p; | |
| } | |
| app.queuePrompt(0); | |
| } | |
| export { restart_from_here, all_v_nodes } |