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): diff по имени — новые сущности/наблюдения/связи добавляются, изменённые обновляются на месте, исчезнувшие помечаются ghost (красный прямоугольник), вернувшиеся — восстанавливаются. Позиции и раскладка существующих узлов не меняются. -
Явная чистка (
--prune-ghost): удаляет ghost-узлы, когда вы сами этого захотите; ручная блокировкаkg_lockedзащищает узлы от любых правок. -
Автослежение (
--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 memory.jsonl --search "таксономия класс" # поиск без Cytoscape
Обновление по мере роста памяти:
node kg2cytoscape.mjs example.jsonl --update # разовый инкремент
node kg2cytoscape.mjs example.jsonl --watch # следить за файлом
node kg2cytoscape.mjs example.jsonl --watch --interval 3000
node kg2cytoscape.mjs example.jsonl --update --prune-ghost # убрать ghost-узлы
Опции
| Опция | Значение |
|---|---|
--name <имя> |
имя сети в Cytoscape (дефолт — имя файла) |
--layout <тип> |
force-directed | timeline | clusters
|
--host, --port
|
адрес CyREST (дефолт localhost:1234) |
--keep |
не удалять прежнюю сеть с тем же именем |
--dry-run |
только разбор файла, без обращения к Cytoscape |
--style <имя> |
имя стиля (дефолт KG Memory) |
--update |
инкрементальная синхронизация с существующей сетью (diff S1–S5) |
--watch |
автослежение за файлом (не завершается, Ctrl+C — выход) |
--prune-ghost |
удалить ghost-узлы (только вместе с --update/--watch) |
--interval <мс> |
период опроса файла в режиме --watch (дефолт 2000) |
--filter <префикс> |
оставить только один проект по неймспейсу; можно повторять. Связанные соседи (другой проект, infra:*) подтягиваются на один шаг |
--source <формат> |
формат входа: memory | neo4j | obsidian | lorebook | generic. По умолчанию — автодетекция (см. «Источники данных») |
--config <файл> |
конфиг визуального языка (цвета, формы, размеры). По умолчанию — kg.config.json рядом, иначе встроенные дефолты |
--search <запрос> |
поиск по памяти (Cytoscape не нужен): слова с нормализацией, сортировка по релевантности, агрегация по сущности |
--ns <проект> |
поиск: только указанный неймспейс |
--type <тип> |
поиск: только указанный тип (можно повторять) |
--from, --to <дата>
|
поиск: диапазон дат наблюдений (YYYY-MM-DD), границы включительно |
--limit <число> |
поиск: сколько сущностей показать (дефолт 10) |
--json |
поиск: вывести результат в JSON (для скриптов) |
Порядок аргументов свободный: --dry-run example.jsonl и
example.jsonl --dry-run равнозначны.
Поиск по памяти
Отдельный режим без Cytoscape: ищет по словам с нормализацией русских форм, сортирует по релевантности и печатает сущности с лучшими наблюдениями.
node kg2cytoscape.mjs memory.jsonl --search "таксономия класс"
node kg2cytoscape.mjs memory.jsonl --search "экспорт" --ns ssys --type issue
node kg2cytoscape.mjs memory.jsonl --search "экспорт" --from 2026-10-01 --to 2026-10-31
node kg2cytoscape.mjs memory.jsonl --search "kg_vclass" --limit 3 --json
MCP: поиск для агентов
src/mcp/server.mjs — самостоятельный stdio-сервер с одним инструментом
kb_search (без SDK и без зависимостей). Агент получает тот же поиск,
что и --search, и может пользоваться им вместо поиска по подстроке.
// конфиг MCP-клиента (pi, Koda, Claude Desktop и т.п.)
{
"mcpServers": {
"kg2cytoscape-search": {
"command": "node",
"args": ["<путь к репозиторию>/src/mcp/server.mjs"],
"env": { "MEMORY_FILE_PATH": "<путь к memory.jsonl>" }
}
}
}
Файл можно передать и опцией --file. Сервер перечитывает память лениво и
только когда меняются mtime/размер, поэтому данные всегда актуальны.
Источники данных
Вход разбирается адаптерами (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/, src/search/
|
graph/model.mjs — дедупликация рёбер, степени, размеры, карта «наблюдение → родитель»; graph/filter.mjs — срез графа по проекту с замыканием на один шаг (--filter); graph/config.mjs — визуальный язык из конфига (цвета, формы, палитры); graph/classifier.mjs — визуальный класс узла (kg_vclass) по правилам конфига (незнакомый тип → unknown, исходный kg_type не меняется); graph/geometry.mjs — размещение узлов и разведение облаков; graph/diff.mjs — сверка памяти с сетью (S1–S5: новый/совпал/изменён/исчез/вернулся, ghost и kg_locked); search/tokenize.mjs — разбиение текста на слова; search/stem.mjs — стеммер русского (падежные/родовые формы); search/index.mjs — in-memory BM25 по сущностям и наблюдениям с фильтрами по проекту, типу и дате. |
| L3 | src/cyrest/ |
client.mjs — транспорт CyREST (сети, представления, координаты, рёбра); columns.mjs — таблицы атрибутов kg_*; style.mjs — визуальный стиль. |
| L4 | src/usecases/ |
build.mjs — полная сборка сети; sync.mjs — инкрементальное обновление (diff S1–S5); prune.mjs — явная чистка ghost-узлов (--prune-ghost); watch.mjs — автослежение за файлом. |
| L5 |
kg2cytoscape.mjs, src/cli/
|
args.mjs — разбор аргументов; точка входа — оркестрация сценариев. |
Поток данных: parse (текст → записи → сырой граф) → graph (модель,
цвета, геометрия) → usecases (сценарий) → cyrest (запросы к Cytoscape).
Логика каждого уровня описана в комментариях к модулям и в REFACTORING.md.
Тестирование и проверки
npm test # юнит-тесты (встроенный node:test)
npm run check # всё сразу: линтер + формат + типы + тесты
Тесты покрывают чистые уровни (текст, экранирование, разбор, модель, цвета, геометрия, стиль, разбор аргументов, поиск — токенизация, стеммер, BM25 — и чтение рёбер/координат) — их можно запускать без 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). Код можно использовать, изменять и распространять без ограничений, в том числе коммерчески, без указания авторства.





