Движок команд и история
Каждое изменение графа, человеком или помощником, это одна команда. Движок живёт в main
(src/main/commands/commit.ts); схемы общие (src/shared/commands/types.ts).
Команда
| Поле | Значение |
|---|---|
projectId | Проект, которому принадлежит граф. |
actionId | Новый id этого действия. Тот же id, присланный снова, получает ответ из записи и никогда не применяется дважды. |
expectedRevisionId | Версия, которую видел отправитель. Если граф ушёл дальше, команда даёт конфликт. |
actor | manual (человек) или ai (помощник). |
runId | null у человека; id открытого хода у помощника. |
payload | Что сделать: add-node, remove-node, move-node, move-nodes, rename-node, connect, remove-edge, retarget-edge, set-parameter, annotate-node, set-component, set-process, import-workflow, open-native, create-subgraph, insert-subgraph, dissolve-subgraph, rename-subgraph, add-subgraph-io, remove-subgraph-io, rename-subgraph-io, edit-in-subgraph, add-group, remove-group, rename-group, restore-revision. |
Что делает commitCommand
В одной транзакции SQLite (immediate, чтобы два писателя не перемешались):
- Разбирает запрос; запрос не по схеме получает
rejected. - Смотрит в
applied_commands: тот жеactionIdс тем же содержимым этоhistorical(возвращается сохранённый результат); с другим содержимымrejected. - Проверяет исполнителя: у команды
manualхода быть не должно; командаaiдолжна принадлежать ходу в состоянииrunning, который ждёт ровно текущую версию. Иначеconflict. - Применяет содержимое к текущему графу. Нода, которую добавляет помощник, ставится так, чтобы не лечь на другую.
- Пишет новую строку в
graph_revisions(весь граф, его документ, компоненты и название), переводит на неёprojects.current_revision_idи записывает команду вapplied_commands. - Обновляет объяснения для новой версии и помечает открытые черновики устаревшими, когда их ноды пропали или открыт другой граф.
- Сдвигает
expected_revision_idоткрытого хода: на новую версию для помощника, а когда человек правит во время хода, тоже на версию человека, чтобы ход продолжился от того, что сделал человек.
Ответ: applied, historical, conflict или rejected, всегда вместе с текущей проекцией (граф, версия,
открытый ход). Полный диск или файл, который нельзя записать, откатывают транзакцию и возвращаются как rejected с
причиной, чтобы человек узнал, что изменение не сохранилось.
Ходы
Ход (run) это один ответ помощника, который может менять граф (таблица runs).
| Вызов | Что делает |
|---|---|
startRun | Закрывает любой другой открытый ход проекта (один за раз) и открывает новый на текущей версии. |
pauseRun | running → paused; пока ход на паузе, его команды отклоняются. |
resumeRun | Открывает самый новый ход на паузе на текущей версии или начинает новый. |
cancelRun | Останавливает ход; построенное остаётся, и его можно отменить. |
closeRun | Ответ закончен: ноды хода раскладываются ещё одной командой, затем ход закрывается. |
closeStaleRuns | При запуске закрывает ходы, оставленные открытыми прошлым сеансом. |
Лимит шагов («Настройки ▸ Помощник ▸ Шагов на ответ») ставит ход на паузу на контрольной точке; «Продолжить» возобновляет его.
Отмена, повтор и история
- Отмена и повтор это команды с содержимым
restore-revision: старая версия становится новой. Ничего не переписывается, поэтому и саму отмену можно отменить. - Целая сборка помощника отменяется одним шагом: стек отмены в renderer объединяет команды одного хода
(
src/renderer/state/undoState.ts,src/renderer/commands/undo.ts). - История прореживается после команд (
src/main/commands/history.ts): не больше 2000 версий на проект, меньше для большого графа (бюджет 256 МБ), но не меньше 200; версия на экране и версии, от которых зависят открытые ходы и черновики, хранятся всегда.
Тесты
tests/unit и tests/integration проверяют движок напрямую; aiHumanConflict.test.ts и chatRunLifecycle.test.ts
ведут ход через конфликты и паузы; tests/e2e/undo-redo.test.ts и command-lifecycle.test.ts проверяют то же через
окно.