Mini SDK para trabajar con conceptrones CFT (Color, Forma, Tono) en JavaScript, tanto en navegador como en Node.js. Incluye helpers para validar, renderizar y enviar cadenas CFT.
Un conceptrón se representa en JS como:
const c = { C: "red", F: "triangle", T: [300, 500] }; const chain = [c1, c2, c3];
El resto es azúcar: validación, serialización, visualización y envío por red.
// conceptron.js export const COLORS = [ "red","orange","yellow","green","cyan","blue", "purple","pink","white","grey","black" ]; export const SHAPES = [ "circle","square","triangle","hexagon","star","bar","wave" ]; export function makeConceptron(C, F, T){ return { C, F, T }; // T = [minHz, maxHz] } export function validateConceptron(c){ if(!COLORS.includes(c.C)) throw new Error("Color no permitido: " + c.C); if(!SHAPES.includes(c.F)) throw new Error("Forma no permitida: " + c.F); if(!Array.isArray(c.T) || c.T.length !== 2) throw new Error("T debe ser [min,max]"); if(typeof c.T[0] !== "number" || typeof c.T[1] !== "number") { throw new Error("T debe contener números (Hz)"); } }
import { makeConceptron, validateConceptron } from "./conceptron.js"; const riesgoFiscal = [ makeConceptron("red", "triangle", [300, 500]), makeConceptron("blue", "hexagon", [200, 350]) ]; riesgoFiscal.forEach(validateConceptron);
const pattern = { id: "riesgo_fiscal_alto", label: "Riesgo fiscal alto", chain: riesgoFiscal, tags: ["tax","alert","high_risk"] };
// Serializar para guardar en BD o localStorage const json = JSON.stringify(pattern); // Cargar de nuevo const loaded = JSON.parse(json); loaded.chain.forEach(validateConceptron);
const vocabulary = { "ok": { id: "ok", label: "Estado normal", chain: [ makeConceptron("green","circle",[600,800]) ] }, "warning": { id: "warning", label: "Atención", chain: [ makeConceptron("yellow","triangle",[400,700]) ] }, "danger": { id: "danger", label: "Peligro", chain: [ makeConceptron("red","triangle",[300,500]) ] } }; localStorage.setItem("os_vocab_v1", JSON.stringify(vocabulary));
/** * Renderiza una cadena CFT como una fila de figuras SVG. * container: elemento DOM donde dibujar */ export function renderChain(container, chain){ container.innerHTML = ""; // limpiar chain.forEach((c, idx) => { const el = document.createElement("div"); el.className = "cft-item"; el.style.display = "inline-flex"; el.style.alignItems = "center"; el.style.marginRight = "8px"; const shape = document.createElement("div"); shape.style.width = "22px"; shape.style.height = "22px"; shape.style.background = c.C; shape.style.marginRight = "4px"; // Forma mínima con border-radius if(c.F === "circle") shape.style.borderRadius = "50%"; if(c.F === "triangle"){ shape.style.width = "0"; shape.style.height = "0"; shape.style.borderLeft = "11px solid transparent"; shape.style.borderRight = "11px solid transparent"; shape.style.borderBottom = "22px solid " + c.C; shape.style.background = "transparent"; } const label = document.createElement("span"); label.textContent = ${c.C} · ${c.F} · ${c.T[0]}-${c.T[1]}Hz; label.style.fontSize = "11px"; label.style.color = "#cfe6ff"; el.appendChild(shape); el.appendChild(label); container.appendChild(el); }); }
<div id="preview"></div> <script type="module"> import { renderChain, makeConceptron } from "./conceptron.js"; const chain = [ makeConceptron("red","triangle",[300,500]), makeConceptron("blue","hexagon",[200,350]) ]; const box = document.getElementById("preview"); renderChain(box, chain); </script>
function buildPacket(pattern){ return { ver: 1, ts: Date.now(), src: "device-lab-01", dst: "panel-main", payload: pattern.chain, meta: { id: pattern.id, label: pattern.label } }; } // Enviar a un backend HTTP async function sendPacket(pattern){ const packet = buildPacket(pattern); await fetch("/api/osnet/send", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(packet) }); }
class ConceptronBus { constructor(){ this.handlers = {}; } on(id, fn){ if(!this.handlers[id]) this.handlers[id] = []; this.handlers[id].push(fn); } emit(id, payload){ (this.handlers[id] || []).forEach(fn => fn(payload)); } } // Uso const bus = new ConceptronBus(); // Registramos acciones bus.on("danger", pattern => { flashRedLights(); playTone(pattern.chain[0].T); }); // Emitimos desde cualquier parte bus.emit("danger", vocabulary["danger"]);
// server.js (Node) import express from "express"; import { validateConceptron } from "./conceptron.js"; const app = express(); app.use(express.json()); app.post("/api/osnet/send", (req,res) => { const packet = req.body; try{ if(!packet.payload || !Array.isArray(packet.payload)){ throw new Error("Payload inválido"); } packet.payload.forEach(validateConceptron); // Aquí guardar en BD, log, etc. console.log("Paquete OK:", packet.meta?.id || "sin id"); res.json({ ok:true }); }catch(err){ console.error(err); res.status(400).json({ ok:false, error: err.message }); } }); app.listen(3000, () => console.log("OSNet demo listening on 3000"));
Desde JS puedes llamar a tu proveedor de IA y convertir directamente texto en cadenas CFT. Se combina con lo visto en AI Integration.
async function textToCFT(text){ const systemPrompt = `Eres un traductor simbólico OpenSymbolic... [mismo prompt que en la guía de IA]`; const messages = [ { role: "system", content: systemPrompt }, { role: "user", content: text } ]; const resp = await callLLM(messages); // tu wrapper const pattern = JSON.parse(resp.content); pattern.chain.forEach(validateConceptron); return pattern; } const pattern = await textToCFT("Patrón para 'necesito ayuda urgente'"); renderChain(document.getElementById("preview"), pattern.chain);
schemaVersion: 1 en tus patrones).