Skip to content
RedRatInHatPublic

About

Open-source VK bot for remote control of OpenAI Codex. Бот для удалённого управления Codex через ВКонтакте.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Русский · English

Логотип VKodex

VKodex

Диагностика подключения и отправки

Desktop-мост автоматически ведёт отдельный приватный JSONL-журнал в BOT_DATA_DIR/diagnostics. Одна строка — одно событие vkodex.diagnostic.v1: UTC-время, runId/PID/порядковый seq, attemptId, VK eventId, задача/привязка, поколения потока/маршрута/backend, операция и этап. entrySha256 — отпечаток entry point при запуске, не доказательство версии всего bundle. События связывают очередь входящих сообщений, подготовку наблюдения, отказ обнаружения владельца, выбор маршрута, RPC-запись, подтверждение и сверку по истории. connection.join ссылается на существующую попытку подключения; input.associated связывает фрагменты объединённого запроса. Параметры/ответы RPC, тексты сообщений, содержимое файлов, токены и тексты/стеки ошибок не записываются. Нестандартные идентификаторы хешируются; сообщения об ошибке ограничены классом, числовым кодом и фиксированной причиной.

После сборки: npm run diagnostics:read -- --thread THREAD_UUID --event message:123 --limit 200. Можно указать --directory ABSOLUTE_PATH, --attempt, --operation, --connection, --peer, --after и --before. Отчёт только читает до 16 ограниченных сегментов, повторно фильтрует поля и не подключается к Codex/SQLite. Для полной цепочки сначала найдите attemptId по сообщению, затем повторите запрос с --attempt без --event. При connection.join отдельно запросите указанный connectionAttemptId через --connection: фоновые события могут не иметь attemptId входящего сообщения. input.journal/input.adapter не доказывают отправку по сети. write-returned означает возврат записи, не принятие хода. accepted требует native turn/queue receipt или сверки истории; adapter-returned не даёт такого доказательства. unknown не разрешает повторную отправку. Диагностика не даёт прав владения и не заменяет health-механизм. Старый уже запущенный процесс не получает новые события без обновления/перезапуска.

Запись асинхронна, очередь ограничена 256 КиБ/512 событиями, запись — 4 КиБ, диск — 16 сегментами по 1 МиБ. Сегменты разных запусков не перезаписываются: после 16 выделений журнал может заполниться даже раньше 16 МиБ. Состояние и счётчики потерь появляются в обычном логе при запуске/изменении, не чаще раза в минуту; пропуски seq также означают неполную трассу. Переполнение/ошибка логирования не блокируют команды. Для освобождения места сохраните нужные сегменты вне Git и переместите ненужные в корзину, затем перезапустите мост штатным безопасным способом. Логи внутренние: не помещайте их в Git или пользовательский VK outbox.

VKodex — открытый бот для удалённого управления OpenAI Codex через сообщения и беседы ВКонтакте.

Продолжайте существующие задачи Codex или создавайте новые с телефона: выбирайте проект в менеджерском диалоге, открывайте связанную VK-беседу, отправляйте уточнения и вложения в тот же контекст.

VK Messenger: личный диалог с менеджером VKodex и отдельная беседа связанной задачи Codex

Личный диалог с сообществом — менеджер. Отдельная VK-беседа — одна задача Codex. Комментарии агента приходят без уведомлений, готовые ответы — обычными сообщениями.

Статус: экспериментальная интеграция с Codex на Windows. Для каждого профиля с owner: "app-server" VKodex держит один долгоживущий App Server. Периодическая проверка может снять подписку на свободную задачу только после проверки её текущего исполнителя, очереди, цели и дочерних задач. Снятие подписки ещё не доказывает выгрузку native writer; /health отдельно показывает ожидание и подтверждённое освобождение. Это снижает вероятность конфликта с Codex Desktop и VS Code, однако бесшовный ввод, повторное открытие и переключение владельца во всех нативных клиентах пока не прошли приёмку: предупреждение «чат открыт в другом приложении» всё ещё возможно. Если подтверждённый нативный владелец уже выполняет ход, маршрутизация переключается до отправки команды; после начала записи автоматического fallback нет. Launcher используется только явной командой /open, поэтому обычный запрос не выводит окно приложения поверх остальных. Новый независимый Gateway/worker проверяется отдельно и не объявлен общедоступным режимом. Внутренние протоколы Codex могут измениться после обновления, поэтому совместимость проверяется при запуске и во время работы. Начните с проверки на неважной задаче.

Содержание

1. Требования и схема подключения

Компонент Что нужно
Компьютер Windows с запущенным десктопным Codex. VKodex запускается на том же компьютере и под тем же пользователем Windows.
Codex Рабочая авторизация и доступ хотя бы к одному локальному проекту. Для подключения существующей задачи проверьте, что она отвечает непосредственно в приложении.
Node.js Рекомендуется Node.js 24 LTS. Проект также проверяется в CI на Node.js 22.
npm В проекте и CI используется 11.12.1.
Git Git для Windows для загрузки и обновления репозитория.
VK Ваш аккаунт, отдельное сообщество под вашим управлением и ключ сообщества с доступом к сообщениям.
Сеть Для типичного запуска из России нужна раздельная маршрутизация: VKodex обращается к VK API и Long Poll напрямую через российский IP, а Codex/OpenAI — через VPN.

Установите и авторизуйте десктопное приложение по официальной инструкции для Windows. В актуальной документации оно называется ChatGPT desktop app; для задач разработки используется Codex. Порядок входа и создания первой задачи описан в официальном quickstart.

Для подключения к уже авторизованному десктопу не нужно добавлять OPENAI_API_KEY в VKodex. Авторизацию, модель, доступ к файлам и разрешения на команды определяет сама задача Codex. Ключ VK — отдельный ключ другого сервиса.

Публичный IP, домен, HTTPS-сертификат и входящий порт не нужны: VKodex сам получает события через Bots Long Poll. Отдельное приложение VK и пользовательский токен VK для этого режима не требуются.

Развёртывание на VPS, внутри Docker или WSL не заменяет запуск рядом с Windows-десктопом. Docker-файлы в репозитории относятся к прежнему SDK-режиму. Поддержка других ОС для живого десктопного подключения здесь не заявлена.

2. Установка VKodex

Все команды ниже выполняются в PowerShell. После установки Node.js и Git откройте новое окно терминала.

Проверьте инструменты:

git --version
node --version
npm --version

Скачайте репозиторий в папку, где хотите его хранить:

git clone https://github.com/RedRatInHat/VKodex.git
Set-Location VKodex
npm install --global npm@11.12.1
npm ci
npm run check
npm run runtime:prepare

npm ci устанавливает зависимости по зафиксированному lock-файлу. npm run check проверяет TypeScript, запускает тесты и собирает проект; для этих тестов реальные ключи не нужны.

runtime:prepare создаёт отдельный исполняемый файл VKodex.exe и выводит путь к нему. Подробности — в разделе процесс и VPN.

Создайте локальную конфигурацию. Защита в примере не даст случайно перезаписать существующую .env:

if (Test-Path -LiteralPath .env) {
    throw '.env уже существует. Откройте его для редактирования, не копируйте шаблон поверх.'
}
Copy-Item -LiteralPath .env.example -Destination .env
notepad .env

Пока оставьте файл открытым: следующие шаги объясняют, чем заполнить ключ и ID. Не публикуйте заполненную .env.

3. Сообщество VK, ключ API и численные ID

3.1. Создайте отдельное сообщество

  1. Откройте раздел сообществ в VK и создайте сообщество для вашего экземпляра VKodex. Название и короткий адрес могут быть любыми.
  2. Убедитесь, что у вашего аккаунта есть права управления этим сообществом.
  3. Не используйте сообщество, сообщения которого уже обрабатывает другой бот: два получателя Long Poll могут конфликтовать.

Сообщество из скриншота — пример интерфейса, а не общий сервер. Для своей установки используйте собственное сообщество и собственный ключ.

3.2. Включите сообщения и работу в беседах

В управлении сообществом откройте раздел Сообщения и включите сообщения сообщества.

В подразделе с настройками бота включите возможности ботов и разрешение добавлять сообщество в беседы, если эти переключатели доступны. Названия пунктов могут различаться между версиями интерфейса VK.

Откройте обычную страницу сообщества со своего аккаунта и отправьте ему, например, Привет. Это создаст личный диалог с будущим менеджером. До запуска VKodex автоматического ответа не будет. Если VK предлагает разрешить сообщения от сообщества, разрешите их.

3.3. Настройте Bots Long Poll

Откройте Управление → Работа с API → Long Poll API:

Настройка Значение
Long Poll API Включён
Версия API 5.199
Тип события «Входящее сообщение» message_new — включён
Тип события «Редактирование сообщения» message_edit — включён
События действий с кнопками message_event — включён

message_new нужен для новых сообщений, message_edit — для синхронизации исправленного последнего запроса, message_event — для кнопок меню. Настройка Callback API, адрес сервера и строка подтверждения для VKodex не нужны.

Не выбирайте другую версию просто потому, что она новее: адаптер и команда проверки рассчитаны на 5.199. Сохраните изменения. Параметры Long Poll описаны в официальной схеме VK.

3.4. Получите ключ сообщества

  1. В разделе Работа с API → Ключи доступа выберите создание ключа.
  2. Выдайте доступ к сообщениям сообщества. Другие права без необходимости не добавляйте.
  3. Подтвердите действие способом, который запросит VK.
  4. Скопируйте выданную строку целиком в VK_GROUP_TOKEN локального файла .env.

Нужен именно ключ доступа сообщества, не сервисный ключ приложения и не ключ личного аккаунта. Не вставляйте его в сообщения боту, issue, скриншоты, ссылки или команды терминала с явным значением токена.

Если ключ оказался опубликован, отзовите его в VK и создайте новый. Одного удаления текста из файла недостаточно.

3.5. Найдите ID сообщества и свой ID

В конфигурации используются положительные числа:

Поле Что указывать
VK_GROUP_ID Численный ID сообщества, без минуса и без club/public.
VK_OWNER_ID Численный ID вашего личного VK-аккаунта, без id. Только один пользователь.

Если адрес содержит club<число>, public<число> или id<число>, нужен его числовой суффикс. Короткое имя вроде my_vk_bridge вместо числа не подойдёт.

Если виден только короткий адрес, можно получить ID через utils.resolveScreenName. Этот метод поддерживает ключ сообщества. Для следующей команды достаточно уже заполненного VK_GROUP_TOKEN; два ID пока могут быть пустыми.

Выполните из папки VKodex:

$screenName = Read-Host 'Короткий адрес без https://vk.ru/ и без завершающего слеша'
$runtime = Join-Path $env:LOCALAPPDATA 'VKodex/runtime/VKodex.exe'

@'
import { VK } from "vk-io";

const token = process.env.VK_GROUP_TOKEN?.trim();
const screenName = process.argv[2]?.trim();
if (!token || !screenName) {
  console.error("Заполните VK_GROUP_TOKEN в .env и укажите короткий адрес.");
  process.exit(1);
}

try {
  const vk = new VK({ token, apiVersion: "5.199", apiRetryLimit: 0 });
  const result = await vk.api.utils.resolveScreenName({ screen_name: screenName });
  if (!result || !Number.isSafeInteger(result.object_id) || !["user", "group", "page", "event"].includes(result.type)) {
    console.error("Профиль или сообщество не найдены. Проверьте короткий адрес.");
    process.exitCode = 1;
  } else {
    console.log("Тип: " + result.type + "; ID: " + result.object_id);
  }
} catch (error) {
  const code = Number.isSafeInteger(error?.code) ? error.code : "нет ответа";
  console.error("Ошибка VK: " + code);
  process.exitCode = 1;
}
'@ | & $runtime --env-file=.env --input-type=module - $screenName

Запустите её сначала для адреса сообщества, затем для адреса своего профиля. Для профиля ожидается тип user, для сообщества — group, page или event. Перенесите полученные числа в соответствующие поля .env.

Команда только читает ID и не создаёт сообщений. Токен берётся из локального файла и не выводится. Результат содержит ваш личный ID: не прикладывайте этот вывод к публичным отчётам.

4. Конфигурация

Для десктопного режима достаточно следующих полей в .env:

VK_GROUP_TOKEN=
VK_GROUP_ID=
VK_OWNER_ID=

BOT_DATA_DIR=./data/desktop
CODEX_HOME=
CODEX_EXTRA_HOMES=[]
CODEX_SOURCES=
VKODEX_PROJECTLESS_ROOT=
HEALTH_CHECK_INTERVAL_MS=60000

Первые три поля нужно заполнить своими значениями. Пустые строки выше не являются рабочей конфигурацией.

Переменная Обязательна Назначение
VK_GROUP_TOKEN Да Полная строка ключа сообщества с доступом к сообщениям.
VK_GROUP_ID Да Один положительный численный ID сообщества.
VK_OWNER_ID Да Один положительный численный ID владельца. Только он управляет менеджером и служебными кнопками; обычные сообщения участников связанной беседы остаются промптами задачи.
BOT_DATA_DIR Нет Папка приватной базы, очереди и привязок. По умолчанию десктопный адаптер использует ./data/desktop.
CODEX_HOME Нет Основной каталог данных Codex. Пустое значение означает ~/.codex. Это не папка проекта с исходниками.
CODEX_EXTRA_HOMES Нет Совместимый старый формат: JSON-массив дополнительных каталогов данных, максимум 16.
CODEX_SOURCES Нет Предпочтительный JSON-массив источников с home, owner и launcher. owner: "app-server" включает автономного владельца профиля; launcher нужен для /open. Если задан, заменяет CODEX_HOME и CODEX_EXTRA_HOMES.
VKODEX_PROJECT_CATALOG_MODE Нет По умолчанию no-live-legacy: VKodex не читает живой .codex-global-state.json, показывает неизвестное назначение проектов и отклоняет их изменение. Создание задачи в проекте и перенос в проект отклоняются до создания копии; создание задачи без проекта доступно. legacy-file возвращает старый вид проектов, но может мешать атомарному сохранению Desktop; включайте его только с пониманием этого риска. Для полного восстановления проектов нужен проверенный owner-side источник.
VKODEX_PROJECTLESS_ROOT Нет Корень автоматически создаваемых пустых рабочих папок для задач «Без проекта». По умолчанию используется локальная папка данных пользователя, на Windows — %LOCALAPPDATA%/VKodex/workspaces.
HEALTH_CHECK_INTERVAL_MS Нет Интервал полной эксплуатационной проверки. По умолчанию 60 секунд; допустимо от 30 секунд до одного часа.

В общем .env.example сохранены настройки прежнего SDK-бота, включая BOT_DATA_DIR=./data. Для нового десктопного запуска поставьте BOT_DATA_DIR=./data/desktop, чтобы не использовать базу старого режима. Если у вас уже работает десктопная установка с другим путём, сохраните её существующий путь.

MAX_INBOUND_FILES, MAX_INBOUND_FILE_BYTES, MAX_INBOUND_TOTAL_BYTES и DOWNLOAD_TIMEOUT_MS настраивают приём файлов десктопным адаптером. Остальные параметры прежнего SDK-режима, включая VK_OWNER_IDS, VK_ALLOWED_USER_IDS, WORKSPACE_ROOTS, CODEX_MODEL и CODEX_APPROVAL_POLICY, им не управляют. Здесь используется VK_OWNER_ID в единственном числе. Разрешения и модель берутся из задачи Codex; модель следующего хода можно менять через меню.

После изменения .env перезапустите только VKodex. Закрывать работающие задачи Codex не нужно.

5. Проверка и первый запуск

5.1. Проверьте VK

npm run vk:check

В норме все проверки отмечены OK:

messages_permission
long_poll
message_new
message_edit
message_event
event_version
long_poll_server

Эта команда только читает настройки: не создаёт бесед, не отправляет сообщений и не подключается к Codex. Если есть FAIL, исправьте указанную настройку до запуска.

Успешная проверка подтверждает права на сообщения и Long Poll. Возможность создать беседу и получить ссылку-приглашение проверяется отдельно при первом подключении задачи.

5.2. Проверьте каталог Codex

Откройте Codex и задачу, которую хотите подключить:

npm run desktop:probe

Команда выводит количество источников, задач и проектов. Для просмотра каталога ключ VK не нужен. Если taskCount равен нулю или unreadableSources больше нуля, проверьте каталоги в конфигурации. Поля catalogMode и unknownAssignments показывают действующий режим и число задач без подтверждённого назначения проекта; неизвестное назначение не равно «Без проекта».

При известном ID задачи можно проверить и живую подписку:

$threadId = Read-Host 'ID открытой задачи Codex'
npm run desktop:probe -- $threadId

Эта проверка читает состояние, не отправляет промптов и не запускает ход. Ожидаемый признак успешного подключения — subscribed: true. При совпадении ID в нескольких каталогах проверка попросит выбрать один источник; обычный менеджер различает такие копии.

5.3. Запустите мост

После успешного npm run check сборка уже готова:

npm run desktop:start

Для запуска из TypeScript во время разработки:

npm run desktop:dev

Выберите одну из этих команд. Не запускайте два экземпляра с одним сообществом или одной базой. npm start и npm run dev запускают другой, SDK-режим.

Дождитесь строки:

VKodex desktop bridge: VK Long Poll started.

Оставьте терминал и Codex работающими. Через несколько секунд проверьте первый отчёт:

npm run health:check

Команда должна завершиться со статусом Health: OK. Для штатной остановки моста нажмите Ctrl+C в его терминале. Это не команда остановки задачи Codex.

5.4. Подключите первую задачу

  1. Со своего разрешённого VK-аккаунта откройте личный диалог с сообществом и отправьте /menu.
  2. Нажмите Задачи Codex или отправьте /list.
  3. Выберите проект, Без проекта или Все подряд, затем нужную задачу.
  4. Бот создаст или найдёт связанную VK-беседу и пришлёт ссылку в менеджер.
  5. Если VK не добавил вас автоматически, вступите по присланной ссылке. Связь с задачей уже включена: отдельного подтверждения вступления нет.
  6. В связанной беседе отправьте простой тестовый запрос, например: «Кратко опиши текущую задачу, ничего не меняя».
  7. Убедитесь, что сообщение поступило в ту же задачу в десктопе, а её ответ появился в VK.

Проверяйте сначала на неважной задаче. Внутренний протокол приложения не является стабильным публичным API; тесты проекта не гарантируют совместимость со всеми версиями Codex.

Дополнительный адаптер клиента-владельца

Обычным задачам, которыми владеет профильный App Server VKodex, этот адаптер не нужен. Он требуется только для безопасной архивации источника переноса, если writer задачи уже удерживает VS Code: VKodexOwnerLauncher.exe передаёт запрос через тот же App Server клиента. Это не дополнительный исполнитель ходов и не fallback после таймаута.

Подготовка на Windows после npm run build:

./scripts/prepare-owner-launcher.ps1 `
  -CodexHome 'C:\CodexProfiles\work' `
  -NativeExecutable 'C:\Path\To\Native\codex.exe' `
  -Destination 'C:\VKodexAdapters\work-v1'

Укажите реальный нативный CLI выбранного клиента, а не другой экземпляр адаптера. Установщик создаёт отдельный пакет и закрытый локальный канал; настройки клиентов и работающие процессы он не меняет. Для стандартной установки расширения VS Code пакет использует extensions.json, чтобы находить обновлённую версию расширения. Неоднозначная запись или несовпадение манифеста останавливают запуск.

  • VS Code: в настройках нужного профиля задайте chatgpt.cliExecutable равным пути к созданному VKodexOwnerLauncher.exe. Это экспериментальная настройка расширения.
  • Уже работающий клиент: новое окружение не подключает адаптер к существующему App Server. Первое подключение требует безопасного перезапуска соответствующего клиента; не выполняйте его во время задач или при необходимости сохранить браузерную сессию.
  • Откат: восстановите прежнюю настройку CLI или уберите CODEX_CLI_PATH, затем перезапустите клиент в безопасный момент. Историю задач адаптер не переписывает.

Не внедряйте адаптер в Codex Desktop и не настраивайте глобальный CODEX_CLI_PATH: эта схема не поддерживается VKodex и может нарушить запуск приложения. Архивация через адаптер проверена на отдельном профиле VS Code. Адаптер проверяет источник и неархивированных потомков любой глубины: все должны иметь подтверждённое состояние простоя и неактивную цель. Непроверенные, выгруженные или работающие потомки блокируют архивацию; автоматически загружать или останавливать их адаптер не пытается. Неопределённый результат архивации не повторяется автоматически. Каталог owner-transports содержит локальные токены доступа: не публикуйте его и не отправляйте в VK.

6. Менеджер и связанные беседы

Длинные входящие сообщения: в связанной беседе текст от 3000 символов запускает окно сборки. Следующие текстовые части того же автора объединяются через перевод строки после 1,5 секунды тишины (до 64 000 символов в запросе). Короткий хвост включается; команды, вложения и другой автор завершают текущую сборку и обрабатываются отдельно. VK не передаёт признак частей одного сообщения, поэтому это эвристика: при паузе больше 1,5 секунды получится отдельный запрос. Правка одной части уже объединённого запроса остаётся только в VK. Каждая часть и состояние пачки сохраняются в SQLite до отправки: после перезапуска незавершённая сборка продолжается, а пачка, которая уже могла попасть в Codex, автоматически повторно не отправляется.

Менеджер

Менеджер находится в личном диалоге с сообществом, а не в дополнительной общей беседе.

Команда или кнопка Действие
/menu, /start, /status Открыть меню с технической информацией о мосте.
/help Показать допустимые команды менеджера.
/health, «Проверить здоровье» Немедленно перепроверить VK, очередь, SQLite, каталоги Codex, API целей, named pipe, stream protocol и активные трансляции.
/load, /pc Снять текущую загрузку CPU, RAM и диска, время работы ОС, а также CPU, RAM и PID процесса VKodex. Доступно только в менеджере; команда не передаётся агенту.
/limits, «Лимиты Codex» Показать каталог, аккаунт, использованный процент лимитов, время сброса, тариф и доступные кредиты. Если Codex сообщает доступный кредит сброса, здесь же появляется кнопка его ручного использования с отдельным подтверждением. В менеджере показываются все настроенные каталоги; в связанной беседе — только аккаунт каталога этой задачи. Команда не передаётся агенту.
/list, «Задачи Codex» Сначала выбрать проект, затем задачу.
/new, «Новая задача» Создать пользовательскую задачу: каталог Codex → проект или «Без проекта» → название → стартовый промпт → модель → уровень рассуждения. Для проекта можно выбрать локальную папку или отдельный Git worktree.
/cancel Отменить незавершённый мастер создания задачи.
«Проекты» Посмотреть названия проектов и их рабочие папки.
«Без проекта» Задачи, для которых подтверждено отсутствие проекта.
«Все подряд» Все найденные пользовательские задачи, включая задачи с неизвестной принадлежностью к проекту.
«Выбрать проект» Вернуться к выбору проекта.
«Обновить» Обновить выбранный экран вручную.
«Отключить трансляцию» Отвязать трансляцию, сохранив задачу Codex.

Список разбит на страницы; выбранный проект сохраняется при перелистывании. Служебные задачи агентов и архивные задачи не показываются. Название берётся из индекса имён Codex, затем из локальной базы. Длинный стартовый промпт не подставляется вместо имени.

В служебных ответах менеджера есть кнопка Меню. В меню видны процесс и время работы моста, количество задач и связей, очередь отправки и последний полный health-отчёт. Полное меню открывается только по запросу; отдельное приветствие при запуске не присылается.

Входящие события упорядочиваются отдельно для каждой VK-беседы. Зависшее подключение одной задачи не удерживает менеджер и остальные задачи. Через 45 секунд watchdog сообщает о задержке, но сохраняет порядок этой беседы до завершения вызова; изменяющая команда автоматически не повторяется. Остальные беседы продолжают работать через собственные очереди.

Новая задача создаётся атомарно через App Server выбранного CODEX_HOME: операция материализует постоянный thread ID и принимает первый ход до возврата результата. События первого хода до готовности VK-беседы хранятся в SQLite, поэтому перезапуск моста между созданием задачи и её привязкой не теряет готовый ответ. После завершения короткой сессии создания все последующие ходы идут через долгоживущего профильного владельца; если UI-клиент уже держит writer, команда до отправки маршрутизируется к нему. Launcher в этом пути не нужен. Сессия создания не продолжает существующие задачи и не используется как fallback. Для задачи в проекте режим Локально использует сохранённую рабочую папку проекта. Вариант Без проекта не требует вводить путь с телефона: VKodex создаёт отдельную пустую папку под VKODEX_PROJECTLESS_ROOT, выбирает локальный режим и сохраняет задачу без проектной привязки. Кнопка Выбрать папку показывает постраничный список известных рабочих папок из проектов и существующих задач выбранного каталога; выбор выполняется кнопкой, а привязка к проекту при этом не добавляется. В этом же списке доступны новая пустая папка и резервный ручной ввод пути. В режиме Отдельный worktree VKodex вызывает git worktree add --detach и создаёт соседнюю папку вида <репозиторий>_VKodex_<идентификатор>_worktree; исходная папка должна быть Git-репозиторием, автоматического удаления worktree нет. Если первый ход подтверждён, а последующий ответ VK потерян, мастер помечает результат как неопределённый и не создаёт дубликат.

Беседа задачи

Обычное сообщение продолжает связанную задачу. Во время работы агента оно передаётся как уточнение; после завершения — как следующий ход в том же контексте. Автором промпта может быть любой участник связанной беседы: мост игнорирует только собственные сообщения сообщества и уже обработанные исходящие сообщения. Пока в беседе фактически пишет только владелец, VKodex передаёт Codex чистый текст без подписи. После первого сообщения другого пользователя мост добавляет к последующим запросам технический блок с отображаемым именем автора и его VK ID, поэтому Codex различает участников общей беседы; замеченные авторы сохраняются после перезапуска, имя профиля кешируется, а при недоступности VK API остаётся ID. Этот блок явно помечен как транспортная атрибуция, а не инструкция. Состав беседы не проверяется. При неподтверждённом состоянии Codex или потерянном ответе запрос не повторяется автоматически.

Редактирование в VK синхронизируется с Codex только для последнего сообщения того же автора, если оно запустило отдельный ход через живой десктоп. VKodex останавливает незавершённый ход, вызывает штатное редактирование последнего запроса, удаляет из VK ответы и комментарии отброшенной ветки и запускает исправленный ход. Уже выполненные команды и изменения рабочих файлов не откатываются. Сообщение, добавленное как уточнение внутрь идущего хода, более старое сообщение или ход с последующими уточнениями не переписываются: правка остаётся только в VK, а бот присылает объяснение.

Если связь явно отключена через /detach или архивирование, входящее сообщение не включает её скрытно. В личный менеджер приходит объяснение и кнопка повторного подключения. После подключения повторите исходное сообщение. Для беседы, которая вообще не связана с задачей, менеджер предложит открыть список задач. Выход участника и другие изменения состава беседы связь не отключают.

Строка Меню задачи: и кнопка Меню добавляются в конец итогового ответа Codex; у длинного ответа — только в последнюю часть. Отдельного сообщения с меню при подключении или завершении хода нет. Кнопка открывает актуальную карточку, даже если предыдущие кнопки настроек уже устарели. До первого ответа меню можно открыть командой /menu.

Действие Что происходит
/menu, /status Открывается техническая карточка задачи.
/help Показать допустимые команды этой беседы.
/open, «Поделиться» → «Открыть в Codex» Явно вывести настроенное приложение Codex на передний план и открыть эту задачу. Обычный промпт не вызывает launcher и не фокусирует окно.
/files Проверить папки отправки этой связи и передать новые готовые файлы в VK.
/files unknown [страница] Показать staged-файлы этой беседы, для которых результат загрузки в VK неизвестен.
/files verify <операция> <ключ файла> <doc...> По указанному ID документа VK сверить его байты с неизменной staged-копией и, только при совпадении, возобновить доставку без повторной загрузки.
/goal, «Цель» Показать цель Codex, её статус, бюджет, расход токенов и время работы. Через меню можно задать или изменить формулировку и бюджет, поставить цель на паузу, возобновить либо снять её. Завершённой цель отмечает сам агент после проверки результата.
«Модель / рассуждение» Выбор модели и уровня рассуждения для следующего хода из доступного кеша Codex. Текущий ход не прерывается.
«Обновить» Обновляются статус, модель и заполнение контекстного окна.
«Переименовать» После ввода и подтверждения имя сохраняется в Codex, затем VK-беседа получает название [VKodex] <имя>. Переименование в самом Codex автоматически переносится в связанную VK-беседу.
«Архивировать» После подтверждения архивируется неработающая задача; трансляция отключается.
«Рабочая директория» Папка задачи присылается текстом.
«Диплинк» Локальная ссылка для открытия задачи в десктопе.
«Markdown-файл» Экспорт видимой переписки, если история полная и не превышает 2 МБ.
«Поделиться» Явное открытие приложения, диплинк и экспорт. Публичная ссылка автоматически не создаётся.
«Переместить в проект» Сохранить новую принадлежность задачи проекту Codex либо убрать её из проекта. Рабочая директория уже существующей задачи не перемещается.
«Переместить» → «В другой каталог» Создать native fork завершённой истории в другом CODEX_HOME, явно восстановить и проверить пользовательское название, сохранить модель, effort и рабочую папку, переключить на него текущую VK-беседу и архивировать исходную задачу. Для задачи с подтверждённым проектом VKodex подбирает или создаёт соответствующий проект в целевом каталоге; для задачи без проекта можно выбрать проект или «Без проекта».
/stop Прервать активный ход в этой задаче. Команда фиксирует точный ID хода, после отказа или потерянного ответа сверяет его нативный статус и не затрагивает более новый ход. Повтор допустим только после явного отказа при подтверждённом продолжении того же хода; неизвестный результат вслепую не повторяется. Задача не архивируется.
/detach Отключается только трансляция. Задача не прерывается и не архивируется.

Неизвестная slash-команда владельца показывает соответствующую справку и не передаётся агенту. Сообщения остальных участников связанной беседы, включая текст, начинающийся с /, по-прежнему считаются обычными промптами.

При возобновлении цели VKodex сохраняет идентификатор попытки до изменения статуса. Если выбранный владелец не выдаёт квитанцию именно нативного хода цели, VKodex сначала загружает задачу в его runtime, повторно проверяет неизменность цели, затем переводит её в активное состояние через штатный API и прямо отмечает, что запуск следующего хода не подтверждён. Обычный пустой пользовательский ход для этого не создаётся. Если постоянный исполнитель не назначен или задачей владеет другой клиент Codex, VKodex отклоняет активацию вместо записи активного статуса через временный процесс или чужой runtime. Пауза и снятие цели также проверяют, что пользователь подтверждал ту же версию цели; у штатного API пока нет атомарной операции сравнения и записи, поэтому гонку с одновременным изменением цели другим клиентом полностью исключить нельзя. Если ответ на изменение статуса потерян, /goal показывает неизвестный исход и не повторяет запись вслепую. Снятие цели и смена каталога не снимают эту защиту: сначала нужно проверить исход в Codex.

Значение контекста — последняя оценка Codex, а не суммарное количество потраченных за задачу токенов. Отсутствующие данные не угадываются. Диплинк полезен на устройстве с установленным десктопным приложением; бот не меняет буфер обмена телефона.

Синхронизация названия: переименование через меню VK сохраняет имя в каталоге Codex и меняет связанную беседу на [VKodex] <имя>. Переименование штатными средствами Codex обнаруживается при обновлении каталога и автоматически переносится в VK, в том числе после перезапуска моста. При временной ошибке VK автоматическая синхронизация повторяется с увеличивающимся интервалом; кнопку «Повторить для VK» можно использовать немедленно. Старое подтверждение не выполняет операцию повторно и не может перезаписать более новое имя.

Локальный API Codex может сохранить имя в каталоге, не обновив кеш уже открытого окна. Мост отдельно показывает подтверждение живой задачи, не перезапускает приложение и никогда не передаёт название как промпт агенту. Для немедленного обновления такого окна используй штатное переименование в Codex.

Какие сообщения приходят в VK

Пересылка видимых комментариев не зависит от инициатора хода: VK, приложение, расширение, цель или сообщение другого агента. Если входное сообщение ещё не появилось в потоке, мост ждёт его не более двух секунд для упорядочивания, затем отправляет комментарии. Этот срок сохраняется при перезапуске и не продлевается новыми фрагментами. Позднее входное сообщение помечается как «Вход этого хода»; готовые ответы и старая история не переигрываются. Явно тихие автоматизации сохраняют свою политику уведомлений. Health проверяет также буфер комментариев до очереди VK.

  • Во время работы хода последним в переписке остаётся отдельное тихое сообщение вида думаю... · обновлено 15:42:20; оно циклически меняется на думаю.. и думаю. и никогда не встраивается в комментарии агента. После вашего сообщения, меню или нового ответа бот создаёт новый индикатор ниже, а прежний удаляет, поэтому состояние работы видно прямо в списке чатов без служебных сообщений в истории. Обновление — раз в двадцать секунд, чтобы длительная задача не упиралась в flood control VK. После завершения индикатор показывает Готово.; ошибки и потеря связи показываются явно. При отключении трансляции редактирование прекращается.
  • Каждый комментарий агента — отдельное тихое сообщение. Дописывание того же комментария редактирует его сообщение не чаще одного раза в двадцать секунд, чтобы поток нескольких задач не включал flood control VK. Финальные ответы и запрошенные панели этим интервалом не задерживаются.
  • Готовый ответ — отдельное сообщение с обычным уведомлением и кнопкой Меню.
  • Ваше сообщение из десктопа — с заголовком ## user request; у длинного запроса заголовок повторяется в каждой части.
  • Сообщение, пришедшее из VK, не должно возвращаться в ту же беседу дубликатом.
  • Команды, их вывод, изменения файлов, события инструментов и скрытые рассуждения не пересылаются.

Автоматический предпросмотр ссылки не мешает передаче текста: если URL уже есть в сообщении, карточка VK не считается отдельным файлом. Ошибки обработки запроса приходят в ту беседу, из которой он отправлен.

Звук и показ уведомлений зависят также от клиента и настроек VK. Вся история до первого подключения автоматически не копируется.

Если VK ограничивает частоту запросов, доставка делает общую паузу: при ошибке 6 — секунду, при 9 или 29 — две минуты. Пауза сохраняется при перезапуске; сообщения остаются в очереди. В это время анимация и доставка могут временно остановиться.

Фотографии и документы

В VK → Codex: прикрепите фотографию или документ к обычному сообщению в связанной беседе. Можно отправить только вложения, без текста. Фото поступает в ту же задачу как изображение, документ — как локальный файл с указанным путём. Вложения в ответах и пересланных сообщениях тоже проверяются. При ошибке скачивания запрос целиком отклоняется, чтобы агент не продолжил работу без нужного файла.

По умолчанию принимаются до 10 файлов, один входящий файл может занимать до 200 МиБ, а общий размер вложений одного сообщения — до 200 МиБ. Файл потоково записывается на диск и не удерживается целиком в памяти; тайм-аут скачивания одного файла — 10 минут. Пределы можно уменьшить через MAX_INBOUND_FILES, MAX_INBOUND_FILE_BYTES, MAX_INBOUND_TOTAL_BYTES и DOWNLOAD_TIMEOUT_MS, но поднять размер выше 200 МиБ нельзя. Видео, голосовые сообщения, стикеры и другие отдельные типы вложений пока не поддерживаются напрямую; отправьте видео как документ. В менеджере и вместе с командами вроде /menu файлы не принимаются.

Codex → VK: каждый запрос из связанной беседы получает собственную папку отправки. Попросите агента сохранить туда нужный результат, например: «Сделай CSV и положи его в папку отправки VKodex». После завершения хода мост загружает готовые файлы в эту беседу. PNG/JPEG отправляются как фото, GIF/WebP и остальные файлы — как документы. Ошибка загрузки фото не запускает вторую загрузку как документа: если VK принял байты, но ответ потерялся, это могло бы создать дубль. Для сохранения исходных байтов изображения, которые VK может сжать, отправляйте его в архиве. Команда /files ставит проверку в долговечную очередь и сразу возвращает подтверждение; итог загрузки приходит отдельным сообщением. Повторный /files присоединяется к уже выполняющейся проверке и не создаёт дубликаты. Поэтому сообщение о тайм-ауте VK означает только, что синхронное ожидание закончилось: фоновая доставка может ещё продолжаться.

Если в одной папке лежат допустимые и слишком большие файлы, неподходящий файл получает отдельное уведомление, а остальные продолжают отправляться. Предел исходящей выдачи — до 10 файлов и 200 МиБ на файл; выдача разбивается на несколько VK-сообщений. Стадия «поставлено в очередь» ещё не означает, что VK уже показал вложение.

Входящие файлы сохраняются в BOT_DATA_DIR/files/<идентификатор-запроса>/inbox/, исходящие — в соседней outbox/. Идентификатор создаёт мост; точный путь передаётся агенту в запросе. Это не папка проекта. Разрешения задачи Codex не расширяются: если её ограничения не позволяют работать с этой папкой, разрешите доступ штатным способом в десктопе. Запросы, отправленные прямо из десктопа, не получают новую папку автоматически.

Исходящая выдача разбивается на сообщения до 10 вложений и 200 МиБ каждое; отдельный файл не может превышать 200 МиБ. Мост отправляет обычные файлы из outbox/ и его вложенных папок: скрытые файлы пропускаются, ссылки и файлы, изменившиеся во время чтения, отклоняются. Поздние файлы после завершения хода проверяются автоматически с увеличивающимся интервалом до 48 часов; старые выдачи остаются доступны через /files, в том числе после переноса беседы между каталогами. При неизвестном результате загрузки повтор той же версии блокируется до ручной сверки в VK, чтобы не создать дубль. Пути из текста ответов и остальные каталоги проекта не сканируются. Архивы автоматически не распаковываются. Содержимое документов остаётся пользовательскими данными, а не командами для моста.

Режим подготовки неизменной копии файла перед загрузкой пока проходит отдельную приёмку и по умолчанию выключен, в том числе в рабочем мосте. Изолированно его можно включить для одной беседы через VKODEX_STAGED_FILE_PILOT=single-chat и VKODEX_STAGED_FILE_PILOT_PEER_ID, либо для всех бесед через VKODEX_STAGED_FILE_PILOT=all-chats; перед включением для всех бесед проверьте локальную квоту и ручной сценарий загрузки. Для подготовленных копий мост раз в пять минут выполняет ограниченную сверку: освобождает заброшенную резервацию только при подтверждённом завершении процесса записи и отсутствии файла; копию старше семи дней перемещает в корзину только после подтверждённой доставки именно этого вложения в VK и проверки неизменности файла. Исчезновение файла после записи намерения очистки не доказывает успешный перенос в корзину: квота остаётся занятой до подтверждения операции или отдельной сверки оператором. Проверка stage_storage показывает занятую квоту и неподтверждённые переносы без путей файлов. API корзины работает по пути, поэтому процесс под той же учётной записью Windows всё ещё может подменить файл между последней проверкой и переносом. Обычные выдачи при выключенном режиме сохраняют прежний маршрут; неизвестный результат загрузки по-прежнему не повторяется вслепую.

Для ранее подготовленного staged-файла с неизвестным результатом владелец беседы может вызвать /files unknown, скопировать оттуда операцию и ключ файла и затем выполнить /files verify <операция> <ключ файла> <doc...> с точным ID документа сообщества. VKodex читает документ через VK API, проверяет размер и SHA-256 байтов с сохранённой копией и только после этого ставит вложение в очередь доставки. Проверка не загружает файл повторно и не добавляет документ в список автоматической очистки. Без известного ID или при несовпадении байтов результат остаётся неизвестным. Для выдач без staged-копии эта команда недоступна.

Повторная проверка и перезапуск не отправляют неизменившийся файл второй раз. Перед скачиванием, загрузкой и отправкой проверяется активность привязки, но не состав беседы. После отключения связи старые папки не отправляются автоматически при повторном подключении. Локальные файлы сохраняются; очищайте ненужные данные вручную через корзину и не добавляйте папку BOT_DATA_DIR в Git.

Если VK отвечает no_free_space при загрузке документа, VKodex может удалить самые старые документы, которые ранее загрузил сам мост, и повторить ту же загрузку. Для удаления нужен отдельный пользовательский VK-токен с правом работы с документами: групповой токен для docs.delete не подходит. Токен не записывается в .env, базу или логи. На Windows один раз выполните npm run vk:token:setup в каталоге VKodex и вставьте токен в скрытом приглашении. Если VK сохранил OAuth-ответ в файл, можно импортировать его без вывода токена: npm run vk:token:import -- -InputPath "C:\path\to\vk_auth.txt". Скрипт извлечёт access_token из URL или JSON и сохранит его в DPAPI-файле %LOCALAPPDATA%\VKodex\secrets\vk-document-token.xml; VKodex прочитает его только при подтверждённом переполнении хранилища. Удаляются только зарегистрированные загрузки VKodex, текущие и ещё не доставленные вложения защищены. Без этого секрета переполнение не обходится повторными попытками: бот сообщает, что требуется локальная настройка.

Выход из беседы и отключение связи

Изменения состава беседы не приостанавливают и не отключают трансляцию. Если владелец вышел, мост может продолжить отправлять прогресс и ответы оставшимся участникам. Любой участник, кроме самого бота, может продолжать задачу обычными сообщениями. Удаление бота из беседы естественным образом лишает мост возможности доставлять сообщения в VK, но не служит командой отключения привязки.

Чтобы остановить трансляцию предсказуемо, владелец должен сначала отправить /detach или отключить её через менеджер. Это закрывает подписку на Codex и отменяет ещё не отправленную очередь; сама задача Codex продолжает работать. Для восстановления выберите задачу в менеджере снова. Отклонённые во время явного отключения сообщения автоматически не повторяются.

Удаление переписки только у себя не имеет отдельного события в API сообщества VK и также не отключает связь. Уже отправленное или находящееся в обработке VK сообщение отозвать через /detach нельзя.

7. Дополнительные каталоги Codex

По умолчанию VKodex читает задачи из ~/.codex. Для нескольких аккаунтов используйте CODEX_SOURCES: каждый каталог получает отдельного владельца команд и необязательный launcher для явного /open.

Codex Desktop для основного аккаунта и отдельный профиль VS Code для рабочего аккаунта:

CODEX_SOURCES='[{"home":"~/.codex","owner":"app-server","launcher":{"type":"desktop"}},{"home":"~/.codex-work","owner":"app-server","launcher":{"type":"vscode","executable":"C:/Path/To/Code.exe","userDataDir":"C:/Path/To/Code-Codex-Work"}}]'

Доступны три типа launcher:

  • desktop передаёт codex://threads/<id> зарегистрированному Windows-обработчику Codex Desktop. VKodex не запускает ChatGPT.exe из WindowsApps напрямую: такой путь меняется при обновлениях и может создать отдельные процессы, не передав задачу уже работающему приложению;
  • vscode запускает указанный Code.exe с CODEX_HOME, userDataDir и адресом задачи официального расширения;
  • command запускает пользовательскую программу с массивом arguments и необязательным environment. В значениях разрешены подстановки {threadId} и {codexHome}.

owner: "app-server" включает долгоживущего владельца выбранного CODEX_HOME. Он продолжает существующие задачи без открытия окна. Если Desktop или VS Code уже держит active writer конкретной задачи, VKodex распознаёт это до изменения состояния и использует подключение того клиента. После отправки команда никогда не повторяется через другого владельца.

Старые CODEX_HOME и CODEX_EXTRA_HOMES продолжают работать для чтения списков. При отсутствии CODEX_SOURCES основной каталог автоматически получает launcher desktop, а дополнительные каталоги нужно перевести на новый формат, чтобы VKodex мог адресно открыть их клиент.

Это каталоги данных Codex, не репозитории проектов. В старом формате основной каталог остаётся в поиске, а повторяющиеся пути учитываются один раз. CODEX_SOURCES полностью заменяет этот список: его первый элемент становится основным, остальные — дополнительными; дублирующиеся пути считаются ошибкой конфигурации. ~ означает домашнюю папку пользователя Windows. Относительные пути считаются от каталога запуска; для явности используйте абсолютные пути. В JSON на Windows удобнее писать / вместо обратных слешей.

После правки перезапустите VKodex и обновите список задач. Задачи всех читаемых источников объединяются по времени обновления. Название каталога показывается рядом с задачей только тогда, когда валидные задачи одновременно найдены более чем в одном источнике; пустой или нечитаемый дополнительный каталог не добавляет префикс к основному списку.

Команда /limits учитывает эти профили отдельно. В менеджере она читает лимиты каждого настроенного CODEX_HOME, а в беседе задачи выбирает источник по сохранённому sourceId. Для ChatGPT-авторизации строка Аккаунт содержит имя, если Codex его сообщает, и адрес входа; для API key показывается только тип аккаунта. Токены и идентификаторы аккаунта не запрашиваются для отображения, не записываются в базу VKodex и не попадают в Git.

Если для аккаунта доступен кредит сброса лимита, /limits показывает кнопку Сбросить лимит. В менеджере кнопка подписана каталогом, когда подключено несколько профилей; перед списанием VKodex ещё раз показывает выбранные каталог и аккаунт и требует явного подтверждения. Сброс выполняется через локальный Codex App Server с уникальным idempotency key. Если ответ потерян, кнопка Проверить тот же запрос повторяет ту же операцию с прежним ключом, поэтому второй кредит не списывается. VKodex не применяет кредиты автоматически и не расходует их при обычном обновлении экрана лимитов.

Если дополнительный CLI/work-профиль содержит задачи, но не имеет собственного файла проектов десктопа, VKodex сопоставляет их с общими локальными проектами по рабочей директории. Привязка выполняется только при единственном наиболее точном совпадении корня; остальные задачи остаются в разделе «Без проекта». Копии с одинаковым ID в разных каталогах не смешиваются: у них отдельные VK-привязки, источники истории и кеши моделей.

Для команд и live-событий существующей задачи мост использует владельца её профиля и проверяет sourceId до любого изменения. Профильный App Server самостоятельно подключает незагруженную задачу; active-writer отказ от UI-клиента считается подтверждением, что задача уже открыта, а не поводом запускать окно и ждать 30 секунд. Все операции одного владельца используют общее загруженное состояние задачи: повторный thread/resume не отправляется во время активного хода, потому что он способен прервать этот ход. После разрыва соединения кэш владения сбрасывается и создаётся заново. Launcher вызывается только /open. При несовпадении каталога или аккаунта, потере владельца после начала записи либо несовместимой версии протокола команда блокируется; другой исполнитель не запускается. Отправленная команда с неизвестным результатом сверяется по неизменяемому operation ID и автоматически не повторяется.

Перенос между каталогами запускается из меню задачи: Переместить → В другой каталог. Это фоновая операция с этапами в SQLite, а не длительный запрос внутри обработчика кнопки. Обработчик VK сразу возвращается; после перезапуска VKodex продолжает сохранённый этап. Повторные попытки имеют увеличивающуюся паузу и ограничение количества. Операция, которая ещё выполняется в живом процессе, не запускается вторым исполнителем даже после таймаута интерфейса.

Если исходная задача состоит в подтверждённом проекте, VKodex ищет в целевом каталоге единственный проект с тем же названием и упорядоченными рабочими корнями. Если его нет, проект создаётся через штатный Codex App Server с ключом идемпотентности до создания fork. После создания проверяются нативный ответ и видимость проекта в целевом каталоге. Изменение проекта источника, неоднозначное совпадение или неизвестный результат создания останавливают перенос до нового подтверждения; проект другого каталога не подставляется по одному только имени. Для исходной задачи без проекта остаётся явный выбор проекта или варианта «Без проекта». Проверка этого нового пути пока прошла на изолированном App Server и в тестах; живой перенос через VK с автоматическим созданием проекта ещё не принят.

Перед копированием фиксируется последний завершённый ход и состояние исходного журнала. Создаётся новый thread ID в выбранном CODEX_HOME; модель, уровень рассуждения и рабочая папка сохраняются. Paginated-история адаптируется через временную копию JSONL в <целевой CODEX_HOME>/.vkodex-transfer-staging. До переключения VK-беседы семантически сравниваются все страницы завершённой истории: различия пользовательских и агентских сообщений блокируют перенос, а локальные проекционные элементы reasoning, fileChange и contextCompaction, которые App Server может не переносить между профилями, из сравнения исключаются. Также проверяются граница истории, неизменность источника, нативные название и назначение проекта и готовность живого клиента назначения — в том числе для варианта Без проекта. Проект, который каталог лишь вывел из пути рабочей папки, не считается подтверждённым назначением. После открытия клиента название и проект проверяются заново.

Цель сохраняется отдельно от истории. Активная цель приостанавливается; копия также остаётся на паузе, чтобы не запустить двух агентов. После завершения переноса её можно возобновить через /goal. В новый каталог передаётся только оставшийся бюджет, а не полный бюджет заново. API Codex не позволяет импортировать накопленные счётчики: предыдущий расход и время сохраняются в локальной базе VKodex и показываются в /goal отдельно от счётчиков новой копии. Лимиты аккаунта переносом не сбрасываются.

ID подтверждённого fork сохраняется до дальнейших операций с метаданными. Повтор подготовки использует эту же копию. Если Codex не подтвердил ID результата, автоматический fork не повторяется и случайный потомок исходной задачи не принимается за результат операции. Изменение исходной истории или цели также останавливает переключение: источник и копия сохраняются для проверки. Во время подготовки переноса новые сообщения и изменяющие команды не отправляются в старую задачу; бот объясняет причину. Отменить перенос снимает эту блокировку, если этап уже закончил выполняться и переключения ещё не было. Созданная копия при отмене не удаляется, цель автоматически не запускается.

После атомарного переключения VK-привязки выполняется архивация источника через его профильного владельца. Результат проверяется по записи исходной задачи и сохранённой границе истории, а не по исчезновению из списка. Два последовательных живых цикла .codex → .codex-work → .codex прошли без ручной правки: сохранились история, название, явный проект назначения, рабочая папка, модель/effort и паузная цель с бюджетом; оба источника были архивированы. Короткий ход после возврата в .codex подтверждён. Ход в .codex-work не запускался из-за исчерпанного лимита этого аккаунта и остаётся отдельной живой проверкой после восстановления лимита. Отдельный аварийный прогон намеренно завершил процесс после переключения привязки и до архивации: новый процесс продолжил ту же операцию с мёртвой lease, создал ровно один fork и подтвердил архив. Неизвестный результат записи никогда не повторяется вслепую: VKodex сначала проверяет архив чтением. Если после копирования изменились история или цель источника, архивация останавливается и обе копии сохраняются для сверки. Источник, который удерживает UI-клиент без поддерживаемого канала архивации, остаётся проверяемой блокировкой, а не поводом закрыть Codex или снять writer принудительно.

/health отдельно показывает незавершённые переносы, операции без прогресса и архивные задачи с активной VK-привязкой. Старые записи без сохранённой границы истории не запускаются автоматически: недостающие сведения не восстанавливаются догадкой. Если у старой записи граница есть, источник уже архивирован и семантическая история источника совпадает с префиксом истории целевой копии, VKodex может закрыть тот же этап без нового fork и правки базы. Если источник получил новый ход, повтор архивации блокируется даже после переключения VK-беседы.

Проверки восстановления выполняются на отдельных тестовых задачах: аварийное завершение процесса после сохранения ID fork, после открытия назначения и после переключения привязки, перенос цели на паузе с оставшимся бюджетом и обработка истории длиннее одной страницы. Живые аварийные тесты выполнялись отдельными процессами и подтвердили продолжение с каждой сохранённой стадии, ровно один fork, корректную VK-привязку и архивацию источника. Ожидание завершения нативного процесса отделено от закрытия его потоков вывода: задержка Windows при закрытии stdio не должна превращать подтверждённый fork в ошибку.

Названия, проекты и цели читаются после записи. При переносе завершённая цель остаётся завершённой; активная ставится на паузу. Если оставшийся бюджет равен нулю, для API, принимающего только положительное число, используется технический минимум 1 токен и запрещающий продолжение статус budgetLimited (либо complete для уже достигнутой цели). Цель автоматически не запускается.

Не меняйте основной CODEX_HOME или первый источник CODEX_SOURCES при использовании существующей базы VKodex. Добавьте другой каталог в конец CODEX_SOURCES (для старого формата — в CODEX_EXTRA_HOMES) либо создайте отдельную установку с другим BOT_DATA_DIR. Launcher не передаёт секреты VKodex в окружение запускаемого клиента. Не редактируйте базы Codex вручную ради привязки к проекту.

8. Постоянная работа и VPN

VKodex должен работать всё время, пока вы хотите получать сообщения. Компьютер, десктопное приложение и сеть должны оставаться доступны. Сон, выключение компьютера или закрытие процесса моста прекращают доставку.

Необходима раздельная маршрутизация

Для стабильной работы из России недостаточно направить весь компьютер либо целиком в VPN, либо целиком в прямое соединение. Настройте split tunneling с двумя маршрутами:

Трафик Маршрут
VKodex.exe → VK API, Bots Long Poll и серверы загрузки VK DIRECT, через российский IP
Десктопный Codex и его обращения к OpenAI Через VPN/прокси

Если пустить VKodex через зарубежный VPN, VK может отвечать нестабильно или не отвечать вовсе. Если вывести Codex из VPN в сети, где OpenAI недоступен напрямую, перестанут запускаться и продолжаться задачи. Поэтому оба маршрута нужно проверить одновременно: npm run vk:check должен проходить через прямое соединение, а тестовый ход Codex — через VPN.

Подойдёт TUN-клиент с правилами по приложениям или процессам, например v2RayTun. Это лишь пример стороннего клиента: VKodex его не устанавливает и не настраивает. Названия пунктов и формат правил зависят от версии клиента.

Сначала проверьте ручной запуск через npm run desktop:start. Затем установите задачу автозапуска для текущего пользователя:

npm run service:install

Установщик регистрирует задачу VKodex в Планировщике Windows и запускает её сразу. Локальный supervisor поднимает мост снова через пять секунд после любого завершения; Планировщик дополнительно перезапускает сам supervisor при его сбое и не создаёт второй экземпляр поверх работающего. Задача работает только в интерактивном сеансе того же пользователя, что и Codex, а сам мост по-прежнему выполняется как стабильный %LOCALAPPDATA%\VKodex\runtime\VKodex.exe. Запуск от SYSTEM не поддерживается.

Внешний watchdog записывает в supervisor.log, когда health перестал обновляться и когда восстановился. Просроченный health сам по себе не завершает мост: принудительное завершение может оборвать работающие ходы Codex. Supervisor автоматически перезапускает мост только после фактического выхода процесса. Если процесс завис, проверьте причину и согласуйте контролируемый перезапуск с учётом активных задач.

VKodex пишет один и тот же структурированный поток одновременно в консоль и локальный BOT_DATA_DIR/logs/vkodex-<запуск>.log; ошибки и стеки аварий входят в тот же файл с соответствующим уровнем. История запусков и кодов завершения хранится отдельно в supervisor.log. Файлы разных запусков не перезаписываются. Эта папка входит в приватный data/, исключённый из Git. Не публикуйте журналы без просмотра: сообщения сторонних библиотек могут содержать локальные пути и технические данные.

Окно supervisor намеренно остаётся видимым с логотипом VKodex и заголовком VKodex Bridge - DO NOT CLOSE. Его консоль принадлежит небольшому локально собираемому VKodexSupervisor.exe, поэтому Windows показывает фирменную иконку и в панели задач, а не иконку PowerShell. В окне отображаются предупреждение, события supervisor и живой структурированный лог VKodex; те же строки одновременно сохраняются в файл текущего запуска. Не закрывайте окно: закрытие вручную останавливает и supervisor, и мост. Если это произошло, запустите задачу VKodex в Планировщике либо повторно выполните npm run service:install.

Проверить состояние можно через Get-ScheduledTask -TaskName VKodex и Get-ScheduledTaskInfo -TaskName VKodex. Для удаления задачи выполните npm run service:uninstall. После переноса клона в другую папку переустановите задачу, чтобы обновить абсолютные пути.

Не запускайте одновременно задачу Планировщика и desktop:start в терминале. После входа в Windows потребуется также работающий и авторизованный Codex.

npm run service:controlled-restart сохраняет в data/desktop/restart-intent.json идентичности задач, которые в сохранённом состоянии отмечены как работающие, затем отдельный worker останавливает мост; supervisor запускает замену. Режим совместимости resume-interrupted использует intent v1 и может отправить один технический запрос на продолжение, если новая проверка показывает interrupted. Журнал предотвращает повтор этого служебного запроса, но не доказывает, что прерван именно ход из снимка или что его прервал этот перезапуск. Снимок не является полной проверкой отсутствия работы; остановка общих профильных backend может затронуть другие задачи.

Для восстановления без автоматической отправки предусмотрен явный режим npm run service:controlled-restart -- -RecoveryPolicy reconcile-only. Его intent v2 не запускает дополнительный recovery-tick, профильное подключение, чтение через inspectTask или запрос «продолжи». Подтверждённый captured turn managed worker сверяется с точной привязкой, поколением потока и неизменным ready claim; остальные результаты сохраняются как ожидание. Нативные active/idle сами по себе не идентифицируют ход из снимка, поэтому native-задачи в этом режиме остаются pending. Неизвестная политика отклоняется до остановки процесса. Незавершённый intent не заменяется новым снимком; текущие cooperating helpers сериализуют публикацию и архивацию, проверяя точное содержимое перед перемещением в архив. Старые helpers и ручные изменения файлов не входят в этот протокол.

reconcile-only ограничивает только восстановление: это не подтверждение безопасной остановки, физического освобождения прежнего backend или готовности Desktop. Штатный запуск моста всё ещё включает наблюдение и обычную обработку входящих сообщений. Для безопасного обновления отдельно нужны проверенная сборка и граница обслуживания для всех затрагиваемых backend; не используйте эту команду как обход удержания чата другим владельцем.

Отдельный процесс для TUN

На Windows команды запуска используют отдельную копию Node.js:

%LOCALAPPDATA%/VKodex/runtime/VKodex.exe

Имя и путь не меняются вместе с расположением репозитория или версией системного Node.js. В v2RayTun, sing-box или другом TUN-клиенте направьте этот процесс в DIRECT. Используйте полный путь, если клиент поддерживает правила по пути. VKodexSupervisor.exe только управляет локальными процессами и сам не обращается к VK или OpenAI, поэтому добавлять его в правила маршрутизации не требуется.

Это исключение касается VKodex, а не всего node.exe и не самого Codex. Не добавляйте в DIRECT десктопный Codex: его доступ к OpenAI должен оставаться в VPN-маршруте. VKodex не изменяет настройки VPN.

desktop:dev, desktop:start, desktop:probe и vk:check используют этот runtime автоматически. Команда получения ID выше тоже запускается через него.

9. Обновление и резервные копии

Проверка отдельной сборки без запуска

node dist/src/desktop/deployment-artifact-check.js --descriptor "<абсолютный путь к descriptor.json>" --sha256 "<SHA-256 descriptor в нижнем регистре>" — отдельная проверка файлов, а не команда установки. Запускайте её проверенным Node.js из доверенной сборки валидатора; не выполняйте runtime или код ещё не проверенного артефакта. Успешный результат содержит validated_not_launched и хеши, без содержимого конфигурации и локальных путей.

Descriptor находится вне Git и артефакта; версия 1 принимает ровно поля version, artifactRoot, configurationRoot, dataDirectory, manifestSha256. Все каталоги абсолютные; сборка должна быть отдельно от исходной конфигурации и данных. configurationRoot/.env только проверяется как обычный файл, его содержимое не читается. dataDirectory задаёт заранее выбранный эффективный BOT_DATA_DIR; относительное значение конфигурации следует разрешать от исходного каталога, не от каталога сборки.

В artifactRoot/artifact-manifest.json обязательны ровно version, sourceCommit, sourceTree, node (version, platform, arch, modules), sdkVersion и files. files перечисляет все файлы, кроме самого manifest: относительный путь с / → { "size": число_байт, "sha256": хеш }. Проверяются полный состав и хеши, фиксированные файлы runtime/bridge/scripts/icon/package/lock, закреплённые SDK/CLI и ESM export SDK. Ссылки, junction, неподдерживаемые пути, вложенные зависимости в каталогах приложения и добавленные/изменённые файлы отклоняются. Допустимы только области dist, scripts, node_modules, runtime, docs/logo.ico, package.json и package-lock.json; не включайте секреты, .env или данные.

Это проверка inventory и заявленных метаданных, не доказательство исполнимости runtime, происхождения сборки из указанного коммита или готовности Desktop. Внутренний план сохраняет исходный cwd, абсолютный BOT_DATA_DIR и явно пустые NODE_OPTIONS/NODE_PATH. Валидатор не запускает этот план, не копирует runtime, не создаёт каталоги, не открывает базу и не меняет задачу Планировщика. Существующие команды запуска и установки не используют descriptor. service:install -NoStart не является безопасной проверкой: существующий установщик всё равно останавливает прежнюю службу.

Закреплённый план запуска без установки

Доверенная сборка также содержит библиотеку deployment-binding и отдельный внутренний CLI deployment-plan-private. Они только проверяют файлы и возвращают данные. Новый явный путь C#/PowerShell использует этот план; обычный установщик и существующая служба автоматически на него не переключаются. План не снимает владение чатом и не подтверждает исправление Desktop.

Launch-binding версии 1 содержит ровно version, descriptorPath, descriptorSha256, bootstrapRoot, bootstrapManifestSha256, stableRuntimePath, stableRuntimeSha256. Внутренний CLI принимает только --launch-binding <абсолютный файл> --launch-binding-sha256 <независимый SHA-256>. Bootstrap-manifest имеет поля version, protocol: "deployment-plan-v1", files и фиксированный полный состав валидатора, метаданных ESM, launcher и supervisor/watchdog. Эти файлы проверяются как данные, не исполняются. Конфигурация может содержать каталог данных; bootstrap и артефакт должны находиться вне обоих. Не сохраняйте binding/manifest или конфигурацию в Git.

План выбирает именно отдельно закреплённый stableRuntimePath, чтобы будущий запуск сохранял существующий путь runtime для правил маршрутизации. Его хеш должен совпадать и с независимым pin, и с проверенным inventory runtime артефакта. Несовпадение означает отказ, без копирования, ремонта или запасного runtime. Проверки повторяются после чтения артефакта. Результат неизменяемый, со статусом validated_not_launched; planDeploymentAction возвращает только предложенные аргументы, без установки.

Внутренний CLI выводит один ограниченный JSON-record с необходимыми локальными путями; это не публичный журнал. Он не читает содержимое .env. Запущенный Node и код CLI уже должны быть доверенными: самопроверка bootstrap после старта не устанавливает это доверие и не отменяет ранее выполненный NODE_OPTIONS.

Явный запуск закреплённой Windows-сборки

Launcher принимает ровно --launch-binding <файл> --launch-binding-sha256 <хеш> --operation <режим>. plan-only запускает только заранее проверенный Node-валидатор и печатает план; run-once запускает выбранный bridge один раз; supervise запускает цикл PowerShell с повторной проверкой при каждом старте. supervise-once предназначен для ограниченных стендов: одна итерация без watchdog. Проверка библиотеки и planDeploymentAction по-прежнему не запускают дочерних процессов. deployment-execution — отдельная явная граница исполнения, не импортируемая внутренним CLI.

До первого C#-процесса доверенный родитель проверяет launcher и подавляет стартовые Node/CLR hooks; самостоятельная проверка внутри EXE не удостоверяет уже начавшееся исполнение. C# проверяет закреплённые bootstrap/runtime до Node, строго разбирает один ограниченный ответ, сохраняет исходные cwd/config/data и удерживает файлы кода/runtime без совместного доступа на запись/удаление на время дочернего supervisor. Mutable binding/descriptor освобождаются; последующие итерации проверяют их по первоначальным хешам. Отказ проверки (код 86) прекращает цикл без запасной старой версии. Watchdog только диагностирует и не завершает процессы или ходы.

Bootstrap и артефакт должны быть заранее подготовлены как доверенные неизменяемые каталоги. Хеширование даёт наблюдение на момент проверки, не файловую транзакцию или защиту от того же пользователя, способного заменить родителя/окружение. Эти команды не устанавливают службу, не обновляют общий runtime, не переключают старую базу и не удостоверяют бесшовность Desktop. Переключение работающей службы требует отдельного согласованного окна, исключения старого restart-loop, согласованной резервной копии и проверки исходных процессов/владения.

Скрытая versioned-цепочка не гарантирует передачу stdout/stderr в консоль. После запуска logger структурированная диагностика моста пишется в отдельный vkodex-<run ID>.log выбранного каталога данных; supervisor записывает фактический код завершения. Поэтому ранняя ошибка, выведенная только в stderr до инициализации logger, может оказаться недоступной. Успешный запуск проверяют по структурированным журналам моста и health/ownership, а не только по PID supervisor. Ожидание процесса и потоков при проверке плана ограничено; эти ограничения никогда не завершают мост или native backend.

Обновление исходников

  1. Штатно остановите VKodex в согласованное окно обслуживания. Остановка моста может прервать ходы в принадлежащих ему backend; снимок и reconcile-only не гарантируют их сохранение. Desktop и VS Code отдельно останавливать не требуется.
  2. Сохраните резервную копию конфигурации и данных.
  3. Проверьте git status: если есть собственные изменения, сохраните или согласуйте их перед обновлением. Не используйте принудительный сброс.
  4. В папке репозитория выполните:
git pull --ff-only
npm ci
npm run check
npm run vk:check
npm run desktop:start

Health check

Диагностический просмотр задачи через профильный App Server использует только thread/read: он не запускает thread/resume и не меняет подписку живого наблюдателя. Ответ с notLoaded, неизвестным статусом или без статуса не подтверждает рабочее подключение. Таймаут изменяющей команды оставляет её результат неизвестным, но сам по себе больше не завершает общий App Server: остальные задачи и уведомления продолжают обслуживаться. Не повторяйте такую команду вслепую; факт таймаута не доказывает, что Codex её отклонил.

Локальные наблюдатели одной задачи делят одну upstream-подписку: закрытие одного наблюдателя не отключает остальных. Повторное подключение ждёт завершения предыдущего unsubscribe; его неопределённый результат не разрешает слепой resume. При отправке запроса из VK мост ждёт подключение этой задачи, а не завершение всех фоновых подключений. Закрытие завершённой подписки не ждёт отправки финального ответа в VK: сохранённая очередь доставки продолжает работать независимо. Это не подтверждение передачи writer другому клиенту.

Если локальная подготовка состояния падает после подтверждения подписки Codex, VKodex всё равно пытается отписать эту задачу, не закрывая общий сервер. Поздний ответ resume от потерянного соединения не может подтвердить нового владельца или опубликовать начальное состояние.

Входящий запрос сохраняется в долговечный журнал до ожидания подключения своей задачи. Это ожидание не зависит от фонового чтения историй, обновления панелей или каталога. Ошибка подключения либо смена привязки запрещает отправку запроса; локальные команды восстановления, например /detach, остаются доступны. Запоздавшие результаты каталога и истории не заменяют новую подписку или её контрольную точку. Сброс читателя истории также отменяет применение ещё не завершённых чтений.

Фоновое наблюдение также разделено по задачам: медленное чтение истории, проверка создаваемой задачи или обновление панелей не удерживает общий цикл подключений. Незавершённое задание не запускается повторно на каждом тике. Health отдельно показывает этап и возраст задержки (history, catalog, creator-inspect, panels), даже когда сам таймер моста исправен. Общий каталог по-прежнему нужен для фонового поиска ещё не подключённых задач; это ожидание не блокирует обслуживание существующих подписок.

Если отправка отклонена до записи, профиль сообщил owner-busy, а native discovery подтверждает именно no-client-found, фоновый health может один раз открыть существующий чат через обычный Desktop deep link. Это разрешено только для настроенного основного каталога и Desktop launcher, при неизменной привязке и без переноса, creator, исключительного владельца или startup quarantine. Попытка сохраняется до открытия; повторные тики и перезапуск моста не повторяют её в том же эпизоде отказа. Подтверждением восстановления служит новая проверенная пассивная snapshot, а не запуск окна, локальная аренда или старое состояние idle. Отклонённое сообщение не отправляется заново; цели, настройки модели и writer lifecycle не изменяются этим механизмом. Тайм-ауты, повреждённые ответы, дополнительные каталоги и custom/VS Code launchers автоматически не открываются. В /health результат виден как codex_native_observation_recovery.

Native-owner health recovery only opens an existing task with the configured primary Desktop launcher after an exact missing-owner discovery and scoped owner-busy evidence. A durable single-flight attempt prevents repeated opens during an unresolved outage. Only a verified passive snapshot proves recovered observation; it does not prove input acceptance. This path never replays input, resumes a writer, changes goals/settings, or falls through an exclusive owner fence.

Внутри одного соединения App Server повтор идентичного незавершённого серверного запроса не вызывает обработчик вопроса или инструмента заново. Разные данные с тем же ожидающим RPC ID отклоняются без закрытия остальных задач; поздний ответ обработчика не попадает в новое соединение. Защита касается ожидающих запросов, а не долговременного восстановления завершённых операций.

Отписка от наблюдения не удаляет ожидающий вопрос Codex: задача может продолжать работать без подписчика. Вопрос закрывается при ответе, замене, подтверждённой выгрузке задачи или потере её соединения. Перед отправкой ответа повторно проверяется, что вопрос не сменился за время подготовки; ошибка одного наблюдателя вопросов не мешает остальным.

IPC-клиент также поддерживает явно переданный обработчик входящих native-запросов для проверки Gateway. По умолчанию он отклоняет discovery и не объявляет мост владельцем задач. Этот интерфейс сам по себе не включает managed workers и не подтверждает совместимость native UI. Экспериментальный launcher требует trusted hook записи долговечной привязки для любой задачи с утверждённой политикой: без него запуск отклоняется до резервации. Hook вызывается после резервации и до запуска worker; отдельное read-only подключение к SQLite сначала проверяет сохранённую привязку к точной задаче, источнику, worker epoch и семейству. Финальная проверка через подключение с короткой write-lock транзакцией и синхронный вызов spawn проходят под одним блокированием, чтобы конкурентный handoff не завершился между ними. Точная привязка сохраняется только в защищённом состоянии worker. При старте worker проверяет её ещё раз до регистрации host, а регистрацию проводит под новой короткой блокировкой claim. Ошибка оставляет резервацию для явной сверки; если процесс мог быть создан, результат помечается неизвестным. Рабочий мост этот путь ещё не вызывает; короткие проверки не доказывают исключительное владение нативным writer после старта.

Экспериментальный CLI Gateway включается только явной опцией изолированного managed worker; рабочий мост её не задаёт. Он использует WebSocket на 127.0.0.1 с ключом только в памяти. Без подтверждённого источника WebSocket допускает чтение, но отклоняет turn/start. Первый текстовый turn/start требует привязки к квалифицированному журналу создания задачи, единственному rollout в изолированном каталоге и всё ещё пустой истории; затем проверяются тот же backend, текущий владелец, пустые очередь и цель, отсутствие другого автоматического запуска и точные настройки gpt-5.6-sol / low / read-only. Ответ о принятии возвращается только после долговечной квитанции, неопределённый результат не повторяется вслепую. Проверка простоя читает backend по закрытому owner-каналу, не вытесняя CLI-сессию; потеря владельца отзывает WebSocket и его ключ без остановки backend. При обычном отключении frontend ход остаётся у worker. Эти изолированные тесты ещё не означают приёмку настоящего CLI, Desktop или VS Code.

Явно включаемый stock-путь managed worker поддерживает прямой текстовый запуск из нативного клиента и однородную нативную очередь на одном worker с уже утверждённой политикой полного доступа. Прямой запуск возвращает настоящий долговечный результат turn/start, а не подменяется thread/queue/add. Перед новым прямым запуском каждый предыдущий запрос из очереди должен сопоставиться с одним уникальным пользовательским элементом в стабильной завершённой истории. Между прямыми запросами и очередью нельзя переиспользовать client ID. Явная отписка, новое подключение наблюдателя и сообщение об отключении клиента отзывают незавершённый допуск; обрыв самого транспорта не отзывает его и не останавливает backend. Новая проверка владельца всё ещё может отклонить запуск до записи. Точный повтор с записью в журнале worker получает лишь сохранённый результат: неизвестная операция вслепую не отправляется снова. Нетекстовый ввод, неподдерживаемые настройки и несовместимый контекст отклоняются до записи. Изолированные протокольные тесты не подтверждают работу настоящего интерфейса Desktop или VS Code; рабочий мост этот путь автоматически не включает.

Входящие IPC-broadcast принимаются как с адресатом этого клиента, так и без списка адресатов: именно так native-клиент объявляет начало наблюдения при открытии задачи. Чужие, пустые и некорректные списки адресатов игнорируются; обработчики состояния дополнительно проверяют владельца, каталог и задачу.

Наблюдатели одной native-задачи внутри одного IPC-транспорта также используют общую подписку. Отписка отправляется только после закрытия последнего наблюдателя; каждый получает отдельную копию состояния. Конфликтующие копии одной задачи из разных каталогов не объединяются.

После запуска и далее с интервалом HEALTH_CHECK_INTERVAL_MS VKodex проверяет всю рабочую цепочку:

  • целостность SQLite через PRAGMA quick_check;
  • работу секундного runtime-цикла и длительность текущего обновления;
  • размер и возраст важной очереди VK (ответы и панели) отдельно от фоновой трансляции (комментарии и индикатор), а также паузу rate limit;
  • локальный Bots Long Poll, права токена, настройки событий и доступность Long Poll server;
  • чтение всех настроенных каталогов CODEX_HOME;
  • доступность рабочих папок подключённых задач, чтобы переименование или удаление каталога не выглядело как исправный Codex;
  • безопасное чтение состояния цели через локальный API Codex без вывода её формулировки в health-отчёт;
  • число подключённых активных трансляций;
  • системные ошибки задач Codex, включая исчерпание лимита аккаунта: они дают DEGRADED, даже если VK и IPC работают;
  • named pipe Codex и совместимость stream protocol v11. Полный protocol canary выполняется при запуске, вручную через /health и не реже одного раза в десять минут.

Подключение каждой live-задачи дополнительно проверяется в фоне каждые 30 секунд. После перезапуска профильного App Server мост переподключает подписку без открытия окна и без повторного запуска промпта; устаревшее поколение событий игнорируется. Если владелец отсутствует, индикатор «думаю» останавливается. /menu доступно и без связи; кнопка «Открыть в Codex» или /open явно открывает задачу через launcher выбранного каталога. Ошибка systemError не считается работающим ходом, даже если в восстановленной истории осталось старое inProgress. При исчерпании лимита бот предлагает /limits, а не продолжает анимацию.

Последний отчёт сохраняется без токенов и содержимого сообщений в BOT_DATA_DIR/health.json. Текущее состояние процесса и причина обработанного завершения записываются без конфигурации и текста ошибок в BOT_DATA_DIR/runtime-process.json. Команда ниже читает health-файл, проверяет его свежесть и возвращает ненулевой код, если мост остановился, отчёт устарел или состояние отличается от OK:

npm run health:check

Встроенная проверка не может отправить сообщение после гибели собственного процесса, поэтому для постоянной установки нужен внешний перезапуск через service:install либо другой supervisor. FAILED отправляется в менеджер после двух последовательных проверок, а DEGRADED — только если держится десять проверок подряд. Сообщение health check снова OK приходит после трёх последовательных успешных проверок, поэтому краткая пауза VK не создаёт каскад тревог и восстановлений. Если сам VK недоступен, предупреждение остаётся в устойчивой очереди и отправляется после восстановления связи.

DEGRADED означает, что основная работа может продолжаться, но часть цепочки не подтверждена: например, нет задачи для protocol canary, выполняющаяся задача потеряла владельца, VK включил временную паузу, последняя попытка доставки завершилась ошибкой или важная очередь не очищается более 30 секунд. Наличие ожидающей фоновой правки комментария либо думаю без ошибки доставки само по себе не ухудшает health-state и не повышает его до FAILED. Закрытые и бездействующие задачи могут не держать live-подписку и сами по себе не ухудшают health-state. Профильный App Server восстанавливает выгруженную задачу без фокуса окна; /open нужен только для явного показа задачи. FAILED означает отказ обязательной проверки или задержку одного и того же важного ответа/панели более пяти минут. После обновления Codex дополнительно выполните desktop:probe, /health и тестовый ход в отдельной задаче. Не меняйте вручную версию протокола, чтобы обойти отказ адаптера.

Что копировать

При остановленном мосте скопируйте в защищённое место:

  • .env;
  • всю папку BOT_DATA_DIR, включая vkodex.sqlite и, если они есть, файлы -wal/-shm.

В базе находятся привязки бесед, очередь и сведения об обработанных событиях. Не удаляйте её при обычном обновлении: потеря базы может привести к повторному созданию VK-бесед. Резервная копия VKodex не заменяет отдельное резервирование проектов и данных самого Codex.

База привязана к настроенным владельцу и сообществу. Для другого аккаунта или сообщества используйте отдельную папку данных; не переиспользуйте чужую базу.

Обновление Node.js

Приватный VKodex.exe не заменяется автоматически. Если вы обновляете его:

  1. Остановите VKodex.
  2. Установите нужный поддерживаемый Node.js.
  3. Переместите только приватный VKodex.exe из папки runtime в корзину.
  4. Выполните npm ci, npm run runtime:prepare и npm run check.
  5. Повторно запустите мост.

При несовпадении архитектуры или ABI нативных модулей запуск блокируется. Не удаляйте вместе с runtime .env, данные VKodex или каталоги Codex.

10. Решение проблем

Симптом Что проверить
Бот не отвечает вообще Есть ли строка VK Long Poll started; правильны ли ключ, ID сообщества и один VK_OWNER_ID; разрешены ли сообщения от сообщества. Запустите npm run vk:check.
Текст работает, кнопки — нет Включено ли событие message_event и установлена ли версия Long Poll 5.199.
Редактирование в VK не доходит до Codex Включено ли событие message_edit; действительно ли это последнее сообщение того же автора и запустило ли оно отдельный live-ход. Уточнение, отправленное во время работы агента, безопасно переписать нельзя.
В каталоге нет задач Работает ли Codex под тем же пользователем; правильно ли заданы CODEX_HOME и дополнительные каталоги; что показывает desktop:probe. Архивные и служебные задачи исключены.
Задача видна, но подключение не удалось Codex и VKodex должны работать под тем же пользователем ОС. Проверьте owner: "app-server", путь home, аккаунт и каталог источника в CODEX_SOURCES. notLoaded означает, что задача выгружена из UI; профильный владелец должен подключить её без launcher. Если задача уже открыта в Desktop/VS Code, нужен доступный active-writer канал этого клиента. Подтверждённый отказ до отправки отображается в health как codex_route; мост безопасно переподключает канал в фоне, но не повторяет отклонённый промпт. Для дубликатов ID также проверьте sourceId и путь истории.
Нет приглашения в беседу Откройте менеджер: после создания беседы бот выдаёт ссылку независимо от того, добавил ли VK владельца автоматически. Вступите по ней; отдельной кнопки подтверждения нет. Проверьте разрешение боту работать в беседах.
Неизвестно, создалась ли беседа или выполнилась команда Проверьте VK и Codex вручную. Мост намеренно не повторяет действие после неоднозначного ответа. Не очищайте базу ради повтора.
После обновления осталось старое сообщение о паузе Перезапустите мост. Устаревшая пауза, созданная прежней проверкой участников, будет снята автоматически. Если связь раньше была явно отключена, выберите задачу в менеджере снова.
Выход из беседы не остановил трансляцию Это ожидаемо. Состав беседы не используется как управление доступом. Перед выходом отправьте /detach или отключите связь в менеджере.
Уточнение или следующий ход не отправились notLoaded после завершённого хода не является блокировкой: мост запускает в той же задаче следующий ход и сохраняет её контекст. Реальной блокировкой остаются активный ход, вопрос или подтверждение Codex, несовпадение источника и потеря владельца IPC. Потерянный ответ не означает, что запрос можно безопасно повторить; сначала убедитесь в результате в десктопе.
Codex ждёт разрешения на действие Ответьте в десктопе. Подтверждения через VK пока не подключены. Не отключайте защиту ради работы моста.
Не виден готовый ответ Проверьте, завершился ли ход в Codex, активна ли связь и доступен ли VK. При восстановлении подключения очередь продолжает доставку, но история до первого подключения не пересылается целиком.
Модели недоступны Откройте выбор моделей в Codex и обновите его кеш. Кеш старше суток адаптер считает устаревшим.
Файл или фотография не дошли до Codex Отправляйте фотографии и документы в связанную беседу, не в менеджер. Проверьте лимиты, доступ к серверам загрузки VK и разрешения задачи на локальную папку файлов.
Готовый файл не пришёл в VK Убедитесь, что файл сохранён именно в outbox/, указанную в запросе. Отправьте /files. Файлы из остальных папок и неподтверждённых запросов не собираются.
npm.ps1 cannot be loaded Можно вызывать npm.cmd вместо npm, например npm.cmd ci. Не меняйте глобальную политику исполнения без понимания последствий.
Ошибка загрузки better-sqlite3 или несовместимый runtime Проверьте версию и архитектуру Node.js, переустановите зависимости через npm ci, затем обновите приватный runtime по инструкции выше.
Через VPN не работает VK Настройте split tunneling: полный путь к VKodex.exe — через российский IP (DIRECT), Codex/OpenAI — через VPN. Повторите vk:check; не исключайте весь node.exe.

При сообщении об ошибке укажите версию Windows, Node.js, Codex и ревизию VKodex, команду запуска и безопасный текст ошибки. Не прикладывайте заполненную конфигурацию, базу, токены, личный VK ID или приватную переписку.

11. Безопасность и ограничения

Приватный менеджер VKodex рассчитан на одного владельца. Его меню и изменяющие кнопки в связанных беседах доступны только VK_OWNER_ID.

Связанная беседа задачи намеренно является общей поверхностью для промптов. Мост не читает и не проверяет список участников: любое входящее сообщение не от самого сообщества становится запросом к Codex, включая текст и поддерживаемые вложения от постороннего участника. Такой участник может влиять на задачу, файлы и рабочий каталог через инструкции агенту, а также видеть прогресс, ответы и исходящие файлы. Ограничение кнопок владельцем не является защитой от обычного текстового промпта. Не добавляйте в связанную беседу людей, которым не доверяете управление этой задачей.

Пересылаемый текст хранится в VK и в приватной базе моста; вложения — в VK и в локальной папке файлов. Не подключайте задачи с данными, которые нельзя передавать всем участникам выбранной беседы. Состав беседы не является границей безопасности.

Файл .env, папка data/, SQLite-базы и логи исключены из Git. Если задаёте нестандартный BOT_DATA_DIR внутри репозитория, добавьте всю папку в .git/info/exclude и проверьте git status. Сам факт наличия .gitignore не защищает секрет, уже попавший в коммит или скриншот.

Чего пока нет в десктопном адаптере

Возможность Текущее поведение
Подтверждения и вопросы с вариантами ответа Обрабатываются в десктопе.
Отдельные типы медиа Принимаются фотографии и документы; видео, голосовые сообщения и другие типы нужно передавать как документ.
Публичная ссылка «Поделиться» Создаётся только в самом Codex.
Управление удалённым или облачным Codex Эта инструкция и адаптер предназначены для локального десктопа.

Каталоги Codex не редактируются вручную. Для каждого CODEX_HOME с owner: "app-server" мост использует отдельное долгоживущее соединение codex app-server --stdio; одинаковые thread ID из разных каталогов не смешиваются. Создание остаётся отдельной атомарной границей с первым ходом, после которой профильный владелец принимает продолжение, остановку, штатную очередь, вопросы, модель, цель и события. Если задача уже загружена в Desktop или VS Code, active-writer классифицируется до изменения и команда направляется подключённому владельцу клиента. При несовместимой версии или неопределённом результате мост блокирует изменение вместо запуска запасного исполнителя.

12. Прежний режим на Codex SDK

Отдельный режим: запускает собственные сессии и не управляет открытыми задачами десктопа

Этот прототип сохранён в репозитории для разработки. Его команды npm run dev и npm start не являются сокращениями для desktop:dev и desktop:start. Не запускайте оба режима с одним сообществом или одной базой данных.

Для SDK-режима нужны VK_GROUP_TOKEN, VK_GROUP_ID, VK_OWNER_IDS, VK_ALLOWED_USER_IDS, WORKSPACE_ROOTS и авторизация Codex CLI либо OPENAI_API_KEY. Владелец должен входить в список разрешённых пользователей. Каталоги WORKSPACE_ROOTS должны существовать; не храните .env внутри разрешённых агенту рабочих папок.

npm run dev

Для собранной версии:

npm run build
npm start

Начните с /bootstrap в личном диалоге. Затем создайте сессию командой /new my-repository | Название задачи; папка должна находиться внутри WORKSPACE_ROOTS.

Команда Действие в SDK-режиме
/bootstrap Попытаться создать общую управляющую беседу.
/new <workspace> | <title> Создать собственную сессию Codex.
/list, /use <id> Показать сессии и выбрать одну в управляющем чате.
/status Показать состояние.
/stop, /close Остановить ход или архивировать сессию в отдельной беседе.
/help Показать справку.

VK_CONVERSATION_MODE=managed требует отдельные беседы, single использует выбор сессии в одном управляющем чате, auto пытается создать беседу и при неудаче оставляет сессию в общем чате. В режиме single команды /stop и /close недоступны.

Файлы принимаются в .vkcodex/inbox/<turn-id>/ и отправляются из .vkcodex/outbox/<turn-id>/ внутри рабочего каталога. Архивы не распаковываются. Лимиты файлов и другие настройки описаны в .env.example.

Это не изоляция участников друг от друга: разрешённые участники управляющего чата могут выбирать общие сессии. Интерактивные подтверждения через VK не реализованы. Дополнительные переменные из CODEX_ENV_ALLOWLIST доступны процессу агента; не добавляйте туда секреты без необходимости.

Проверка с реальным сообществом описана в SDK smoke-test. Docker-конфигурация относится только к этому режиму.

13. Разработка и лицензия

npm run typecheck
npm test
npm run build

Или все три проверки одной командой: npm run check. Автоматические тесты используют подмены VK и Codex; они не отправляют сообщения настоящим пользователям. Проверку реальной интеграции выполняйте отдельно на собственном сообществе и тестовой задаче.

VKodex — независимый проект, не официальный продукт VK или OpenAI.

Отложенный запрос: /queue

В беседе задачи отправь /queue <промпт> (можно с новой строки и с вложениями). VKodex добавит запрос через thread/queue/add в штатную очередь Codex, не вмешиваясь в текущий ход. Если задача свободна, Codex может начать его сразу. Хранением очереди и запуском занимается Codex; отдельного планировщика очереди в VKodex нет. Клиент задачи должен быть подключён. При неопределённом результате добавление автоматически не повторяется. Редактирование уже поставленного запроса выполняется в Codex.

Если Codex подтвердил добавление, но VKodex не увидел последующий ход, /health показывает сохранённое подтверждение и прогресс чтения истории, включая время полного прохода без терминального доказательства. Мост ищет точный ID запроса и снимает неопределённость только после проверки завершённого хода по полной нативной записи. Пустая текущая очередь, законченный поиск без совпадения или отсутствие доступного сканера не доказывают отказ: запрос не повторяется и подтверждение не удаляется автоматически.

Вопросы Codex в VK: /questions

Health отделяет сохранённые подтверждения запросов от удержания legacy-подписки. Старый ACK сам по себе не препятствует безопасному освобождению, но неизвестный результат текущей операции, работающий ход, цель, дочерняя задача или неполный ответ backend блокируют его. Наблюдение и сверка истории продолжаются отдельно. После перезапуска сохранённый факт освобождения не разрешает заново захватить writer: до проверки текущего владельца новый legacy-запуск отклоняется. Общий процесс App Server ради отдельного чата не останавливается.

Для контролируемой миграции старого исполнителя доступен явный режим predecessor-maintenance. Доверенный локальный оператор заранее сохраняет полный снимок в BOT_DATA_DIR/predecessor-maintenance.json и задаёт независимый SHA-256 через VKODEX_PREDECESSOR_SNAPSHOT_SHA256. Снимок версии 1 с политикой reconcile-only содержит точные PID/время рождения/образ процессов, все legacy-источники и все их привязки, включая idle и отключённые. Неполный снимок, изменение привязки при первоначальной установке или неверный pin запрещают запуск. Уже установленный карантин может восстановиться после изменения привязок только при прежних pin, политике источников и отдельно сохранённой идентичности того же физического SQLite-файла. Это остаётся degraded-режимом; строгое сравнение области перед действием не ослабляется. Исторический fence без физического pin сначала требует точного совпадения привязок. Этот снимок не является разрешением на остановку процессов или доказательством освобождения native writer.

В этом режиме весь разрешённый VK-ввод сохраняется без запуска команд, восстановления batches/очереди, переноса, файловых операций или холодного профильного RPC. Работают только подтверждённые read-only потоки, локальное наблюдение rollout и доставка уже наблюдаемых событий. Health явно сообщает ожидание проверки прежнего исполнителя. Ограничение сохраняется в SQLite: удаление переменной или файла не включает writer обратно. Автоматического снятия ограничения по process-exit receipt нет; не используйте этот режим как обычный restart. Физический cutover и последующий маршрут требуют отдельной проверки.

Наблюдатель завершения Windows-процессов — отдельная read-only утилита, не автоматическая разблокировка health. Он открывает query/synchronize handles для явно выбранного живого набора PID/время рождения/образ/hash, переводит время рождения и выхода в .NET UTC ticks и ждёт в пределах отдельных ограничений захвата и наблюдения. Отсутствующая или недоступная идентичность не считается доказанным выходом. Положительный результат текущего вызова доказывает только завершение выбранного набора, а не полноту списка writers, запрет перезапуска или готовность приложения. Наблюдатель не посылает этим процессам сигналы и не исполняет сохранённые запросы или receipts.

Библиотечный entry point observeMaintenancePredecessorExits связывает явное наблюдение с тем же store, полным pinned-снимком, поколениями привязок и pins successor/configuration. Только после захвата всех исходных handles он выдаёт непереносимый ticket отдельно разрешённому контроллеру; ticket сам по себе не разрешает остановку. Контроллер обязан открыть и перепроверить собственные точные handles. Наблюдатель отзывает ticket при завершении, EOF, ошибке, отмене или истечении срока. Факт выхода сохраняется до короткого CAS: изменение привязки или pins не стирает факт, но запрещает scoped-подтверждение. Сохранённый JSON не восстанавливает ticket или действие. Координатор не запускается автоматически при boot/health и не содержит production-controller. Health показывает лишь диагностический результат выбранного набора; старые ACK, неизвестные операции и legacy fence не меняются. Полнота дочерних процессов, исключение restart authority и настоящий ввод Desktop всё ещё требуют отдельного подтверждения.

Отдельная Windows-команда dist/src/desktop/predecessor-cutover-command.js выполняет только явно согласованные остановку выбранного старого runtime и снимок его сохранённых данных. Она принимает ровно --request <absolute.json> --sha256 <independent SHA-256> --operator-approved-stop stop-selected-legacy-runtime-no-replay; флаг не заменяет разрешение владельца. JSON версии 1 фиксирует operationId, dataDirectory, legacyRoot, privateJournalDirectory, физическую expectedFileIdentity базы, legacySourceIds, snapshotSha256, pins launchBindingPath/launchBindingSha256/configurationSha256, deadlineMs, task (path, definitionSha256, instances GUID/EnginePID) и processes (role, pid, parentPid, birthTicks, imagePath, imageSha256). Поддерживается только прежняя Task-grammar: один Exec выбранного wrapper, одна заключённая в кавычки абсолютная папка и та же рабочая папка/.env. Неизвестные варианты отклоняются, аргументы не исполняются и не угадываются.

Команда должна запускаться доверенным родителем вне дерева выбранного Codex/моста. Перед каждым действием сохраняется отдельный grant, затем helper перепроверяет Windows Task и использует уже открытый точный process handle, а не повторный поиск по PID. Сначала отключается проверенная задача планировщика и останавливаются выбранные restart loops; обнаруженный дополнительный процесс не добавляется к разрешённому набору. XML задачи проверяется до и после вызова с единственным допустимым изменением Enabled. COM не предоставляет атомарный CAS против одновременной замены задачи администратором: такой конфликт запрещает дальнейшую работу, но нулевые побочные эффекты уже начатого setter не гарантируются. Неизвестный ACK, истёкший срок, изменившийся pin, неполная родословная или дополнительный дочерний процесс запрещают продолжение/автоповтор. Durable lock намеренно не удаляется автоматически.

После выхода выбранных процессов helper остаётся жив до проверки после снимка. База открывается минимальным read-only соединением без миграций; SQLite backup включает committed WAL, затем проверяются integrity/FK, идентичность файла и SHA-256. Копирования одного main-файла, удаления WAL, восстановления базы, изменения старых ACK/batches или повторения Publishing-запросов нет. Результат доказывает только известный выбранный runtime и проверенные restart authorities; произвольные потомки через уже исчезнувшие промежуточные процессы и любые другие writers этим не исключаются. Команда оставляет старую Task выключенной и не публикует новые quarantine pins, не запускает successor и не подтверждает native readiness. Она не является готовым rolling restart и не включается через health. Снимок/журнал необходимо сохранять вне Git и папок пользовательской выдачи; это серверные данные.

Открытый вопрос Codex появляется в беседе задачи с кнопками вариантов и кнопкой «Свой ответ». Можно также использовать штатное «Ответить» в VK на карточке вопроса и написать текст. Если вопросов несколько, мост собирает ответы по порядку и передаёт их вместе. /questions повторно проверяет открытые вопросы и обновляет кнопки (их срок действия — 30 минут).

Поддерживаются обычные item/tool/requestUserInput и асинхронные вопросы request_user_input_async: для последних используется тот же служебный формат ответа через steer, что и в клиенте Codex. Асинхронный вопрос не означает остановку агента. После завершения соответствующего хода он больше не доступен для ответа.

Ответить через VK может только владелец VKodex, в том числе в общей беседе. Поля isSecret нельзя заполнять через VK; запросы разрешений на команды, файлы и MCP-формы эта функция не обрабатывает. Для них используйте Codex. Ответы на вопросы не запускают новый ход и не добавляются в /queue.

Клиент-владелец задачи должен передавать live-состояние: одного чтения истории с диска недостаточно. Перед отправкой мост проверяет актуальность вопроса и выбранный каталог. Ответ из приложения закрывает карточку в VK; при перезапуске моста открытые вопросы восстанавливаются без повторной отправки ответов. Если результат отправки неизвестен, повтор блокируется до проверки в Codex. Редактирование отправленного ответа из VK пока не поддерживается.

About

Open-source VK bot for remote control of OpenAI Codex. Бот для удалённого управления Codex через ВКонтакте.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages