mirror of
https://github.com/SamueleLorefice/ComfySharp
synced 2026-01-15 01:35:48 +00:00
Revamped parsing part 1
This commit is contained in:
2
ComfySharp.sln.DotSettings
Normal file
2
ComfySharp.sln.DotSettings
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/Environment/Hierarchy/NuGetOptions/DefaultPackageManagementFormat/@EntryValue">PackageReference</s:String></wpf:ResourceDictionary>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Dynamic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -8,7 +9,7 @@ namespace ComfySharp;
|
|||||||
|
|
||||||
public class ComfyClient {
|
public class ComfyClient {
|
||||||
private HttpClient client;
|
private HttpClient client;
|
||||||
private List<Node> nodes;
|
private List<ExpandoObject> nodes;
|
||||||
|
|
||||||
public string BaseUrl { get; set; }
|
public string BaseUrl { get; set; }
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ public class ComfyClient {
|
|||||||
BaseAddress = new Uri(baseUrl),
|
BaseAddress = new Uri(baseUrl),
|
||||||
DefaultRequestHeaders = { { "User-Agent", "ComfySharp" } }
|
DefaultRequestHeaders = { { "User-Agent", "ComfySharp" } }
|
||||||
};
|
};
|
||||||
nodes= new List<Node>();
|
nodes= new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string[]?> GetEmbeddings() {
|
public async Task<string[]?> GetEmbeddings() {
|
||||||
@@ -49,10 +50,10 @@ public class ComfyClient {
|
|||||||
if (req is { IsSuccessStatusCode: true, Content: not null }) {
|
if (req is { IsSuccessStatusCode: true, Content: not null }) {
|
||||||
var doc = await req.Content.ReadFromJsonAsync<JsonDocument>();
|
var doc = await req.Content.ReadFromJsonAsync<JsonDocument>();
|
||||||
ObjectInfoParser.Parse(doc, out nodes);
|
ObjectInfoParser.Parse(doc, out nodes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException();
|
return null;
|
||||||
|
//throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<byte[]?> GetImage(string filename) {
|
public async Task<byte[]?> GetImage(string filename) {
|
||||||
|
|||||||
@@ -1,75 +1,21 @@
|
|||||||
using System.Text.Json;
|
using System.Dynamic;
|
||||||
|
using System.Text.Json;
|
||||||
using ComfySharp.Types;
|
using ComfySharp.Types;
|
||||||
|
|
||||||
namespace ComfySharp;
|
namespace ComfySharp;
|
||||||
|
|
||||||
public static class ObjectInfoParser {
|
public static class ObjectInfoParser {
|
||||||
public static void Parse(JsonDocument document, out List<Node> nodes) {
|
|
||||||
nodes = new List<Node>();
|
public static void Parse(JsonDocument document, out List<ExpandoObject> nodes) {
|
||||||
foreach (var node in document.RootElement.EnumerateObject()) {
|
NodeDBGenerator dbGenerator = new();
|
||||||
Node n = new();
|
dbGenerator.GenerateNodes(document);
|
||||||
n.Name = node.Name;
|
nodes = dbGenerator.GetNodes();
|
||||||
|
dbGenerator.GenerateClasses(document);
|
||||||
foreach (var prop in node.Value.EnumerateObject()) {
|
|
||||||
switch (prop.Name) {
|
|
||||||
case "input":
|
|
||||||
n.Input = new();
|
|
||||||
|
|
||||||
foreach (var input in prop.Value.EnumerateObject()) {
|
|
||||||
switch (input.Name) {
|
|
||||||
case "required":
|
|
||||||
foreach (var field in input.Value.EnumerateObject()) {
|
|
||||||
InputField f = new();
|
|
||||||
f.Name = field.Name;
|
|
||||||
f.Type = Enum.Parse<PrimitiveType>(field.Value.GetString() ?? "");
|
|
||||||
n.Input.Required.Add(f);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "optional":
|
|
||||||
foreach (var field in input.Value.EnumerateObject()) {
|
|
||||||
InputField f = new();
|
|
||||||
f.Name = field.Name;
|
|
||||||
f.Type = Enum.Parse<PrimitiveType>(field.Value.GetString() ?? "");
|
|
||||||
n.Input.Optional.Add(f);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "hidden":
|
|
||||||
foreach (var field in input.Value.EnumerateObject()) {
|
|
||||||
InputField f = new();
|
|
||||||
f.Name = field.Name;
|
|
||||||
f.Type = Enum.Parse<PrimitiveType>(field.Value.GetString() ?? "");
|
|
||||||
n.Input.Hidden.Add(f);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "output":
|
|
||||||
foreach (var output in prop.Value.EnumerateObject()) {
|
|
||||||
n.Outputs.Add(Enum.Parse<PrimitiveType>(output.Value.GetString() ?? ""));
|
|
||||||
n.OutputIsList.Add(output.Value.GetBoolean());
|
|
||||||
n.OutputNames.Add(output.Name);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "display_name":
|
|
||||||
n.DisplayName = prop.Value.GetString() ?? "";
|
|
||||||
break;
|
|
||||||
case "description":
|
|
||||||
n.Description = prop.Value.GetString() ?? "";
|
|
||||||
break;
|
|
||||||
case "category":
|
|
||||||
n.Category = prop.Value.GetString() ?? "";
|
|
||||||
break;
|
|
||||||
case "output_node":
|
|
||||||
n.IsOutputNode = prop.Value.GetBoolean();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ParseNode(JsonElement node, out Node n) {
|
private static void ParseNode(JsonElement node, out Node n) {
|
||||||
n = new();
|
n = new();
|
||||||
|
|
||||||
n.Name = node.GetProperty("name").GetString() ?? "";
|
n.Name = node.GetProperty("name").GetString() ?? "";
|
||||||
n.Input = ParseInput(node.GetProperty("input"));
|
n.Input = ParseInput(node.GetProperty("input"));
|
||||||
n.Outputs = ParseOutputs(node.GetProperty("output"));
|
n.Outputs = ParseOutputs(node.GetProperty("output"));
|
||||||
@@ -80,4 +26,20 @@ public static class ObjectInfoParser {
|
|||||||
n.Category = node.GetProperty("category").GetString() ?? "";
|
n.Category = node.GetProperty("category").GetString() ?? "";
|
||||||
n.IsOutputNode = node.GetProperty("output_node").GetBoolean();
|
n.IsOutputNode = node.GetProperty("output_node").GetBoolean();
|
||||||
}
|
}
|
||||||
|
static private List<string> ParseOutputNames(JsonElement getProperty) {
|
||||||
|
List<string> outputNames = new();
|
||||||
|
foreach (var output in getProperty.EnumerateArray()) {
|
||||||
|
outputNames.Add(output.GetProperty("name").GetString() ?? "");
|
||||||
|
}
|
||||||
|
return outputNames;
|
||||||
|
}
|
||||||
|
static private List<bool> ParseOutputIsList(JsonElement getProperty) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
static private List<PrimitiveType> ParseOutputs(JsonElement getProperty) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
static private Input ParseInput(JsonElement getProperty) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
181
ComfySharp/Types/NodeDBGenerator.cs
Normal file
181
ComfySharp/Types/NodeDBGenerator.cs
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace ComfySharp.Types;
|
||||||
|
|
||||||
|
public class NodeDBGenerator {
|
||||||
|
private List<ExpandoObject> nodes;
|
||||||
|
|
||||||
|
private List<string> knownTypes = new();
|
||||||
|
public List<string> GetKnownTypes() => knownTypes;
|
||||||
|
|
||||||
|
private Dictionary<string, List<string>> knownEnums = new();
|
||||||
|
public Dictionary<string, List<string>> GetKnownEnums() => knownEnums;
|
||||||
|
|
||||||
|
public int Count => nodes.Count;
|
||||||
|
private int typeFields = 0;
|
||||||
|
private int enumFields = 0;
|
||||||
|
|
||||||
|
public NodeDBGenerator() {
|
||||||
|
nodes = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetDb() => nodes.Clear();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new type to the list of known types, avoids duplicates
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">type name as string</param>
|
||||||
|
private void AddKnownType(string type) {
|
||||||
|
if (!knownTypes.Contains(type)) {
|
||||||
|
knownTypes.Add(type);
|
||||||
|
Console.WriteLine("Added new known type: {0}", type);
|
||||||
|
} else {
|
||||||
|
Console.WriteLine("Type {0} already known, skipped.", type);
|
||||||
|
}
|
||||||
|
typeFields++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds or updates a known enum, avoids duplicates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">enum type name as string</param>
|
||||||
|
/// <param name="values">Collection of valid string values for this enum</param>
|
||||||
|
private void AddKnownEnum(string type, ICollection<string> values) {
|
||||||
|
if (!knownEnums.ContainsKey(type)) {
|
||||||
|
knownEnums.Add(type, values.ToList());
|
||||||
|
Console.WriteLine("Added new known enum: {0}", type);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
values.ToList().ForEach(value => {
|
||||||
|
if (!knownEnums[type].Contains(value)) {
|
||||||
|
knownEnums[type].Add(value);
|
||||||
|
Console.WriteLine("Added new value to known enum: {0}", value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
enumFields++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateClasses(JsonDocument document) {
|
||||||
|
foreach (var node in document.RootElement.EnumerateObject()) ScanNode(node);
|
||||||
|
|
||||||
|
Console.WriteLine("List of recognized Types:");
|
||||||
|
foreach (var knownType in knownTypes) {
|
||||||
|
Console.WriteLine(knownType);
|
||||||
|
}
|
||||||
|
Console.WriteLine("\nTotal amount of types iterated: {0}\n", typeFields);
|
||||||
|
Console.WriteLine("List of recognized Enums:");
|
||||||
|
foreach (var knownEnum in knownEnums) {
|
||||||
|
Console.WriteLine(knownEnum.Key);
|
||||||
|
foreach (var value in knownEnum.Value) {
|
||||||
|
Console.Write("\t{0}", value);
|
||||||
|
}
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
Console.WriteLine("\nTotal amount of enums iterated: {0}\n", enumFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// executed for a single node, progresses through the properties of the node
|
||||||
|
/// </summary>
|
||||||
|
private void ScanNode(JsonProperty node) {
|
||||||
|
// each of this are top level properties of the node
|
||||||
|
foreach (var property in node.Value.EnumerateObject()) {
|
||||||
|
//if this is a list of input properties:
|
||||||
|
if (property.Name == "input" && property.Value.ValueKind == JsonValueKind.Object) ScanInputs(property);
|
||||||
|
else if (property.Name == "output" && property.Value.ValueKind == JsonValueKind.Array) ScanOutputs(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executed on the input property inside a node
|
||||||
|
/// </summary>
|
||||||
|
private void ScanInputs(JsonProperty input) {
|
||||||
|
foreach (var inputType in input.Value.EnumerateObject()) {
|
||||||
|
//these are related to the nodes themselves and useless for us
|
||||||
|
if (inputType.Name == "hidden") continue;
|
||||||
|
// required and optionals have the same structure, so we can parse them the same way
|
||||||
|
if (inputType.Name == "required" || inputType.Name == "optional")
|
||||||
|
foreach (var inputProperty in inputType.Value.EnumerateObject()) ScanInputField(inputProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executed for each of the elements inside a required or optional input
|
||||||
|
/// </summary>
|
||||||
|
private void ScanInputField(JsonProperty inputProperty) {
|
||||||
|
// if element 0 is a string, this is a type
|
||||||
|
if (inputProperty.Value[0].ValueKind == JsonValueKind.String)
|
||||||
|
AddKnownType(inputProperty.Value[0].ToString());
|
||||||
|
// else, if element 0 is an array, this is an enum
|
||||||
|
else if (inputProperty.Value[0].ValueKind == JsonValueKind.Array) {
|
||||||
|
List<string> enumValues = new();
|
||||||
|
inputProperty.Value[0].EnumerateArray().ToList().ForEach(value => enumValues.Add(value.ToString()));
|
||||||
|
AddKnownEnum(inputProperty.Name, enumValues);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ScanOutputs(JsonProperty output) { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void GenerateNode(JsonElement data) {
|
||||||
|
var node = new ExpandoObject();
|
||||||
|
Console.WriteLine("Generating node: {0}", data.GetProperty("name").GetString() ?? "");
|
||||||
|
foreach (var property in data.EnumerateObject()) {
|
||||||
|
Console.WriteLine("Adding new property: {0}\nType: {2}\nValue: {1}\n", property.Name, property.Value, property.Value.GetType());
|
||||||
|
node.TryAdd(property.Name, property.Value);
|
||||||
|
}
|
||||||
|
nodes.Add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateNode(JsonProperty node) {
|
||||||
|
GenerateNode(node.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateNodes(JsonDocument document) {
|
||||||
|
foreach (var node in document.RootElement.EnumerateObject()) {
|
||||||
|
GenerateNode(node.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateNodes(string json) {
|
||||||
|
var document = JsonDocument.Parse(json);
|
||||||
|
GenerateNodes(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateNodes(ICollection<JsonElement> elements) {
|
||||||
|
foreach (var element in elements) {
|
||||||
|
GenerateNode(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateNodes(ICollection<JsonProperty> elements) {
|
||||||
|
foreach (var element in elements) {
|
||||||
|
GenerateNode(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ExpandoObject> GetNodes() => nodes;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user