K

kg2cytoscape

kg2cytoscape

Визуализация графа знаний из файла памяти и других источников в Cytoscape Desktop через CyREST (REST-API, порт 1234).

Скрипт читает источник графа — по умолчанию JSONL-файл памяти, создаваемый эталонной реализацией сервера памяти Anthropic (Knowledge Graph Memory MCP Server); также поддерживаются экспорт Neo4j, заметки Obsidian и SQLite-база темпорального графа lorebook (см. «Источники данных»). Из входа строится сеть «сущности + наблюдения + связи» и оформляется так, чтобы граф читался с первого взгляда: цвет — по типу, размер — по числу связей, облака — по кластерам.

Возможности

  • Три раскладки: force-directed (дефолт), timeline (хронологическая лента по порядку наблюдений), clusters (облака AutoAnnotate по сущностям).
  • Разные источники: память Anthropic (memory), экспорт Neo4j, заметки Obsidian, SQLite-база lorebook — с автодетекцией формата.
  • Настраиваемый вид: цвета, формы, заливки, размеры и прозрачности задаются файлом kg.config.json (--config), а не правкой кода.
  • Инкрементальное обновление (--update): дописывает в уже нарисованную сеть только новые сущности/наблюдения/связи, не сдвигая существующие узлы, не меняя их цвета и раскладку.
  • Автослежение (--watch): при изменении файла памяти сеть обновляется сама (опрос mtime/размера с настраиваемым интервалом).
  • Визуальный язык: сущности — круги (цвет по типу, размер по степени), наблюдения — скруглённые квадраты (цвет родителя), подписи в тултипах, рёбра окрашены по типу связи.

Требования

  • Cytoscape 3.10.4 (запущен) с включённым приложением CyREST;
  • для режима clusters — плагин AutoAnnotate;
  • Node.js 18+ — для текстовых источников (memory, neo4j, obsidian, generic); для источника lorebook (SQLite) нужен Node.js 22.5+ — используется встроенный модуль node:sqlite.

Быстрый старт

node kg2cytoscape.mjs example.jsonl                     # граф force-directed
node kg2cytoscape.mjs example.jsonl --layout timeline   # хронологическая лента
node kg2cytoscape.mjs example.jsonl --layout clusters   # облака по сущностям
node kg2cytoscape.mjs example.jsonl --filter resume     # только проект resume

Обновление по мере роста памяти:

node kg2cytoscape.mjs example.jsonl --update            # разовый инкремент
node kg2cytoscape.mjs example.jsonl --watch             # следить за файлом
node kg2cytoscape.mjs example.jsonl --watch --interval 3000

Опции

Опция Значение
--name <имя> имя сети в Cytoscape (дефолт — имя файла)
--layout <тип> force-directed | timeline | clusters
--host, --port адрес CyREST (дефолт localhost:1234)
--keep не удалять прежнюю сеть с тем же именем
--dry-run только разбор файла, без обращения к Cytoscape
--style <имя> имя стиля (дефолт KG Memory)
--update инкрементальная синхронизация с существующей сетью
--watch автослежение за файлом (не завершается, Ctrl+C — выход)
--interval <мс> период опроса файла в режиме --watch (дефолт 2000)
--filter <префикс> оставить только один проект по неймспейсу; можно повторять. Связанные соседи (другой проект, infra:*) подтягиваются на один шаг
--source <формат> формат входа: memory | neo4j | obsidian | lorebook | generic. По умолчанию — автодетекция (см. «Источники данных»)
--config <файл> конфиг визуального языка (цвета, формы, размеры). По умолчанию — kg.config.json рядом, иначе встроенные дефолты

Порядок аргументов свободный: --dry-run example.jsonl и example.jsonl --dry-run равнозначны.

Источники данных

Вход разбирается адаптерами (src/parse/sources/) — у каждого свой формат, но общий интерфейс { name, detect, parse }; источники, читающие файл, а не текст, добавляют detectFile / parseInput. Новый источник = новый файл рядом

  • одна строка в реестре; существующие не меняются.
--source Формат Что делает
memory JSONL/JSON записей {type:"entity"|"relation"} родной формат сервера памяти (по умолчанию)
neo4j JSON {nodes, relationships} метки → тип, свойства → наблюдения, start/end/type → связи
obsidian Markdown одной заметки frontmatter и текст → наблюдения, [[wikilinks]] → связи
lorebook SQLite-база MCP-сервера lorebook сущности и факты темпорального графа: entities → узлы, facts → рёбра (subject → object), valid_from → дата. Читается встроенным node:sqlite, без зависимостей
generic что угодно запасной: JSON-массив, {nodes,edges}, строки-триплеты

Без --source формат определяется автоматически: для SQLite — по magic-байтам файла, для остальных — по содержимому. Если ничего не опознано — берётся generic.

Формат memory (по умолчанию)

Файл памяти создаётся эталонной реализацией сервера памяти Anthropic (Knowledge Graph Memory MCP Server) — именно она пишет сущности и связи в формате {type:"entity"|"relation"}, который и читает этот скрипт. То есть формат входа — не наш собственный, а стандартный «memory» от Anthropic; при желании файл можно наполнить из любой другой системы, соблюдая ту же схему. Обезличенный пример — example.jsonl; личная рабочая память в репозиторий не входит.

JSONL, по одной записи в строке:

{"type":"entity","name":"project:alpha","entityType":"project","observations":["первое наблюдение","второе наблюдение"]}
{"type":"relation","from":"project:alpha","to":"file:main.ts","relationType":"depends_on"}
  • Каждое observation становится отдельным узлом-вершиной, связанным с сущностью ребром has_observation; порядок наблюдений = хронология.
  • Есть универсальный запасной разбор (id / source-target / триплеты «S | P | O»).

Файл скрипт только читает — повредить память невозможно.

Как это выглядит

Ниже — кадры, снятые из Cytoscape (CyREST, экспорт PNG) на синтетической памяти: сущности — круги (цвет по типу, размер по степени), наблюдения — квадраты, цвет наследуется от родителя.

1. Force-directed, небольшая память. Каждый «веер» — сущность со своими наблюдениями; крупнее круг — больше связей.

force-directed, малая сеть

2. Force-directed, большая память (115 сущностей, 470 узлов). Видно несколько независимых кластеров-проектов.

force-directed, большая сеть

3. Режим clusters, небольшая память. Облака AutoAnnotate вокруг каждой сущности, метка — частотные слова из её наблюдений.

clusters, малая сеть

4. Режим clusters, средняя память. Облака разведены, чтобы не накладываться; метки читаются.

clusters, средняя сеть

5. Режим timeline. Хронологическая лента: сущности выстроены по порядку наблюдений (колонка kg_seq).

timeline

6. Инкрементальное обновление (--update). Слева — уже сложившийся граф, справа — новый проект zeta, дописанный в память: он появился отдельным кластером, а позиции существующих узлов не сдвинулись.

инкрементальное обновление

Визуальный язык

По умолчанию: проекты — чёрные залитые круги, файлы — чёрные незалитые окружности, решения — зелёные, проблемы — красные; остальные типы получают свободный цвет палитры. Сущности — круги, диаметр 24 + 9·√(степень) (здесь степень — число связей узла: наблюдения плюс смысловые связи). Наблюдения — приглушённые квадраты 18 px, цвет наследуют от родителя. Рёбра has_observation тонкие и полупрозрачные, смысловые — толще и цветнее. Наведение на узел показывает тултип (тип, наблюдений, текст, дата).

Весь этот вид настраивается файлом kg.config.json (--config <файл>): цвета, формы, заливка (filled: false — только контур), размеры, прозрачности, шрифты. Дефолты встроены в код, внешний файл переопределяет только нужное — без него поведение как выше. В комплекте примеры kg.config.dark.json (тёмная тема) и kg.config.decisions.json (акцент на решениях и проблемах).

Документация

Карта документации проекта — что где искать:

  • GUIDE.md — руководство для пользователя: что можно делать с графом в Cytoscape и AutoAnnotate (зум, поиск, фильтры, раскладки, облака, экспорт). Начните здесь, если просто смотрите на граф.
  • AGENTS.md — подробная техническая документация: особенности CyREST 3.10.4, экранирование аргументов, режим clusters, известные ограничения. Начните здесь, если лезете в код.
  • SCHEMA.md — полная схема колонок kg_* (семантика, визуал, служебное), поток данных и эвристики для чужого файла памяти.
  • CHANGELOG.md — история изменений по датам.
  • ROADMAP.md — планы развития (что сделано и что предстоит).
  • REFACTORING.md — разбиение на модули L0–L5 и архитектурный рефакторинг (настраиваемая визуализация таксономии памяти) с планом внедрения.
  • TEMPLATE.md — переиспользуемый набор решений (слои, TDD, статический анализ, CI, карта документации) для переноса в другие проекты.
  • LICENSE — Unlicense (общественное достояние).
  • .agents/skills/memory-curator/SKILL.md — навык куратора памяти в формате Agent Skills: правила наполнения памяти, чтобы граф получался читаемым (атомарные наблюдения, неймспейсы, типы). Полезен и без визуализации.

Навык memory-curator

В каталоге .agents/skills/memory-curator/ лежит навык в открытом формате Agent Skills (SKILL.md + скрипты). Он задаёт правила наполнения памяти MCP-сервера memory, чтобы граф получался читаемым: атомарные наблюдения, неймспейсы, набор типов сущностей и связей. Включает автономный линтер scripts/lint-memory.mjs (нужен только Node.js).

Навык переносим: агенты с поддержкой формата Agent Skills подхватывают его из .agents/skills/ прямо из репозитория. Для клиента с другой раскладкой каталог навыка достаточно скопировать в его хранилище скиллов.

Сопутствующие файлы

  • src/ — модули приложения (см. «Архитектура и модули»).
  • test/ — юнит-тесты (npm test).
  • package.json — метаданные и скрипт тестирования.
  • fake_kg.py — генератор тестового потока записей памяти (python fake_kg.py out.jsonl).
  • example.jsonl — обезличенный пример файла памяти (вход); рабочая память memory.jsonl в репозиторий не входит.
  • .agents/skills/memory-curator/ — переносимый навык (формат Agent Skills) с правилами наполнения памяти и автономным линтером.

Полный список документации — в разделе «Документация» выше.

Архитектура и модули

Код разбит по уровням абстракции: сверху — сценарии, снизу — примитивы. Каждый модуль решает одну задачу и по возможности состоит из чистых функций (без ввода-вывода и сети), поэтому покрыт юнит-тестами (npm test).

Уровень Каталог Модули и назначение
L0 src/core/ text.mjs — обрезка строк, разбор даты наблюдения; escape.mjs — экранирование аргументов CyREST; log.mjs — единый формат сообщений.
L1 src/parse/ records.mjs — разбор отдельной записи (родной формат + универсальный); parse.mjs — чтение входа в сырой граф; sources.mjs + sources/ — реестр адаптеров источников (memory, neo4j, obsidian, lorebook, generic).
L2 src/graph/ model.mjs — дедупликация рёбер, степени, размеры, карта «наблюдение → родитель»; filter.mjs — срез графа по проекту с замыканием на один шаг (--filter); config.mjs — визуальный язык из конфига (цвета, формы, палитры); geometry.mjs — размещение узлов и разведение облаков.
L3 src/cyrest/ client.mjs — транспорт CyREST (сети, представления, координаты, рёбра); columns.mjs — таблицы атрибутов kg_*; style.mjs — визуальный стиль.
L4 src/usecases/ build.mjs — полная сборка сети; sync.mjs — инкрементальное обновление; watch.mjs — автослежение за файлом.
L5 kg2cytoscape.mjs, src/cli/ args.mjs — разбор аргументов; точка входа — оркестрация сценариев.

Поток данных: parse (текст → записи → сырой граф) → graph (модель, цвета, геометрия) → usecases (сценарий) → cyrest (запросы к Cytoscape). Логика каждого уровня описана в комментариях к модулям и в REFACTORING.md.

Тестирование и проверки

npm test         # юнит-тесты (встроенный node:test)
npm run check    # всё сразу: линтер + формат + типы + тесты

Тесты покрывают чистые уровни (текст, экранирование, разбор, модель, цвета, геометрия, стиль, разбор аргументов, чтение рёбер/координат) — их можно запускать без Cytoscape.

Статический анализ — dev-инструменты (в devDependencies, для запуска нужен npm install); сам проект остаётся без runtime-зависимостей:

Команда Что делает
npm run lint ESLint — логические ошибки, неиспользуемые переменные
npm run format:check Prettier — единый формат (, format` — авто-правка)
npm run typecheck tsc --checkJs — типы из JSDoc без перехода на TypeScript
npm test юнит-тесты node:test

Все проверки гоняются в CI на hub.mos.ru (.gitlab-ci.yml) на каждый push в main и на каждый merge request; красный пайплайн блокирует слияние.

Подробности

Вся «кухня» (внутренние колонки, поведение команд CyREST и AutoAnnotate, экранирование аргументов, подводные камни) описана в AGENTS.md — этот README намеренно остаётся кратким.

Лицензия

Unlicense — общественное достояние (public domain). Код можно использовать, изменять и распространять без ограничений, в том числе коммерчески, без указания авторства.