Modelium Visualization Ongoing Project, Any ideas and updates?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modelium Designer</title>
    <link rel="stylesheet" href="https://unpkg.com/vis-network/styles/vis-network.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            height: 100vh;
            background-color: #f0f0f0; /* Light gray background */
            color: #333; /* Dark gray text */
        }

        .main-container {
            display: flex;
            height: 100%; /* Make the main container fill the entire viewport */
        }

        #modelium-container {
            flex-grow: 1;
            border: 1px solid #ccc;
            background-color: #fff; /* White network container */
        }

        #sidebar {
            width: 300px;
            background-color: #fff; /* White sidebar */
            padding: 20px;
            overflow-y: auto;
            display: flex;
            flex-direction: column; /* Stack elements vertically */
            box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1); /* Subtle shadow */
        }

        #sidebar-menu {
            flex-grow: 1; /* Allow the menu to take up available space */
            padding-bottom: 20px; /* Add padding at the bottom */
        }

        .node-type {
            padding: 10px;
            border: 1px solid #ccc;
            margin-bottom: 5px;
            cursor: pointer;
            background-color: #eee;
            border-radius: 5px; /* Rounded corners */
            transition: background-color 0.2s ease; /* Smooth transition for hover effect */
        }

            .node-type:hover {
                background-color: #ddd;
            }

        #properties {
            margin-top: 20px;
        }

        #node-properties h3 {
            margin-top: 0;
            color: #333; /* Darker gray for headings */
            font-weight: bold;
        }

        #node-properties label {
            display: block;
            margin-bottom: 5px;
            color: #333;
        }

        #node-properties input,
        #node-properties textarea,
        #node-properties select {
            width: 100%;
            padding: 8px;
            margin-bottom: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
            background-color: #f8f8f8; /* Light gray input background */
            color: #333;
        }

        .modelium-to-model {
            color: #f39c12;
            width: 3px;
        }

            .modelium-to-model .vis-edge .vis-line {
                stroke-dasharray: 5, 5;
            }

        #sidebar button {
            padding: 8px 15px;
            background-color: #3498db; /* Blue button */
            color: white;
            border: none;
            cursor: pointer;
            border-radius: 5px;
            margin-bottom: 10px;
            transition: background-color 0.2s ease;
        }

            #sidebar button:hover {
                background-color: #2980b9; /* Darker blue on hover */
            }

        .node-icon {
            position: absolute;
            top: -10px;
            right: -10px;
            width: 20px;
            height: 20px;
            background-size: cover;
        }

        .tools-icon {
            background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAjklEQVR4nO3UQQqDMBCF4X+yCXgQ7yEIgu4KvULXbQW9/26KCSWSlEKpC1cDswj5mMwbQoxxwWtaawvr7+xYa21pCYEHjtivtTiDz5RSqfSctR0X5JzPD+NKqTp0xLRjWlzQe7+WUnZCiA0ppQ0hxK6UsvfeX//6XT/ihjue0Fq71VrXEMKhtfZijLl9Mz8BmI0StacvT10AAAAASUVORK5CYII=');
        }

        .parallel-icon {
            background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAV0lEQVR4nGNgGAWjYKiD/wDMQKwCZD4TsS4k1jByDWMiRhGxLiTFMCZiFRHrQlINYyJGEbEuJMcwJkIKiXUhuYYx4VNIiovINYyJkEJiXUiJYaNgZAMAYnAb1CJ5IcEAAAAASUVORK5CYII=');
        }

        #sidebar .vis-network {
            display: none; /* Hide the Vis.js network from the sidebar */
        }
    </style>
</head>
<body>
    <div class="main-container">
        <div id="modelium-container"></div>
        <div id="sidebar">
            <div id="sidebar-menu">
                <h2>Elements</h2>
                <div class="node-type" draggable="true" data-type="modelium">Modelium</div>
                <div class="node-type" draggable="true" data-type="model">Model</div>
                <div class="node-type" draggable="true" data-type="result">Result</div>
                <div class="node-type" draggable="true" data-type="return">Return</div>

                <h2>Display Options</h2>
                <label><input type="checkbox" id="show-prompt" onchange="updateModelLabels()"> Show Prompt</label><br>
                <label><input type="checkbox" id="show-system-instructions" onchange="updateModelLabels()"> Show System Instructions</label><br>
                <label><input type="checkbox" id="show-tools" onchange="updateModelLabels()"> Show Tools</label><br>
                <label><input type="checkbox" id="show-model-type" onchange="updateModelLabels()"> Show Model Type</label><br>
            </div>
            <div id="properties">
                <h2>Properties</h2>
                <div id="node-properties"></div>
            </div>
            <button id="generate-description-button" onclick="generateAndDisplayStructuredDescription()">Generate Structured Description</button>
        </div>
    </div>

    <script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
    <script>
        let nodes = new vis.DataSet([]);
        let edges = new vis.DataSet([]);
        let network = null;
        let lastNodeId = 0;

        function initNetwork() {
            const container = document.getElementById('modelium-container');
            const data = { nodes, edges };
            const options = {
                manipulation: {
                    enabled: true,
                    addNode: false,
                    addEdge: function (edgeData, callback) {
                        if (edgeData.from !== edgeData.to) {
                            const fromNode = nodes.get(edgeData.from);
                            const toNode = nodes.get(edgeData.to);
                            if (fromNode.type === 'modelium' && toNode.type === 'model' && toNode.parentId === fromNode.id) {
                                edgeData.classes = 'modelium-to-model';
                            }
                            callback(edgeData);
                        }
                    }
                },
                nodes: {
                    shape: 'box',
                    size: 30,
                    font: { size: 12, color: '#ffffff' },
                    borderWidth: 2,
                    shadow: true,
                    color: {
                        'modelium': {
                            background: '#f1c40f',
                            border: '#f39c12'
                        },
                        'model': {
                            background: '#3498db',
                            border: '#2980b9'
                        },
                        'result': {
                            background: '#2ecc71',
                            border: '#27ae60'
                        },
                        'return': {
                            background: '#27ae60',
                            border: '#1e8449'
                        }
                    }
                },
                edges: {
                    arrows: {
                        to: { enabled: true, scaleFactor: 1 },
                        middle: { enabled: true, scaleFactor: 0.5 }
                    },
                    smooth: { type: 'dynamic' },
                    color: { color: '#848484', highlight: '#848484', hover: '#848484' },
                    width: 2
                },
                physics: { enabled: false },
                interaction: { hover: true }
            };
            network = new vis.Network(container, data, options);

            network.on("click", function (params) {
                if (params.nodes.length > 0) {
                    showNodeProperties(params.nodes[0]);
                } else {
                    clearProperties();
                }
            });

            setupDragAndDrop();

            network.on("edgeAdded", function (params) {
                adjustModeliumStructure();
            });
            network.on("edgeRemoved", function (params) {
                adjustModeliumStructure();
            });
        }

        function setupDragAndDrop() {
            const container = document.getElementById('modelium-container');
            container.ondragover = function (e) { e.preventDefault(); };
            container.ondrop = function (e) {
                e.preventDefault();
                const type = e.dataTransfer.getData("text");
                const pos = network.DOMtoCanvas({ x: e.clientX, y: e.clientY });
                addNewNode(type, pos.x, pos.y);
            };

            const nodeTypes = document.getElementsByClassName('node-type');
            for (let nodeType of nodeTypes) {
                nodeType.ondragstart = function (e) {
                    e.dataTransfer.setData("text", this.dataset.type);
                };
            }
        }

        function addNewNode(type, x, y) {
            if (type === 'modelium') {
                lastNodeId++;
                const modeliumNode = {
                    id: lastNodeId,
                    label: 'Modelium',
                    x: x,
                    y: y,
                    type: 'modelium',
                    group: 'modelium',
                    chainLength: 1,
                    loopCount: 0,
                    parallelCount: 1,
                    modeliumType: 'standard',
                    structureDescription: "",
                    nestedModeliums: []
                };
                if (modeliumNode.parallelCount > 1) {
                    modeliumNode.shape = 'box';
                    modeliumNode.shapeProperties = { borderDashes: [5, 5] };
                    modeliumNode.icon = {
                        face: 'FontAwesome',
                        code: '\uf126',
                        size: 50,
                        color: '#000000'
                    };
                }
                nodes.add(modeliumNode);
                createModeliumStructure(modeliumNode);
            } else if (type === 'model') {
                lastNodeId++;
                let label = 'Model';
                if (document.getElementById('show-prompt').checked) label += '\nPrompt: N/A';
                if (document.getElementById('show-system-instructions').checked) label += '\nSys Instr: N/A';
                if (document.getElementById('show-tools').checked) label += '\nTools: N/A';
                if (document.getElementById('show-model-type').checked) label += '\nType: N/A';

                const modelNode = {
                    id: lastNodeId,
                    label: label,
                    x: x,
                    y: y,
                    type: 'model',
                    group: 'model',
                    system_instructions: "",
                    prompts: "",
                    model_type: "",
                    tools: "none"
                };
                if (modelNode.tools !== 'none') {
                    modelNode.shape = 'box';
                    modelNode.shapeProperties = { borderDashes: [5, 5] };
                    modelNode.icon = {
                        face: 'FontAwesome',
                        code: '\uf0ad',
                        size: 50,
                        color: '#000000'
                    };
                }
                nodes.add(modelNode);
                updateModelLabels(modelNode); // Update label after adding model node
            } else if (type === 'result') {
                lastNodeId++;
                const resultNode = {
                    id: lastNodeId,
                    label: 'Result',
                    x: x,
                    y: y,
                    type: 'result',
                    group: 'result'
                };
                nodes.add(resultNode);
            } else if (type === 'return') {
                lastNodeId++;
                const returnNode = {
                    id: lastNodeId,
                    label: 'Return',
                    x: x,
                    y: y,
                    type: 'return',
                    group: 'return'
                };
                nodes.add(returnNode);
            }
        }

        function createModeliumStructure(modelium) {
            const modelCount = modelium.chainLength * modelium.parallelCount;
            const baseX = modelium.x;
            const baseY = modelium.y + 100;
            let firstModelIds = [];
            let lastModelIds = [];
            let resultNodeIds = [];

            lastNodeId++;
            const returnNode = {
                id: lastNodeId,
                label: 'Return',
                type: 'return',
                parentId: modelium.id,
                x: baseX + (modelium.parallelCount * 150) / 2,
                y: baseY + (modelium.chainLength + 1) * 100,
                group: 'return'
            };
            nodes.add(returnNode);

            for (let j = 0; j < modelium.parallelCount; j++) {
                let lastModelId = modelium.id;
                let xOffset = j * 150 - ((modelium.parallelCount - 1) * 75);

                for (let i = 0; i < modelium.chainLength; i++) {
                    lastNodeId++;
                    const modelNode = {
                        id: lastNodeId,
                        label: 'Model',
                        type: 'model',
                        parentId: modelium.id,
                        x: baseX + xOffset,
                        y: baseY + (i * 100),
                        group: 'model',
                        system_instructions: "",
                        prompts: "",
                        model_type: "",
                        tools: "none"
                    };
                    if (document.getElementById('show-prompt').checked) modelNode.label += '\nPrompt: ' + (modelNode.prompts || 'N/A');
                    if (document.getElementById('show-system-instructions').checked) modelNode.label += '\nSys Instr: ' + (modelNode.system_instructions || 'N/A');
                    if (document.getElementById('show-tools').checked) modelNode.label += '\nTools: ' + (modelNode.tools || 'N/A');
                    if (document.getElementById('show-model-type').checked) modelNode.label += '\nType: ' + (modelNode.model_type || 'N/A');
                    if (modelNode.tools !== 'none') {
                        modelNode.shape = 'box';
                        modelNode.shapeProperties = { borderDashes: [5, 5] };
                        modelNode.icon = {
                            face: 'FontAwesome',
                            code: '\uf0ad',
                            size: 50,
                            color: '#000000'
                        };
                    }
                    nodes.add(modelNode);

                    if (i === 0) {
                        edges.add({
                            from: modelium.id,
                            to: modelNode.id,
                            classes: 'modelium-to-model'
                        });
                        firstModelIds.push(modelNode.id);
                    } else {
                        edges.add({
                            from: lastModelId,
                            to: modelNode.id
                        });
                    }
                    lastModelId = modelNode.id;
                }

                lastNodeId++;
                const resultNode = {
                    id: lastNodeId,
                    label: 'Result',
                    type: 'result',
                    parentId: modelium.id,
                    x: baseX + xOffset,
                    y: baseY + (modelium.chainLength * 100),
                    group: 'result'
                };
                nodes.add(resultNode);
                resultNodeIds.push(resultNode.id);

                edges.add({
                    from: lastModelId,
                    to: resultNode.id
                });
                lastModelIds.push(resultNode.id);
            }

            resultNodeIds.forEach(resultNodeId => {
                edges.add({
                    from: resultNodeId,
                    to: returnNode.id
                });
            });

            if (modelium.modeliumType === 'chainLoop' && modelium.loopCount > 0) {
                lastModelIds.forEach((lastModelId, index) => {
                    const firstModelId = firstModelIds[index];
                    edges.add({
                        id: `loop-${lastModelId}-${firstModelId}`,
                        from: lastModelId,
                        to: firstModelId,
                        smooth: {
                            type: 'curvedCW',
                            roundness: 0.3
                        },
                        label: `x${modelium.loopCount}`,
                        font: { size: 10, color: '#848484' },
                        color: { color: '#848484' },
                        dashes: [5, 5],
                        arrows: { to: { enabled: true, scaleFactor: 0.5 } }
                    });
                });
            }

            modelium.structureDescription = generateStructuredDescription(modelium);
            nodes.update(modelium);
        }

        function generateStructuredDescription(modelium) {
            let schema = {
                type: modelium.modeliumType,
                name: modelium.label, // Include the name of the Modelium
                chainLength: modelium.chainLength,
                parallelCount: modelium.parallelCount,
                loopCount: modelium.loopCount,
                models: [],
                results: [],
                returns: [],
                nestedModeliums: []
            };

            const childNodes = nodes.get({
                filter: function (node) {
                    return node.parentId === modelium.id;
                }
            });

            childNodes.forEach(node => {
                switch (node.type) {
                    case 'model':
                        schema.models.push({
                            id: node.id,
                            systemInstructions: node.system_instructions,
                            prompts: node.prompts,
                            modelType: node.model_type,
                            tools: node.tools
                        });
                        break;
                    case 'result':
                        schema.results.push({ id: node.id });
                        break;
                    case 'return':
                        schema.returns.push({ id: node.id });
                        break;
                    case 'modelium':
                        // Recursively call generateStructuredDescription for nested Modeliums
                        schema.nestedModeliums.push(generateStructuredDescription(node));
                        break;
                }
            });

            return schema;
        }

        function generateAndDisplayStructuredDescription() {
            const modeliumNodes = nodes.get({
                filter: function (node) {
                    return node.type === 'modelium';
                }
            });

            if (modeliumNodes.length === 0) {
                alert('No Modelium node found!');
                return;
            }

            const rootModelium = modeliumNodes.reduce((prev, current) =>
                (prev.y < current.y) ? prev : current
            );

            const structuredDescription = generateStructuredDescription(rootModelium);
            document.getElementById('structureDescription').value = JSON.stringify(structuredDescription, null, 2);
        }

        function clearProperties() {
            document.getElementById('node-properties').innerHTML = '';
        }

        function showNodeProperties(nodeId) {
            const node = nodes.get(nodeId);
            const propertiesDiv = document.getElementById('node-properties');
            propertiesDiv.innerHTML = `<h3>${node.label} Properties</h3>`;

            if (node.type === 'modelium') {
                propertiesDiv.innerHTML += `
                            <label for="modeliumName">Name:</label><br>
                            <input type="text" id="modeliumName" value="${node.label}"><br>
                            <label for="chainLength">Chain Length:</label>
                            <input type="number" id="chainLength" value="${node.chainLength}" min="1"><br>
                            <label for="loopCount">Loop Count:</label>
                            <input type="number" id="loopCount" value="${node.loopCount}" min="0"><br>
                            <label for="parallelCount">Parallel Count:</label>
                            <input type="number" id="parallelCount" value="${node.parallelCount}" min="1"><br>
                            <label for="modeliumType">Modelium Type:</label><br>
                            <select id="modeliumType">
                                <option value="standard" ${node.modeliumType === 'standard' ? 'selected' : ''}>Standard</option>
                                <option value="chainLoop" ${node.modeliumType === 'chainLoop' ? 'selected' : ''}>Chain Loop</option>
                                <option value="hierarchical" ${node.modeliumType === 'hierarchical' ? 'selected' : ''}>Hierarchical</option>
                            </select><br>
                            <button onclick="updateModeliumProperties(${nodeId})">Update Properties</button><br>
                            <button onclick="generateAndDisplayStructuredDescription(${nodeId})">Generate Structured Description</button><br>
                            <label for="structureDescription">Structure Description:</label><br>
                            <textarea id="structureDescription" readonly style="width: 100%; height: 200px;"></textarea><br>
                        `;
            } else if (node.type === 'model') {
                propertiesDiv.innerHTML += `
                                    <label for="system_instructions">System Instructions:</label><br>
                                    <textarea id="system_instructions">${node.system_instructions || ''}</textarea><br>
                                    <label for="prompts">Prompts:</label><br>
                                    <textarea id="prompts">${node.prompts || ''}</textarea><br>
                                    <label for="model_type">Model Type:</label><br>
                                    <input type="text" id="model_type" value="${node.model_type || ''}"><br>
                                    <label for="tools">Tools:</label><br>
                                    <select id="tools">
                                        <option value="none" ${node.tools === 'none' ? 'selected' : ''}>None</option>
                                        <option value="all" ${node.tools === 'all' ? 'selected' : ''}>All</option>
                                        <option value="chooser" ${node.tools === 'chooser' ? 'selected' : ''}>Chooser</option>
                                    </select><br>
                                    <button onclick="updateModelProperties(${nodeId})">Update</button>
                                `;
            }
        }

        function updateModeliumProperties(nodeId) {
            const node = nodes.get(nodeId);
            node.label = document.getElementById('modeliumName').value;
            node.chainLength = parseInt(document.getElementById('chainLength').value);
            node.loopCount = parseInt(document.getElementById('loopCount').value);
            node.parallelCount = parseInt(document.getElementById('parallelCount').value);
            node.modeliumType = document.getElementById('modeliumType').value;
            nodes.update(node);

            // Remove existing child nodes and edges
            const childNodes = nodes.get({
                filter: function (node) {
                    return node.parentId === nodeId;
                }
            });
            nodes.remove(childNodes.map(node => node.id));
            edges.remove(edges.getIds({
                filter: function (edge) {
                    return childNodes.some(node => node.id === edge.from || node.id === edge.to);
                }
            }));

            // Recreate the structure based on updated properties
            createModeliumStructure(node);
        }

        function updateModelProperties(nodeId) {
            const node = nodes.get(nodeId);
            node.system_instructions = document.getElementById('system_instructions').value;
            node.prompts = document.getElementById('prompts').value;
            node.model_type = document.getElementById('model_type').value;
            node.tools = document.getElementById('tools').value;
            nodes.update(node);

            // Update the label after updating properties
            updateModelLabels(node);
        }

        // Function to adjust the Modelium structure for better visualization
        function adjustModeliumStructure() {
            // You can implement various logic here based on your visualization needs
            // Example:
            // 1. Use a layout algorithm (e.g., from vis.js or other libraries)
            // 2. Manually reposition nodes based on their connections and depth
            // 3. Adjust edge smoothness or curvature for better appearance

            // For now, a simple repositioning example:
            const allNodes = nodes.get();
            let maxX = 0;
            allNodes.forEach(node => {
                if (node.x > maxX) {
                    maxX = node.x;
                }
            });
            allNodes.forEach(node => {
                node.x = maxX + 100;
                nodes.update(node);
            });
        }

        function updateModelLabels(node = null) {
            const showPrompt = document.getElementById('show-prompt').checked;
            const showSystemInstructions = document.getElementById('show-system-instructions').checked;
            const showTools = document.getElementById('show-tools').checked;
            const showModelType = document.getElementById('show-model-type').checked;

            if (!node) { // If no specific node is passed, update all model nodes
                const modelNodes = nodes.get({ filter: n => n.type === 'model' });
                modelNodes.forEach(modelNode => {
                    updateModelLabels(modelNode); // Call recursively to update each model node
                });
                return;
            }

            let label = 'Model';
            if (showPrompt) label += '\nPrompt: ' + (node.prompts || 'N/A');
            if (showSystemInstructions) label += '\nSys Instr: ' + (node.system_instructions || 'N/A');
            if (showTools) label += '\nTools: ' + (node.tools || 'N/A');
            if (showModelType) label += '\nType: ' + (node.model_type || 'N/A');

            node.label = label;
            nodes.update(node);
        }

        initNetwork();
    </script>
</body>
</html>
1 Like
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modelium Designer</title>
    <link rel="stylesheet" href="https://unpkg.com/vis-network/styles/vis-network.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            height: 100vh;
            background-color: #181818; /* Dark gray background */
            color: #eee; /* Light gray text */
        }

        .main-container {
            display: flex;
            height: 100%;
        }

        #modelium-container {
            flex-grow: 1;
            border: 1px solid #333;
            background-color: #282828; /* Darker gray network container */
        }

        #sidebar {
            width: 300px;
            background-color: #282828; /* Darker gray sidebar */
            padding: 20px;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
            box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2);
        }

        #sidebar-menu {
            flex-grow: 1;
            padding-bottom: 20px;
        }

        .node-type {
            padding: 10px;
            border: 1px solid #333;
            margin-bottom: 5px;
            cursor: pointer;
            background-color: #333;
            border-radius: 5px;
            transition: background-color 0.2s ease;
        }

            .node-type:hover {
                background-color: #444;
            }

        #properties {
            margin-top: 20px;
        }

        #node-properties h3 {
            margin-top: 0;
            color: #eee;
            font-weight: bold;
        }

        #node-properties label {
            display: block;
            margin-bottom: 5px;
            color: #eee;
        }

        #node-properties input,
        #node-properties textarea,
        #node-properties select {
            width: 100%;
            padding: 8px;
            margin-bottom: 10px;
            border: 1px solid #555;
            border-radius: 5px;
            background-color: #222; /* Darker gray input background */
            color: #eee;
        }

        .modelium-to-model {
            color: #f39c12;
            width: 3px;
        }

            .modelium-to-model .vis-edge .vis-line {
                stroke-dasharray: 5, 5;
            }

        #sidebar button {
            padding: 8px 15px;
            background-color: #3498db;
            color: white;
            border: none;
            cursor: pointer;
            border-radius: 5px;
            margin-bottom: 10px;
            transition: background-color 0.2s ease;
        }

            #sidebar button:hover {
                background-color: #2980b9;
            }

        .node-icon {
            position: absolute;
            top: -10px;
            right: -10px;
            width: 20px;
            height: 20px;
            background-size: cover;
        }

        .tools-icon {
            background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAjklEQVR4nO3UQQqDMBCF4X+yCXgQ7yEIgu4KvULXbQW9/26KCSWSlEKpC1cDswj5mMwbQoxxwWtaawvr7+xYa21pCYEHjtivtTiDz5RSqfSctR0X5JzPD+NKqTp0xLRjWlzQe7+WUnZCiA0ppQ0hxK6UsvfeX//6XT/ihjue0Fq71VrXEMKhtfZijLl9Mz8BmI0StacvT10AAAAASUVORK5CYII=');
        }

        .parallel-icon {
            background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAV0lEQVR4nGNgGAWjYKiD/wDMQKwCZD4TsS4k1jByDWMiRhGxLiTFMCZiFRHrQlINYyJGEbEuJMcwJkIKiXUhuYYx4VNIiovINYyJkEJiXUiJYaNgZAMAYnAb1CJ5IcEAAAAASUVORK5CYII=');
        }

        #sidebar .vis-network {
            display: none;
        }

        /* Node Colors */
        .vis-node.modelium {
            background-color: #f1c40f; /* Yellowish */
            border-color: #f39c12; /* Darker yellow */
        }

        .vis-node.model {
            background-color: #3498db; /* Blue */
            border-color: #2980b9; /* Darker blue */
        }

        .vis-node.result {
            background-color: #2ecc71; /* Green */
            border-color: #27ae60; /* Darker green */
        }

        .vis-node.return {
            background-color: #27ae60; /* Green */
            border-color: #1e8449; /* Darker green */
        }

        /* Node Text Color */
        .vis-node .vis-label {
            color: #000; /* Black */
        }
    </style>
</head>
<body>
    <div class="main-container">
        <div id="modelium-container"></div>
        <div id="sidebar">
            <div id="sidebar-menu">
                <h2>Elements</h2>
                <div class="node-type" draggable="true" data-type="modelium">Modelium</div>
                <div class="node-type" draggable="true" data-type="model">Model</div>
                <div class="node-type" draggable="true" data-type="result">Result</div>
                <div class="node-type" draggable="true" data-type="return">Return</div>

                <h2>Display Options</h2>
                <label><input type="checkbox" id="show-prompt" onchange="updateModelLabels()"> Show Prompt</label><br>
                <label><input type="checkbox" id="show-system-instructions" onchange="updateModelLabels()"> Show System Instructions</label><br>
                <label><input type="checkbox" id="show-tools" onchange="updateModelLabels()"> Show Tools</label><br>
                <label><input type="checkbox" id="show-model-type" onchange="updateModelLabels()"> Show Model Type</label><br>
            </div>
            <div id="properties">
                <h2>Properties</h2>
                <div id="node-properties"></div>
            </div>
            <button id="generate-description-button" onclick="generateAndDisplayStructuredDescription()">Generate Structured Description</button>
        </div>
    </div>

    <script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
    <script>
        let nodes = new vis.DataSet([]);
        let edges = new vis.DataSet([]);
        let network = null;
        let lastNodeId = 0;

        function initNetwork() {
            const container = document.getElementById('modelium-container');
            const data = { nodes, edges };
            const options = {
                manipulation: {
                    enabled: true,
                    addNode: false,
                    addEdge: function (edgeData, callback) {
                        if (edgeData.from !== edgeData.to) {
                            const fromNode = nodes.get(edgeData.from);
                            const toNode = nodes.get(edgeData.to);
                            if (fromNode.type === 'modelium' && toNode.type === 'model' && toNode.parentId === fromNode.id) {
                                edgeData.classes = 'modelium-to-model';
                            }
                            callback(edgeData);
                        }
                    }
                },
                nodes: {
                    shape: 'box',
                    size: 30,
                    font: { size: 12, color: '#000000' }, // Black text
                    borderWidth: 2,
                    shadow: true,
                    color: {
                        'modelium': {
                            background: '#f1c40f',
                            border: '#f39c12'
                        },
                        'model': {
                            background: '#3498db',
                            border: '#2980b9'
                        },
                        'result': {
                            background: '#2ecc71',
                            border: '#27ae60'
                        },
                        'return': {
                            background: '#27ae60',
                            border: '#1e8449'
                        }
                    }
                },
                edges: {
                    arrows: {
                        to: { enabled: true, scaleFactor: 1 },
                        middle: { enabled: true, scaleFactor: 0.5 }
                    },
                    smooth: { type: 'dynamic' },
                    color: { color: '#848484', highlight: '#848484', hover: '#848484' },
                    width: 2
                },
                physics: { enabled: false },
                interaction: { hover: true }
            };
            network = new vis.Network(container, data, options);

            network.on("click", function (params) {
                if (params.nodes.length > 0) {
                    showNodeProperties(params.nodes[0]);
                } else {
                    clearProperties();
                }
            });

            setupDragAndDrop();

            network.on("edgeAdded", function (params) {
                adjustModeliumStructure();
            });
            network.on("edgeRemoved", function (params) {
                adjustModeliumStructure();
            });
        }

        function setupDragAndDrop() {
            const container = document.getElementById('modelium-container');
            container.ondragover = function (e) { e.preventDefault(); };
            container.ondrop = function (e) {
                e.preventDefault();
                const type = e.dataTransfer.getData("text");
                const pos = network.DOMtoCanvas({ x: e.clientX, y: e.clientY });
                addNewNode(type, pos.x, pos.y);
            };

            const nodeTypes = document.getElementsByClassName('node-type');
            for (let nodeType of nodeTypes) {
                nodeType.ondragstart = function (e) {
                    e.dataTransfer.setData("text", this.dataset.type);
                };
            }
        }

        function addNewNode(type, x, y) {
            if (type === 'modelium') {
                lastNodeId++;
                const modeliumNode = {
                    id: lastNodeId,
                    label: 'Modelium',
                    x: x,
                    y: y,
                    type: 'modelium',
                    group: 'modelium',
                    chainLength: 1,
                    loopCount: 0,
                    parallelCount: 1,
                    modeliumType: 'standard',
                    structureDescription: "",
                    nestedModeliums: []
                };
                if (modeliumNode.parallelCount > 1) {
                    modeliumNode.shape = 'box';
                    modeliumNode.shapeProperties = { borderDashes: [5, 5] };
                    modeliumNode.icon = {
                        face: 'FontAwesome',
                        code: '\uf126',
                        size: 50,
                        color: '#000000'
                    };
                }
                nodes.add(modeliumNode);
                createModeliumStructure(modeliumNode);
            } else if (type === 'model') {
                lastNodeId++;
                let label = 'Model';
                if (document.getElementById('show-prompt').checked) label += '\nPrompt: N/A';
                if (document.getElementById('show-system-instructions').checked) label += '\nSys Instr: N/A';
                if (document.getElementById('show-tools').checked) label += '\nTools: N/A';
                if (document.getElementById('show-model-type').checked) label += '\nType: N/A';

                const modelNode = {
                    id: lastNodeId,
                    label: label,
                    x: x,
                    y: y,
                    type: 'model',
                    group: 'model',
                    system_instructions: "",
                    prompts: "",
                    model_type: "",
                    tools: "none"
                };
                if (modelNode.tools !== 'none') {
                    modelNode.shape = 'box';
                    modelNode.shapeProperties = { borderDashes: [5, 5] };
                    modelNode.icon = {
                        face: 'FontAwesome',
                        code: '\uf0ad',
                        size: 50,
                        color: '#000000'
                    };
                }
                nodes.add(modelNode);
                updateModelLabels(modelNode); // Update label after adding model node
            } else if (type === 'result') {
                lastNodeId++;
                const resultNode = {
                    id: lastNodeId,
                    label: 'Result',
                    x: x,
                    y: y,
                    type: 'result',
                    group: 'result'
                };
                nodes.add(resultNode);
            } else if (type === 'return') {
                lastNodeId++;
                const returnNode = {
                    id: lastNodeId,
                    label: 'Return',
                    x: x,
                    y: y,
                    type: 'return',
                    group: 'return'
                };
                nodes.add(returnNode);
            }
        }

        function createModeliumStructure(modelium) {
            const modelCount = modelium.chainLength * modelium.parallelCount;
            const baseX = modelium.x;
            const baseY = modelium.y + 100;
            let firstModelIds = [];
            let lastModelIds = [];
            let resultNodeIds = [];

            lastNodeId++;
            const returnNode = {
                id: lastNodeId,
                label: 'Return',
                type: 'return',
                parentId: modelium.id,
                x: baseX + (modelium.parallelCount * 150) / 2,
                y: baseY + (modelium.chainLength + 1) * 100,
                group: 'return'
            };
            nodes.add(returnNode);

            for (let j = 0; j < modelium.parallelCount; j++) {
                let lastModelId = modelium.id;
                let xOffset = j * 150 - ((modelium.parallelCount - 1) * 75);

                for (let i = 0; i < modelium.chainLength; i++) {
                    lastNodeId++;
                    const modelNode = {
                        id: lastNodeId,
                        label: 'Model',
                        type: 'model',
                        parentId: modelium.id,
                        x: baseX + xOffset,
                        y: baseY + (i * 100),
                        group: 'model',
                        system_instructions: "",
                        prompts: "",
                        model_type: "",
                        tools: "none"
                    };
                    if (document.getElementById('show-prompt').checked) modelNode.label += '\nPrompt: ' + (modelNode.prompts || 'N/A');
                    if (document.getElementById('show-system-instructions').checked) modelNode.label += '\nSys Instr: ' + (modelNode.system_instructions || 'N/A');
                    if (document.getElementById('show-tools').checked) modelNode.label += '\nTools: ' + (modelNode.tools || 'N/A');
                    if (document.getElementById('show-model-type').checked) modelNode.label += '\nType: ' + (modelNode.model_type || 'N/A');
                    if (modelNode.tools !== 'none') {
                        modelNode.shape = 'box';
                        modelNode.shapeProperties = { borderDashes: [5, 5] };
                        modelNode.icon = {
                            face: 'FontAwesome',
                            code: '\uf0ad',
                            size: 50,
                            color: '#000000'
                        };
                    }
                    nodes.add(modelNode);

                    if (i === 0) {
                        edges.add({
                            from: modelium.id,
                            to: modelNode.id,
                            classes: 'modelium-to-model'
                        });
                        firstModelIds.push(modelNode.id);
                    } else {
                        edges.add({
                            from: lastModelId,
                            to: modelNode.id
                        });
                    }
                    lastModelId = modelNode.id;
                }

                lastNodeId++;
                const resultNode = {
                    id: lastNodeId,
                    label: 'Result',
                    type: 'result',
                    parentId: modelium.id,
                    x: baseX + xOffset,
                    y: baseY + (modelium.chainLength * 100),
                    group: 'result'
                };
                nodes.add(resultNode);
                resultNodeIds.push(resultNode.id);

                edges.add({
                    from: lastModelId,
                    to: resultNode.id
                });
                lastModelIds.push(resultNode.id);
            }

            resultNodeIds.forEach(resultNodeId => {
                edges.add({
                    from: resultNodeId,
                    to: returnNode.id
                });
            });

            if (modelium.modeliumType === 'chainLoop' && modelium.loopCount > 0) {
                lastModelIds.forEach((lastModelId, index) => {
                    const firstModelId = firstModelIds[index];
                    edges.add({
                        id: `loop-${lastModelId}-${firstModelId}`,
                        from: lastModelId,
                        to: firstModelId,
                        smooth: {
                            type: 'curvedCW',
                            roundness: 0.3
                        },
                        label: `x${modelium.loopCount}`,
                        font: { size: 10, color: '#848484' },
                        color: { color: '#848484' },
                        dashes: [5, 5],
                        arrows: { to: { enabled: true, scaleFactor: 0.5 } }
                    });
                });
            }

            modelium.structureDescription = generateStructuredDescription(modelium);
            nodes.update(modelium);
        }

        function generateStructuredDescription(modelium) {
            let schema = {
                type: modelium.modeliumType,
                name: modelium.label, // Include the name of the Modelium
                chainLength: modelium.chainLength,
                parallelCount: modelium.parallelCount,
                loopCount: modelium.loopCount,
                models: [],
                results: [],
                returns: [],
                nestedModeliums: []
            };

            const childNodes = nodes.get({
                filter: function (node) {
                    return node.parentId === modelium.id;
                }
            });

            childNodes.forEach(node => {
                switch (node.type) {
                    case 'model':
                        schema.models.push({
                            id: node.id,
                            systemInstructions: node.system_instructions,
                            prompts: node.prompts,
                            modelType: node.model_type,
                            tools: node.tools
                        });
                        break;
                    case 'result':
                        schema.results.push({ id: node.id });
                        break;
                    case 'return':
                        schema.returns.push({ id: node.id });
                        break;
                    case 'modelium':
                        // Recursively call generateStructuredDescription for nested Modeliums
                        schema.nestedModeliums.push(generateStructuredDescription(node));
                        break;
                }
            });

            return schema;
        }

        function generateAndDisplayStructuredDescription() {
            const modeliumNodes = nodes.get({
                filter: function (node) {
                    return node.type === 'modelium';
                }
            });

            if (modeliumNodes.length === 0) {
                alert('No Modelium node found!');
                return;
            }

            const rootModelium = modeliumNodes.reduce((prev, current) =>
                (prev.y < current.y) ? prev : current
            );

            const structuredDescription = generateStructuredDescription(rootModelium);
            document.getElementById('structureDescription').value = JSON.stringify(structuredDescription, null, 2);
        }

        function clearProperties() {
            document.getElementById('node-properties').innerHTML = '';
        }

        function showNodeProperties(nodeId) {
            const node = nodes.get(nodeId);
            const propertiesDiv = document.getElementById('node-properties');
            propertiesDiv.innerHTML = `<h3>${node.label} Properties</h3>`;

            if (node.type === 'modelium') {
                propertiesDiv.innerHTML += `
                                <label for="modeliumName">Name:</label><br>
                                <input type="text" id="modeliumName" value="${node.label}"><br>
                                <label for="chainLength">Chain Length:</label>
                                <input type="number" id="chainLength" value="${node.chainLength}" min="1"><br>
                                <label for="loopCount">Loop Count:</label>
                                <input type="number" id="loopCount" value="${node.loopCount}" min="0"><br>
                                <label for="parallelCount">Parallel Count:</label>
                                <input type="number" id="parallelCount" value="${node.parallelCount}" min="1"><br>
                                <label for="modeliumType">Modelium Type:</label><br>
                                <select id="modeliumType">
                                    <option value="standard" ${node.modeliumType === 'standard' ? 'selected' : ''}>Standard</option>
                                    <option value="chainLoop" ${node.modeliumType === 'chainLoop' ? 'selected' : ''}>Chain Loop</option>
                                    <option value="hierarchical" ${node.modeliumType === 'hierarchical' ? 'selected' : ''}>Hierarchical</option>
                                </select><br>
                                <button onclick="updateModeliumProperties(${nodeId})">Update Properties</button><br>
                                <button onclick="generateAndDisplayStructuredDescription(${nodeId})">Generate Structured Description</button><br>
                                <label for="structureDescription">Structure Description:</label><br>
                                <textarea id="structureDescription" readonly style="width: 100%; height: 200px;"></textarea><br>
                            `;
            } else if (node.type === 'model') {
                propertiesDiv.innerHTML += `
                                        <label for="system_instructions">System Instructions:</label><br>
                                        <textarea id="system_instructions">${node.system_instructions || ''}</textarea><br>
                                        <label for="prompts">Prompts:</label><br>
                                        <textarea id="prompts">${node.prompts || ''}</textarea><br>
                                        <label for="model_type">Model Type:</label><br>
                                        <input type="text" id="model_type" value="${node.model_type || ''}"><br>
                                        <label for="tools">Tools:</label><br>
                                        <select id="tools">
                                            <option value="none" ${node.tools === 'none' ? 'selected' : ''}>None</option>
                                            <option value="all" ${node.tools === 'all' ? 'selected' : ''}>All</option>
                                            <option value="chooser" ${node.tools === 'chooser' ? 'selected' : ''}>Chooser</option>
                                        </select><br>
                                        <button onclick="updateModelProperties(${nodeId})">Update</button>
                                    `;
            }
        }

        function updateModeliumProperties(nodeId) {
            const node = nodes.get(nodeId);
            node.label = document.getElementById('modeliumName').value;
            node.chainLength = parseInt(document.getElementById('chainLength').value);
            node.loopCount = parseInt(document.getElementById('loopCount').value);
            node.parallelCount = parseInt(document.getElementById('parallelCount').value);
            node.modeliumType = document.getElementById('modeliumType').value;
            nodes.update(node);

            // Remove existing child nodes and edges
            const childNodes = nodes.get({
                filter: function (node) {
                    return node.parentId === nodeId;
                }
            });
            nodes.remove(childNodes.map(node => node.id));
            edges.remove(edges.getIds({
                filter: function (edge) {
                    return childNodes.some(node => node.id === edge.from || node.id === edge.to);
                }
            }));

            // Recreate the structure based on updated properties
            createModeliumStructure(node);
        }

        function updateModelProperties(nodeId) {
            const node = nodes.get(nodeId);
            node.system_instructions = document.getElementById('system_instructions').value;
            node.prompts = document.getElementById('prompts').value;
            node.model_type = document.getElementById('model_type').value;
            node.tools = document.getElementById('tools').value;
            nodes.update(node);

            // Update the label after updating properties
            updateModelLabels(node);
        }

        // Function to adjust the Modelium structure for better visualization
        function adjustModeliumStructure() {
            // You can implement various logic here based on your visualization needs
            // Example:
            // 1. Use a layout algorithm (e.g., from vis.js or other libraries)
            // 2. Manually reposition nodes based on their connections and depth
            // 3. Adjust edge smoothness or curvature for better appearance

            // For now, a simple repositioning example:
            const allNodes = nodes.get();
            let maxX = 0;
            allNodes.forEach(node => {
                if (node.x > maxX) {
                    maxX = node.x;
                }
            });
            allNodes.forEach(node => {
                node.x = maxX + 100;
                nodes.update(node);
            });
        }

        function updateModelLabels(node = null) {
            const showPrompt = document.getElementById('show-prompt').checked;
            const showSystemInstructions = document.getElementById('show-system-instructions').checked;
            const showTools = document.getElementById('show-tools').checked;
            const showModelType = document.getElementById('show-model-type').checked;

            if (!node) { // If no specific node is passed, update all model nodes
                const modelNodes = nodes.get({ filter: n => n.type === 'model' });
                modelNodes.forEach(modelNode => {
                    updateModelLabels(modelNode); // Call recursively to update each model node
                });
                return;
            }

            let label = 'Model';
            if (showPrompt) label += '\nPrompt: ' + (node.prompts || 'N/A');
            if (showSystemInstructions) label += '\nSys Instr: ' + (node.system_instructions || 'N/A');
            if (showTools) label += '\nTools: ' + (node.tools || 'N/A');
            if (showModelType) label += '\nType: ' + (node.model_type || 'N/A');

            node.label = label;
            nodes.update(node);
        }

        initNetwork();
    </script>
</body>
</html>

now even more advanced version, but its splited into 3 files:
index.html,
ModeliumDesigner.js
style.css

C:\Users\DELL\Desktop\selfawareGemini\SelAwareAI_Gemini\TESTOWE\visEngine6
├── index.html
├── ModeliumDesigner.js
└── style.css


## File: index.html (in: C:\Users\DELL\Desktop\selfawareGemini\SelAwareAI_Gemini\TESTOWE\visEngine6)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modelium Designer</title>
    <link rel="stylesheet" href="https://unpkg.com/vis-network/styles/vis-network.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
    <link rel="stylesheet" href="https://unpkg.com/jstree/dist/themes/default/style.min.css" />
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="main-container">
        <div id="sidebar">
            <button id="showPresetsButton">Show Presets</button>
            <div id="sidebar-menu">
                <div class="node-type" data-type="modelium" draggable="true">Add Modelium</div>
                <div class="node-type" data-type="model" draggable="true">Add Model</div>
                <div class="node-type" data-type="result" draggable="true">Add Result</div>
                <div class="node-type" data-type="return" draggable="true">Add Return</div>
            </div>
            <div id="properties">
                <h3>Properties</h3>
                <div id="node-properties"></div>

            </div>
            <div>
                <input type="checkbox" id="show-prompt" onchange="updateModelLabels()">
                <label for="show-prompt">Show Prompt</label>
                <input type="checkbox" id="show-system-instructions" onchange="updateModelLabels()">
                <label for="show-system-instructions">Show System Instructions</label>
                <input type="checkbox" id="show-tools" onchange="updateModelLabels()">
                <label for="show-tools">Show Tools</label>
                <input type="checkbox" id="show-model-type" onchange="updateModelLabels()">
                <label for="show-model-type">Show Model Type</label>
            </div>
        </div>

        <div id="modelium-container"></div>
    </div>

    <div id="presets-window" class="modal">
        <div class="modal-content">
            <h2>Presets</h2>
            <div id="preset-list"></div>
            <button onclick="closePresetsWindow()">Close</button>
        </div>
    </div>

    <div id="prompt-selection-window" class="modal">
        <div class="modal-content">
            <h2>Select Prompts and Injectors</h2>
            <div id="prompt-tree"></div>
            <button id="update-prompts-button">Update Prompts</button>
            <button onclick="closePromptSelectisonWindow()">Close</button>
        </div>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
    <script src="https://unpkg.com/jstree/dist/jstree.min.js"></script>
    <script src="ModeliumDesigner.js"></script>
</body>
</html>

## File: ModeliumDesigner.js (in: C:\Users\DELL\Desktop\selfawareGemini\SelAwareAI_Gemini\TESTOWE\visEngine6)
'use strict';

// 1. Data Structures and Initialization

let nodes = new vis.DataSet([]);
let edges = new vis.DataSet([]);
let network = null;
let lastNodeId = 0;

// 2. Presets and Data

const promptsData = [
    {
        "id": "prompt_root",
        "text": "Prompts",
        "children": [
            {
                "id": "sys_general_1",
                "text": "General System Prompt 1",
                "content": "You are a helpful and harmless AI assistant."
            },
            {
                "id": "prompt_i_1",
                "text": "Image Generation Prompt 1",
                "content": "Generate an image of a [subject] in the style of [artist]."
            }
        ]
    }
];

const presets = {
    models: [
        {
            id: 'gpt-3.5-turbo',
            name: 'GPT-3.5 Turbo',
            type: 'Generative Language Model',
            icon: '🤖',
            nickName: "GPT-3.5 Turbo",
            prompts: ['sys_general_1'],
            system_instructions: "You are a helpful assistant.",
            tools: "none",
            modelType: "Generative Language Model"
        },
        {
            id: 'dalle-2',
            name: 'DALL-E 2',
            type: 'Image Generation Model',
            icon: '🎨',
            nickName: "DALL-E 2",
            prompts: ['prompt_i_1'],
            system_instructions: "Generate an image based on the given prompt.",
            tools: "none",
            modelType: "Image Generation Model"
        }
    ],
    modeliums: [
        {
            name: 'Simple Chain',
            chainLength: 3,
            loopCount: 0,
            parallelCount: 1,
            modeliumType: 'standard',
            structureDescription: "",
            nestedModeliums: []
        },
        {
            name: 'Chain with Loop',
            chainLength: 2,
            loopCount: 3,
            parallelCount: 1,
            modeliumType: 'chainLoop',
            structureDescription: "",
            nestedModeliums: []
        }
    ]
};


const modelTypes = [
    "Text",
    "Image",
    "Audio",
    "Video",
    "Text to Audio",
    "Image Generation",
    // Add more as needed
];

// 3. Network Initialization

function initNetwork() {
    const container = document.getElementById('modelium-container');
    const data = { nodes: nodes, edges: edges };
    const options = {
        manipulation: {
            enabled: true,
            addNode: false,
            addEdge: function (edgeData, callback) {
                if (edgeData.from !== edgeData.to) {
                    const fromNode = nodes.get(edgeData.from);
                    const toNode = nodes.get(edgeData.to);
                    if (fromNode.type === 'modelium' && toNode.type === 'model' && toNode.parentId === fromNode.id) {
                        edgeData.classes = 'modelium-to-model';
                    }
                    callback(edgeData);
                }
            }
        },
        nodes: {
            shape: 'box',
            size: 30,
            font: { size: 12, color: '#000000' },
            borderWidth: 2,
            shadow: true,
            color: {
                'modelium': {
                    background: '#f1c40f',
                    border: '#f39c12'
                },
                'model': {
                    background: '#3498db',
                    border: '#2980b9'
                },
                'result': {
                    background: '#2ecc71',
                    border: '#27ae60'
                },
                'return': {
                    background: '#27ae60',
                    border: '#1e8449'
                }
            }
        },
        edges: {
            arrows: {
                to: { enabled: true, scaleFactor: 1 },
                middle: { enabled: true, scaleFactor: 0.5 }
            },
            smooth: { type: 'dynamic' },
            color: { color: '#848484', highlight: '#848484', hover: '#848484' },
            width: 2
        },
        physics: { enabled: false },
        interaction: { hover: true }
    };
    network = new vis.Network(container, data, options);

    network.on("click", function (params) {
        if (params.nodes.length > 0) {
            showNodeProperties(params.nodes[0]);
        } else {
            clearProperties();
        }
    });

    setupDragAndDrop();

    network.on("edgeAdded", function (params) {
        // You can add logic here if needed when an edge is added
    });
    network.on("edgeRemoved", function (params) {
        // You can add logic here if needed when an edge is removed
    });
}

// 4. Drag and Drop Setup

function setupDragAndDrop() {
    const container = document.getElementById('modelium-container');
    container.ondragover = function (e) {
        e.preventDefault();
    };
    container.ondrop = function (e) {
        e.preventDefault();
        const type = e.dataTransfer.getData("text");
        const pos = network.DOMtoCanvas({ x: e.clientX, y: e.clientY });
        addNewNode(type, pos.x, pos.y);
    };

    const nodeTypes = document.getElementsByClassName('node-type');
    for (let nodeType of nodeTypes) {
        nodeType.ondragstart = function (e) {
            e.dataTransfer.setData("text", this.dataset.type);
        };
    }
}

// 5. Add New Node

function addNewNode(type, x, y) {
    lastNodeId++;
    let node = {
        id: lastNodeId,
        x: x,
        y: y,
        type: type,
        label: type.charAt(0).toUpperCase() + type.slice(1),
        chainLength: 1,
        loopCount: 0,
        parallelCount: 1,
        hasInterpreter: true,
        model_type: 'Text', // Default model type
        tools: 'none' // Default tools setting
    };

    nodes.add(node);

    if (type === 'modelium') {
        createModeliumStructure(node);
    }

    network.fit();
}

// 6. Create Modelium Structure

function createModeliumStructure(modelium) {
    const baseX = modelium.x;
    const baseY = modelium.y;
    const verticalSpacing = 300;
    const horizontalSpacing = 500;
    const interpreterOffset = 200;


    const childNodes = nodes.get({
        filter: function (node) {
            return node.parentId === modelium.id;
        }
    });
    nodes.remove(childNodes.map(node => node.id));
    edges.remove(edges.getIds({
        filter: function (edge) {
            return childNodes.some(node => node.id === edge.from || node.id === edge.to);
        }
    }));

    for (let p = 0; p < modelium.parallelCount; p++) {
        let currentX = baseX + p * horizontalSpacing;
        let lastResultId, lastInterpreterResultId;


        for (let i = 0; i < modelium.chainLength; i++) {
            let currentY = baseY + (i + 1) * verticalSpacing;


            lastNodeId++;
            const modelNode = {
                id: lastNodeId,
                label: `Model\nType: Text\nTools: all\nFlags: True\nInterpreter: Yes`,
                type: 'model',
                parentId: modelium.id,
                x: currentX,
                y: currentY,
                group: 'model'
            };
            nodes.add(modelNode);


            if (i === 0) {
                edges.add({
                    from: modelium.id,
                    to: modelNode.id,
                    smooth: { type: 'cubicBezier', roundness: 0.2 }
                });
            }


            lastNodeId++;
            const resultNode = {
                id: lastNodeId,
                label: 'Result',
                type: 'result',
                parentId: modelium.id,
                x: currentX - interpreterOffset / 2,
                y: currentY + verticalSpacing / 3,
                group: 'result'
            };
            nodes.add(resultNode);
            edges.add({
                from: modelNode.id,
                to: resultNode.id,
                smooth: { type: 'cubicBezier', roundness: 0.2 }
            });


            lastNodeId++;
            const interpreterNode = {
                id: lastNodeId,
                label: 'Interpreter',
                type: 'interpreter',
                parentId: modelium.id,
                x: currentX + interpreterOffset / 2,
                y: currentY + verticalSpacing / 3,
                group: 'interpreter'
            };
            nodes.add(interpreterNode);


            lastNodeId++;
            const interpreterResultNode = {
                id: lastNodeId,
                label: 'Interpreter Result',
                type: 'result',
                parentId: modelium.id,
                x: currentX + interpreterOffset / 2,
                y: currentY + 2 * (verticalSpacing / 3),
                group: 'result'
            };
            nodes.add(interpreterResultNode);


            edges.add({
                from: resultNode.id,
                to: interpreterNode.id,
                smooth: { type: 'cubicBezier', roundness: 0.2 }
            });
            edges.add({
                from: interpreterNode.id,
                to: interpreterResultNode.id,
                smooth: { type: 'cubicBezier', roundness: 0.2 }
            });


            if (i < modelium.chainLength - 1) {
                edges.add({
                    from: resultNode.id,
                    to: lastNodeId + 1,
                    smooth: { type: 'cubicBezier', roundness: 0.2 }
                });
                edges.add({
                    from: interpreterResultNode.id,
                    to: lastNodeId + 1,
                    smooth: { type: 'cubicBezier', roundness: 0.2 }
                });
            } else if (modelium.loopCount > 0 && i === modelium.chainLength - 1) {

                const firstModelId = modelNode.id - (modelium.chainLength - 1) * 4;


                edges.add({
                    from: resultNode.id,
                    to: firstModelId,
                    smooth: { type: 'cubicBezier', roundness: 0.8 },
                    dashes: [5, 5],
                    color: { color: '#ff0000' },
                    'data-loop-count': modelium.loopCount,
                    label: modelium.loopCount.toString(), // Display loop count as label
                    class: 'loop-edge'
                });

                edges.add({
                    from: interpreterResultNode.id,
                    to: firstModelId,
                    smooth: { type: 'cubicBezier', roundness: 0.8 },
                    dashes: [5, 5],
                    color: { color: '#ff0000' },
                    'data-loop-count': modelium.loopCount,
                    label: modelium.loopCount.toString(), // Display loop count as label
                    class: 'loop-edge'
                });
            }

            lastResultId = resultNode.id;
            lastInterpreterResultId = interpreterResultNode.id;
        }


        lastNodeId++;
        const returnNode = {
            id: lastNodeId,
            label: 'Return',
            type: 'return',
            parentId: modelium.id,
            x: currentX,
            y: baseY + (modelium.chainLength + 1) * verticalSpacing,
            group: 'return'
        };
        nodes.add(returnNode);


        edges.add({
            from: lastResultId,
            to: returnNode.id,
            smooth: { type: 'cubicBezier', roundness: 0.2 }
        });
        edges.add({
            from: lastInterpreterResultId,
            to: returnNode.id,
            smooth: { type: 'cubicBezier', roundness: 0.2 }
        });
    }

    network.redraw(); // Force Vis.js to redraw
    network.fit();
}

// 7. Node Properties Functions

function clearProperties() {
    document.getElementById('node-properties').innerHTML = '';
}

function showNodeProperties(nodeId) {
    const node = nodes.get(nodeId);
    const propertiesDiv = document.getElementById('node-properties');
    propertiesDiv.innerHTML = `<h3>${node.label} Properties</h3>`;

    if (node.type === 'model') {
        propertiesDiv.innerHTML += `
            <label for="model_type">Model Type:</label><br>
            <select id="model_type">
                ${modelTypes.map(type => `<option value="${type}" ${node.model_type === type ? 'selected' : ''}>${type}</option>`).join('')}
            </select><br>
            <label for="system_instructions">System Instructions:</label><br>
            <textarea id="system_instructions">${node.system_instructions || ''}</textarea><br>
            <label for="prompts">Prompts:</label><br>
            <button id="select-prompts-button" onclick="openPromptSelectionWindow(${nodeId})">Select Prompts</button><br>
            <label for="tools">Tools:</label><br>
            <select id="tools">
                <option value="none" ${node.tools === 'none' ? 'selected' : ''}>None</option>
                <option value="all" ${node.tools === 'all' ? 'selected' : ''}>All</option>
                <option value="chooser" ${node.tools === 'chooser' ? 'selected' : ''}>Chooser</option>
            </select><br>
            <label for="flags">Flags:</label><br>
            <input type="checkbox" id="flags" ${node.flags ? 'checked' : ''}><br>
            <label for="has_interpreter">Has Interpreter:</label><br>
            <input type="checkbox" id="has_interpreter" ${node.has_interpreter ? 'checked' : ''}><br>
            <button onclick="updateModelProperties(${nodeId})">Update</button>
        `;
    } else if (node.type === 'modelium') {
        propertiesDiv.innerHTML += `
            <label for="modeliumName">Name:</label><br>
            <input type="text" id="modeliumName" value="${node.label}"><br>
            <label for="chainLength">Chain Length:</label><br>
            <input type="number" id="chainLength" value="${node.chainLength}"><br>
            <label for="loopCount">Loop Count:</label><br>
            <input type="number" id="loopCount" value="${node.loopCount}"><br>
            <label for="parallelCount">Parallel Count:</label><br>
            <input type="number" id="parallelCount" value="${node.parallelCount}"><br>
            <label for="modeliumType">Modelium Type:</label><br>
            <select id="modeliumType">
                <option value="standard" ${node.modeliumType === 'standard' ? 'selected' : ''}>Standard</option>
                <option value="chainLoop" ${node.modeliumType === 'chainLoop' ? 'selected' : ''}>Chain Loop</option>
                </select><br>
            <button onclick="updateModeliumProperties(${nodeId})">Update</button>
        `;
    }
}

// 8. Update Node Properties Functions

function updateModeliumProperties(nodeId) {
    const node = nodes.get(nodeId);
    node.label = document.getElementById('modeliumName').value;
    node.chainLength = parseInt(document.getElementById('chainLength').value);
    node.loopCount = parseInt(document.getElementById('loopCount').value);
    node.parallelCount = parseInt(document.getElementById('parallelCount').value);
    node.modeliumType = document.getElementById('modeliumType').value;
    nodes.update(node);


    const childNodes = nodes.get({
        filter: function (node) {
            return node.parentId === nodeId;
        }
    });
    nodes.remove(childNodes.map(node => node.id));
    edges.remove(edges.getIds({
        filter: function (edge) {
            return childNodes.some(node => node.id === edge.from || node.id === edge.to);
        }
    }));

    createModeliumStructure(node);
}

function updateModelProperties(nodeId) {
    const node = nodes.get(nodeId);
    node.model_type = document.getElementById('model_type').value;
    node.system_instructions = document.getElementById('system_instructions').value;
    node.tools = document.getElementById('tools').value;
    node.flags = document.getElementById('flags').checked;
    const hasInterpreter = document.getElementById('has_interpreter').checked;

    if (hasInterpreter && !node.has_interpreter) {
        addInterpreterNode(node);
        node.has_interpreter = true;
    } else if (!hasInterpreter && node.has_interpreter) {
        removeInterpreterNode(node);
        node.has_interpreter = false;
    }

    nodes.update(node);
    updateModelLabels(node);
}

// 9. Interpreter Node Management

function removeInterpreterNode(modelNode) {
    const connectedEdges = network.getConnectedEdges(modelNode.id);
    const interpreterEdge = edges.get(connectedEdges.find(edgeId => {
        const edge = edges.get(edgeId);
        return edge.from === modelNode.id && nodes.get(edge.to).type === 'interpreter';
    }));

    if (interpreterEdge) {
        const interpreterNode = nodes.get(interpreterEdge.to);
        const interpreterResultEdge = edges.get(network.getConnectedEdges(interpreterNode.id).find(edgeId => {
            const edge = edges.get(edgeId);
            return edge.from === interpreterNode.id && nodes.get(edge.to).type === 'result';
        }));

        if (interpreterResultEdge) {
            nodes.remove(interpreterResultEdge.to);
            edges.remove(interpreterResultEdge.id);
        }

        nodes.remove(interpreterNode.id);
        edges.remove(interpreterEdge.id);
    }
}

function addInterpreterNode(modelNode) {
    lastNodeId++;
    const interpreterNode = {
        id: lastNodeId,
        label: 'Interpreter',
        type: 'interpreter',
        group: 'interpreter',
        x: modelNode.x + 100,
        y: modelNode.y + 50
    };
    nodes.add(interpreterNode);
    edges.add({from: modelNode.id, to: interpreterNode.id});

    lastNodeId++;
    const interpreterResultNode = {
        id: lastNodeId,
        label: 'Interpreter Result',
        type: 'result',
        group: 'result',
        x: interpreterNode.x + 50,
        y: interpreterNode.y + 50
    };
    nodes.add(interpreterResultNode);
    edges.add({from: interpreterNode.id, to: interpreterResultNode.id});
}

// 10. Update Model Labels

function updateModelLabels(node = null) {
    const showModelType = document.getElementById('show-model-type')?.checked || false;
    const showTools = document.getElementById('show-tools')?.checked || false;

    if (!node) {
        const modelNodes = nodes.get({ filter: n => n.type === 'model' });
        modelNodes.forEach(modelNode => {
            updateModelLabels(modelNode);
        });
        return;
    }

    let label = 'Model';
    if (showModelType) label += '\nType: ' + (node.model_type || 'N/A');
    if (showTools) label += '\nTools: ' + (node.tools || 'N/A');
    label += '\nFlags: ' + (node.flags ? 'True' : 'False');
    label += '\nInterpreter: ' + (node.has_interpreter ? 'Yes' : 'No');

    node.label = label;
    nodes.update(node);
}

// 11. Prompt Selection Window

function openPromptSelectionWindow(nodeId) {
    const promptSelectionWindow = document.getElementById('prompt-selection-window');
    promptSelectionWindow.style.display = 'block';


    $('#prompt-tree').jstree({
        'core': {
            'data': promptsData
        }
    });


    promptSelectionWindow.dataset.nodeId = nodeId;
}

function closePromptSelectisonWindow() {
    const promptSelectionWindow = document.getElementById('prompt-selection-window');
    promptSelectionWindow.style.display = 'none';
}

function updatePromptsForModel(nodeId) {
    const modelNode = nodes.get(nodeId);
    const selectedPrompts = $('#prompt-tree').jstree('get_selected');


    modelNode.prompts = selectedPrompts;
    nodes.update(modelNode);


    updateModelLabels(modelNode);
}

// 13. Event Listeners

document.addEventListener('DOMContentLoaded', function () {
    initNetwork();
});

document.getElementById('update-prompts-button').addEventListener('click', function() {
    const promptSelectionWindow = document.getElementById('prompt-selection-window');
    const nodeId = promptSelectionWindow.dataset.nodeId;
    updatePromptsForModel(nodeId);
    closePromptSelectisonWindow();
});

## File: style.css (in: C:\Users\DELL\Desktop\selfawareGemini\SelAwareAI_Gemini\TESTOWE\visEngine6)
body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    margin: 0;
    padding: 0;
    display: flex;
    height: 100vh;
    background-color: #181818;
    color: #eee;
}

.main-container {
    display: flex;
    height: 100%;
}

#modelium-container {
    flex-grow: 1;
    border: 1px solid #333;
    background-color: #282828;
}

#sidebar {
    width: 300px;
    background-color: #282828;
    padding: 20px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2);
}

#sidebar-menu {
    flex-grow: 1;
    padding-bottom: 20px;
}

.node-type {
    padding: 10px;
    border: 1px solid #333;
    margin-bottom: 5px;
    cursor: pointer;
    background-color: #333;
    border-radius: 5px;
    transition: background-color 0.2s ease;
}

.node-type:hover {
    background-color: #444;
}

#properties {
    margin-top: 20px;
}

#node-properties h3 {
    margin-top: 0;
    color: #eee;
    font-weight: bold;
}

#node-properties label {
    display: block;
    margin-bottom: 5px;
    color: #eee;
}

#node-properties input,
#node-properties textarea,
#node-properties select {
    width: 100%;
    padding: 8px;
    margin-bottom: 10px;
    border: 1px solid #555;
    border-radius: 5px;
    background-color: #222;
    color: #eee;
}

.modelium-to-model {
    color: #f39c12;
    width: 3px;
}

.modelium-to-model .vis-edge .vis-line {
    stroke-dasharray: 5, 5;
}

#sidebar button,
.modal-content button {
    padding: 8px 15px;
    background-color: #3498db;
    color: white;
    border: none;
    cursor: pointer;
    border-radius: 5px;
    margin-bottom: 10px;
    transition: background-color 0.2s ease;
}

#sidebar button:hover,
.modal-content button:hover {
    background-color: #2980b9;
}

.node-icon {
    position: absolute;
    top: -10px;
    right: -10px;
    width: 20px;
    height: 20px;
    background-size: cover;
}

.tools-icon {
    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAjklEQVR4nO3UQQqDMBCF4X+yCXgQ7yEIgu4KvULXbQW9/26KCSWSlEKpC1cDswj5mMwbQoxxwWtaawvr7+xYa21pCYEHjtivtTiDz5RSqfSctR0X5JzPD+NKqTp0xLRjWlzQe7+WUnZCiA0ppQ0hxK6UsvfeX//6XT/ihjue0Fq71VrXEMKhtfZijLl9Mz8BmI0StacvT10AAAAASUVORK5CYII=');
}

.parallel-icon {
    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAV0lEQVR4nGNgGAWjYKiD/wDMQKwCZD4TsS4k1jByDWMiRhGxLiTFMCZiFRHrQlINYyJGEbEuJMcwJkIKiXUhuYYx4VNIiovINYyJkEJiXUiJYaNgZAMAYnAb1CJ5IcEAAAAASUVORK5CYII=');
}

.vis-node {
    border-width: 2px;
    box-shadow: 0 0 10px rgba(0,0,0,0.5);
    padding: 10px;
}

.vis-node.modelium {
    background-color: #f1c40f;
    border-color: #f39c12;
}

.vis-node.model {
    background-color: #3498db;
    border-color: #2980b9;
}

.vis-node.result {
    background-color: #2ecc71;
    border-color: #27ae60;
}

.vis-node.return {
    background-color: #27ae60;
    border-color: #1e8449;
}

.vis-node .vis-label {
    color: #000;
    font-size: 12px;
}

.vis-node.model.with-tools {
    min-height: 100px;
}

.vis-node.model.with-loop {
    min-height: 120px;
}

.modal {
    display: none;
    position: fixed;
    z-index: 1;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgb(0,0,0);
    background-color: rgba(0,0,0,0.4);
}

.modal-content {
    background-color: #fefefe;
    margin: 15% auto;
    padding: 20px;
    border: 1px solid #888;
    width: 80%;
}