{
  "name": "OmniVerse AI - Fabric IQ Module",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "fabric-iq",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook-fabric",
      "name": "Webhook: Build Graph",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        100,
        300
      ]
    },
    {
      "parameters": {
        "url": "http://localhost:3000/api/universes/{{ $json.body.universeId }}/full",
        "options": {}
      },
      "id": "load-entities",
      "name": "Load Universe Entities",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        350,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const lore = $input.first().json || {};\nconst universeId = lore.universe?.id;\nconst characters = lore.characters || [];\nconst factions = lore.factions || [];\nconst relationships = [];\n\n// Automate linking of characters to their factions\nfor (const char of characters) {\n  if (char.factionId && char.faction?.name) {\n    relationships.push({\n      sourceId: char.name,\n      sourceType: \"character\",\n      targetId: char.faction.name,\n      targetType: \"faction\",\n      relationType: \"member_of\",\n      strength: 1.0,\n      description: `${char.name} is a member of ${char.faction.name}`\n    });\n  }\n  if (char.species?.name) {\n    relationships.push({\n      sourceId: char.name,\n      sourceType: \"character\",\n      targetId: char.species.name,\n      targetType: \"species\",\n      relationType: \"member_of_species\",\n      strength: 1.0,\n      description: `${char.name} belongs to species ${char.species.name}`\n    });\n  }\n}\n\nreturn { json: { universeId, relationships } };"
      },
      "id": "build-relationships",
      "name": "Build Relationships",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json || {};\nconst relationships = data.relationships || [];\n\n// Calculate degree centrality\nconst degreeMap = {};\nfor (const rel of relationships) {\n  degreeMap[rel.sourceId] = (degreeMap[rel.sourceId] || 0) + 1;\n  degreeMap[rel.targetId] = (degreeMap[rel.targetId] || 0) + 1;\n}\n\n// Formulate nodes map\nconst uniqueNodes = new Set();\nrelationships.forEach(r => {\n  uniqueNodes.add(JSON.stringify({ id: r.sourceId, type: r.sourceType }));\n  uniqueNodes.add(JSON.stringify({ id: r.targetId, type: r.targetType }));\n});\n\nconst nodes = Array.from(uniqueNodes).map(n => {\n  const parsed = JSON.parse(n);\n  return {\n    id: parsed.id,\n    type: parsed.type,\n    centrality: degreeMap[parsed.id] || 0\n  };\n});\n\nreturn { json: { universeId: data.universeId, nodes, edges: relationships } };"
      },
      "id": "generate-graph",
      "name": "Generate Knowledge Graph",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://localhost:3000/api/universes/{{ $json.universeId }}/relationships",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "relations",
              "value": "={{ $json.edges }}"
            }
          ]
        },
        "options": {}
      },
      "id": "save-graph",
      "name": "Save Graph",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        1100,
        300
      ]
    },
    {
      "parameters": {
        "responseCode": 200,
        "responseBody": "={\n  \"status\": \"success\",\n  \"nodesCount\": \"{{ $node[\"Generate Knowledge Graph\"].json.nodes.length }}\",\n  \"edgesCount\": \"{{ $node[\"Generate Knowledge Graph\"].json.edges.length }}\",\n  \"graph\": {\n    \"nodes\": \"{{ $node[\"Generate Knowledge Graph\"].json.nodes }}\",\n    \"edges\": \"{{ $node[\"Generate Knowledge Graph\"].json.edges }}\"\n  }\n}"
      },
      "id": "return-graph",
      "name": "Return Graph Data",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1350,
        300
      ]
    },
    {
      "parameters": {
        "content": "## \ud83d\uddfa\ufe0f Fabric IQ (Semantic Knowledge Graph)\nStructures relations from generated character dossiers and factions.\nCalculates entity degree centrality and saves edges in SQLite."
      },
      "id": "note-fabric",
      "name": "Note: Fabric IQ",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        100,
        100
      ]
    }
  ],
  "connections": {
    "Webhook: Build Graph": {
      "main": [
        [
          {
            "node": "Load Universe Entities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Universe Entities": {
      "main": [
        [
          {
            "node": "Build Relationships",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Relationships": {
      "main": [
        [
          {
            "node": "Generate Knowledge Graph",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Knowledge Graph": {
      "main": [
        [
          {
            "node": "Save Graph",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Graph": {
      "main": [
        [
          {
            "node": "Return Graph Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  }
}