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, небольшая память. Каждый «веер» — сущность со своими наблюдениями; крупнее круг — больше связей.
2. Force-directed, большая память (115 сущностей, 470 узлов). Видно несколько независимых кластеров-проектов.
3. Режим clusters, небольшая память. Облака AutoAnnotate вокруг каждой
сущности, метка — частотные слова из её наблюдений.
4. Режим clusters, средняя память. Облака разведены, чтобы не
накладываться; метки читаются.
5. Режим timeline. Хронологическая лента: сущности выстроены по порядку
наблюдений (колонка kg_seq).
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). Код можно использовать, изменять и распространять без ограничений, в том числе коммерчески, без указания авторства.





