Saltar al contenido principal
E

maxdshbot

enkolesnikov/maxdshbot

DSH → MAX messenger plugin: compact UX, briefings, status, reliable replies, remote control, GUI settings, reply threads, tables, schedules, webhook, cost & budget. Zero runtime deps.

Instalar

dsh plugin --profile web add github:enkolesnikov/maxdshbot

README

dsh-max-notify — DSH → MAX messenger bridge

dsh-max-notify

Последний ответ агента — в MAX. Пульт управления, approvals, стоимость и наблюдаемость — оттуда же.
Плагин для DeepSeek Harness · мессенджер MAX · ноль runtime-зависимостей

CI npm npm downloads Release License DSH MAX Tests Node Runtime dependencies Stars

Быстрый старт · Возможности · Команды · Архитектура · Конфигурация · Roadmap · Changelog


[!NOTE] Плагин ставится в web-профиль DSH через link: и переживает перезагрузки: состояние (маркер polling, outbox, дедуп-ключи, health) лежит вне репозитория, в $DSH_HOME/max-notify/. Доступ — только по allowlist, интерактив fail-closed. Всё, что агент пишет, уходит на серверы MAX — для чувствительных сессий используйте enabled: false или dryRun: true.

Что умеет

ВозможностьЧто даёт
💬Ответы агентаОдин MAX-месседж на ход (turn/end), чанкинг 4000 символов, картинки и файлы present вложениями, входящие файлы из MAX → max-inbox/
🕹ПультДвусторонний чат, 25+ команд (/status, /model, /plan, /sessions, /budget…), инлайн-кнопки, live-прогресс
🔐ApprovalsПодтверждения и вопросы из MAX с гонкой MAX↔GUI, таймаутом, «запомнить для инструмента», audit-логом
👀НаблюдательSubagent/job/goal/error, TODO-прогресс, режимы молчания, тихие часы, ежедневный дайджест
🛡НадёжностьDurable outbox, at-least-once polling с дедупом, глобальный лимитер, health/heartbeat, redaction секретов
💰СтоимостьRead-only интеграция с dsh-cost-meter: /budget, cost-строки в /status и дайджесте, алерты 80/100 %

Архитектура

flowchart LR
  subgraph DSH["DeepSeek Harness (web profile)"]
    EV["session/event<br/>turn/end · assistant/message"]
    W["approval / user-questions<br/>waterfalls"]
    CM["commands · planMode<br/>workspaceRegistry · sessionController"]
    LEDGER[("cost-meter<br/>ledger.json")]
  end

  subgraph PLUGIN["dsh-max-notify"]
    NOTIFY["notify + format"]
    BOT["bot · commands · cards"]
    INTER["interactions<br/>approve / questions"]
    OUTBOX["outbox · limiter"]
    HEALTH["health · audit · redact"]
    COST["cost adapter"]
  end

  MAX[("MAX Bot API<br/>platform-api2.max.ru")]

  EV --> NOTIFY --> OUTBOX --> MAX
  BOT <-->|long polling / replies| MAX
  W --> INTER --> BOT
  CM --> BOT
  LEDGER --> COST --> BOT
  OUTBOX --> HEALTH
  PLUGIN -->|"0 runtime deps · node builtins"| DSH

Плагин не форкает DSH и не патчит ядро: он использует штатные швы session/event, waterfall-события approvals/questions, sessionController, commands, planMode, workspaceRegistry и read-only ledger dsh-cost-meter.

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

Установка из npm (рекомендуется)

dsh plugin --profile web add dsh-max-notify

Из git-чекаута (для разработки)

git clone https://github.com/enkolesnikov/MaxDSHBot.git
cd MaxDSHBot

cp .env.example .env && chmod 600 .env   # MAX_BOT_TOKEN=..., MAX_CHAT_ID=...
node dsh-max-notify/tools/pair.mjs       # узнать chat_id: нажать Start в диалоге с ботом
node dsh-max-notify/tools/send-test.mjs "проверка"

./dsh-max-notify/install.sh              # профиль web (или: ./install.sh tui)

Оба способа добавляют пакет в dsh.profile.bundles, а его cordis.patch.yml вставляет строку max-notify. Пакет: npmjs.com/package/dsh-max-notify.

Приватная конфигурация (не коммитить)

botTokenFile / chatId / allowedUserIds — в собственном $DSH_HOME/profiles/<p>/cordis.patch.yml, как override строки с тем же id:

- id: max-notify
  config:
    botTokenFile: /path/to/MaxDSHBot/.env
    chatId: 123456789
    allowedUserIds: [987654321]

Конфиг в override заменяет объект целиком. В репозитории нет ни токенов, ни chat/user id.

Команды в MAX

КомандаДействие
/status, /currentСессия, модель, папка, стоимость, бюджет
/stopОстановить текущий ход
/sessions, /use NСписок сессий и переключение (включая холодные — с заголовками)
/new [папка]Новая сессия (папка создаётся)
/model [N|provider/model]Каталог моделей и переключение
/rename <название>, /fork, /compactПереименовать / ответвить / сжать историю
/plan, /plan off, /plan statusРежим плана; review плана приходит файлом plan.md с кнопками
/search <текст>Поиск по содержимому сессий
/archive, /pin, /unpinАрхивировать текущую / закрепить / открепить
/workspace [N|add <path>]Рабочие папки; папка для следующих /new
/approveПолитика подтверждений ask/never (двухшаговое подтверждение)
/mode, /mute, /unmute, /digestРежимы уведомлений, тишина, дайджест
/budget, /costСтоимость и бюджет из dsh-cost-meter
/health, /version, /ping, /helpДиагностика и справка

Текст без / уходит агенту как следующее сообщение. Под финальным ответом — кнопки «Продолжить», «Стоп», «Открыть GUI» и настраиваемые пресеты.

Webhook (production-транспорт)

По умолчанию работает long polling. Для production можно включить webhook — MAX будет сам присылать обновления на публичный HTTPS-эндпоинт:

- id: max-notify
  config:
    transport: webhook
    webhookPath: /max/webhook
    webhookPublicUrl: https://example.com/max/webhook
    webhookSecret: ${MAX_NOTIFY_WEBHOOK_SECRET}   # 5–256 символов [A-Za-z0-9_-]
    webhookAutoSubscribe: true
  1. webServer.register добавляет точный маршрут в уже работающий DSH HTTP-сервер (nginx с Let's Encrypt терминирует 443 и проксирует на DSH).
  2. MAX проверяет TLS-цепочку, домен и secret-заголовок; каждое обновление сначала сохраняется в durable-очередь state.json, потом отвечаем 200.
  3. Обработка идемпотентная (общий dedupe с polling), при сбое — 503, MAX повторит; после 8 часов неудач отписка автоматическая.
  4. Подписка управляется автоматически (GET/POST /subscriptions), вручную: node tools/webhook.mjs status|subscribe|unsubscribe --env ../.env.

Если webServer/secret/public URL не сконфигурированы, плагин откатывается на long polling и пишет warning в лог. Официальная документация MAX: webhooks.

Брифинг и статус (v1.5)

  • /brief — компактный брифинг: что работает, что ждёт решения, деньги, ближайшие расписания. В меню теперь 13 команд.
  • /status стал короче: title ≤30 символов, папка basename, деньги с двумя знаками; если сессия дороже «сегодня», пишется «сессия всего».
  • Исправлены русские склонения в брифинге/дайджесте.

UX-аудит (v1.4)

  • 12 команд в меню вместо 31 (в 1.5 — 13 с /brief); /help ≤450 символов, полный список — /help all.
  • Компактный заголовок 🕒 20:03 · Название; старый подробный режим — messageStyle: detailed.
  • Тише по умолчанию: subagent/job/goal/TODO-уведомления выключены; остаются финальные ответы, ошибки, approvals/questions и бюджетные алерты.
  • Approval-карточка без callId; результат одной строкой; GUI-ответы не создают отдельную карточку; job/subagent/goal — одна строка; digest — «брифинг».
  • Продвинутые команды (/diff, /send, /approve, /workspace, /say, …) скрыты из меню, но работают; аудит и причины — в docs/ux.md.

Автономные расписания (v1.3)

  • /schedules mode N inherit|read-only|auto — политика для конкретной задачи. read-only разрешает только чтение и отклоняет запись/команды; auto разрешает всё (только после подтверждения), inherit — обычные approvals.
  • Решения принимаются автоматически во время запуска по расписанию, без карточки в MAX; пишутся в audit (kind: autonomy).
  • auto/read-only переживают reload, отображаются в /schedules; сопоставление — по target/involved session, для new — по заголовку и свежей delivery-записи.

Голос и инструменты (v1.2)

  • /say <текст> — озвучить текст; авто-TTS коротких финальных ответов (voiceTts, voiceTtsMode: off|short|always) через OpenAI-совместимый /audio/speech; аудио уходит отдельным сообщением, ошибки TTS не мешают тексту.
  • /diff [--staged] [путь] — git diff папки сессии файлом diff.patch.
  • /send <путь> — отправить файл из папки сессии; выход за cwd запрещён, лимит 25 МиБ, тип вложения по расширению.
  • Настройки применяются без рестарта: mode/дайджест/тихие часы/reply-ветки/ таблицы/TTS/approvals и др. — через GUI; transport/секреты — после перезагрузки.

GUI-настройки, голос, нативные изображения (v1.1)

  • Страница настроек в GUI: DSH → Plugins → dsh-max-notify — форма для режима, дайджеста, тихих часов, reply-веток, таблиц, файлов, голоса, таймаутов. Правки сохраняются в $DSH_HOME/max-notify/config.json (0600) и применяются после перезагрузки строки; секреты (токены/ключи) страница не показывает.
  • Нативные входящие изображения: картинки из MAX передаются агенту image-партами, с текстовым fallback, если модель/route не принимает images.
  • Голосовая расшифровка (STT): опциональный OpenAI-совместимый endpoint; аудио из MAX расшифровывается и уходит агенту текстом.
  • TTS, multi-chat и внешний каталог — в 1.2.

Reply-ветки, таблицы, расписания (v1.0)

  • Reply-ветки: первый ответ сессии становится якорем, следующие приходят реплаями к нему; ответ пользователя на любой ответ уходит в исходную сессию. Якоря/mid→session переживают reload.
  • Таблицы → файлы: markdown-таблицы дополнительно уходят как table-N.csv и table-N.md, текст ответа заменяется плейсхолдером (MAX не рендерит таблицы).
  • /schedules: список задач, pause/resume N, cancel N с подтверждением.
  • Forwarded-сообщения из MAX разворачиваются и передаются агенту.
  • /say, /diff, /send — озвучка, git-diff и отправка файлов.
  • /schedules mode N ... — автономный режим задачи (read-only/auto).
  • /settings: снимок эффективных настроек (transport, режим, allowlist, таймауты, фичи) без секретов.
  • Полный GUI-редактор настроек, голос и нативные входящие изображения — в 1.1.

Надёжность и безопасность

  • Durable outbox — финальные ответы и уведомления переживают недоступность MAX и reload; retry с backoff, TTL, приоритеты, дедуп по session:turn:seq.
  • At-least-once polling — marker сдвигается после обработки; обработанные update-id сохраняются, повторная доставка не дублирует промпты.
  • Лимитер — 2 запроса/с на чат, 30/с суммарно; approvals/ошибки идут critical-каналом.
  • Fail-closed — без allowedUserIds/allowedChatIds команды, approvals и polling выключены; уведомления работают. allowUnlistedUsers: true — осознанный escape.
  • Approvals — таймаут 120 с, «запомнить» только для явного approvalRememberTools, audit $DSH_HOME/max-notify/audit.jsonl (0600).
  • Health/redaction — /health, heartbeat-файл, redaction токенов в логах, rate-limit входящих.

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

Все ключи (cordis.patch.yml / override профиля)
КлючПо умолчаниюСмысл
botToken / botTokenFileenv MAX_BOT_TOKENтокен бота или файл с MAX_BOT_TOKEN=...
chatId / userIdenv MAX_CHAT_IDполучатель (чат/диалог или user_id)
formatmarkdownmarkdown / html / текст
notifytruepush-уведомления
disableLinkPreviewtrueотправляется query-параметром (требование MAX)
includeHeader / includeTitle / includeSessionIdtrue / true / falseзаголовок сообщения и сессии
messageStylecompactcompact (🕒 20:03 · title) или detailed (старый DSH-заголовок)
includeSubagentsfalseпересылать и дочерние агент-сессии
allowedUserIds / allowedChatIdsenv MAX_ALLOWED_USER_IDS / ..._CHAT_IDSallowlist получателя, fail-closed
skipReasons[interrupted, forked]окончания хода, которые не пересылаются
maxChars3800предохранитель (жёсткий лимит API — 4000)
enabled / dryRuntrue / falseвыключатель / только лог
requestTimeoutMs / maxRetries / minIntervalMs15000 / 3 / 600транспорт
notifyOnStartfalseодноразовое «плагин подключён» в MAX
polling / pollTimeoutSectrue / 25long polling GET /updates (один поллер на токен)
interactivetrueприём сообщений/кнопок и команды
approvalChannel / questionChannelbothboth (MAX + GUI гонка), max, gui
buttons / buttonsPresets / webUrltrue / [] / env DSH_WEB_URLкнопки, пресеты, ссылка на GUI
progress / progressDelayMs / progressThrottleMs / typingtrue / 2500 / 2000 / truelive-карточка прогресса
deliverablestrueотправлять файлы из present вложениями
forwardImages / forwardToolImages / maxImagestrue / true / 4картинки из ответа и tool-результатов
receiveFiles / inboxDirtrue / <cwd>/max-inboxприём файлов из MAX
maxIncomingFiles / maxIncomingBytes4 / 25 MiBлимиты входящих
registerCommands / greetOnStarttrue / trueменю команд MAX и приветствие по Start
newSessionDir—папка для /new (по умолчанию — папка активной сессии)
notifySubagents / notifyJobs / notifyGoalsfalseуведомления о событиях (тихие по умолчанию)
notifyErrors / todoProgresstrue / falseошибки, TODO-прогресс
todoProgresstrueTODO-прогресс в MAX
quietHours—{start: '23:00', end: '08:00'} — без push ночью
digestEnabled / digestTimefalse / 21:00ежедневный дайджест
modeallстартовый режим: all, errors, mute
stateFile$DSH_HOME/max-notify/state.jsonmarker, сессии, health, dedupe-ключи
outboxEnabled / outboxMaxItems / outboxTtlHourstrue / 200 / 48durable-очередь
ratePerChatPerSecond / rateGlobalPerSecond2 / 30глобальный лимитер
approvalTimeoutMs120000таймаут approvals, 0 — ждать бесконечно
approvalRememberTools / approvalRememberMs[] / 3600000«запомнить» только для явных инструментов
allowUnlistedUsersfalseинтерактив без allowlist (небезопасно)
incomingPerMinute / incomingBurst30 / 10защита от флуда
auditLog / auditFiletrue / $DSH_HOME/max-notify/audit.jsonlаудит решений
heartbeatFile—JSON здоровья для мониторинга
costMeterEnabled / costMeterFiletrue / $DSH_HOME/storages/cost-meter/ledger.jsonread-only адаптер стоимости
budgetAlertEnabled / budgetAlertThresholdstrue / [80, 100]алерты бюджета (раз за период)
transportpollingpolling или webhook
webhookPath / webhookPublicUrl/max/webhook / —маршрут и публичный HTTPS URL
webhookSecretenv MAX_NOTIFY_WEBHOOK_SECRETsecret-заголовок MAX (обязателен для webhook)
webhookUpdateTypesmessage_created,…список типов обновлений для подписки
webhookAutoSubscribe / webhookRemoveOnStoptrue / falseавто-подписка/отписка MAX
webhookQueueMax200durable-очередь входящих webhook-обновлений
threadstruereply-ветки сессий (якорь + маршрутизация ответов)
tableFiles / tableMaxFilestrue / 4markdown-таблицы → CSV/MD файлами
nativeIncomingImagestrueвходящие картинки — нативными image-партами
voiceTranscribe / voiceEndpoint / voiceApiKeyfalse / — / env MAX_NOTIFY_VOICE_API_KEYSTT для голосовых MAX
voiceApiKeyFile / voiceModel / voiceLanguage— / whisper-1 / —ключ из файла, модель и язык STT
settingsPage / settingsFiletrue / $DSH_HOME/max-notify/config.jsonGUI-настройки (overlay, 0600)
voiceTts / voiceTtsModefalse / shortавто-TTS (off/short/always)
voiceTtsEndpoint / voiceTtsApiKeyenv MAX_NOTIFY_TTS_*OpenAI-совместимый TTS
voiceTtsVoice / voiceTtsModel / voiceTtsMaxCharsalloy / gpt-4o-mini-tts / 600голос, модель, лимит
fileSendAllowOutsidefalseразрешить /send вне cwd сессии
autonomyEnabledtrueавто-политики для расписаний

Структура

Файлы плагина
ПутьЧто это
dsh-max-notify/index.jscordis-плагин: конфиг, проводка, сессии, дедуп финала
lib/transport.mjsMAX Bot API на node:https + встроенный Russian Trusted CA
lib/bot.mjslong polling, команды, маршрутизация, flood protection
lib/interactions.mjsapprovals/questions, план-review, гонка MAX↔GUI
lib/progress.mjslive-карточка и typing
lib/deliverables.mjs, lib/incoming.mjsфайлы в обе стороны
lib/outbox.mjs, lib/limits.mjsdurable-очередь и лимитер
lib/state.mjs, lib/health.mjs, lib/audit.mjs, lib/redact.mjsсостояние, health, аудит, секреты
lib/cost-meter.mjsread-only ledger dsh-cost-meter
lib/webhook.mjswebhook-обработчик, secret, подписка MAX
lib/tables.mjsmarkdown-таблицы → CSV/MD
lib/schedules.mjs/schedules: список, пауза, удаление
lib/media.mjsвходящие изображения → native image parts
lib/voice.mjsопциональная STT-расшифровка аудио
lib/settings.mjsGUI-настройки: валидация, overlay, JSON API
lib/tts.mjsTTS-синтез, очистка текста, endpoint/key
lib/workspace-tools.mjsgit diff и безопасная отправка файлов
lib/autonomy.mjsполитики автономных расписаний и матчинг
client/client.jsклиентская страница настроек (без сборки)
lib/observer.mjs, lib/policy.mjsсобытия, дайджест, режимы, алерты бюджета
certs/ca-chain.pemRussian Trusted Sub CA + Root CA
test/187 тестов (node --test)
tools/pair.mjs, send-test.mjs, smoke.mjs, webhook.mjs

Ограничения

Что важно знать
  • Пересылается только финальный текст хода, не стрим и не tool-шаги.
  • MAX markdown не поддерживает списки/таблицы: - пункт отрисуется текстом.
  • Fail-closed: без allowlist интерактив выключен (уведомления идут). allowUnlistedUsers: true открывает бота всем, кто знает чат.
  • Long polling — один поллер на токен; tools/pair.mjs конкурирует с плагином за события. Webhook — в roadmap 0.9 (MAX требует публичный HTTPS :443; nginx с Let's Encrypt готов).
  • Approvals по умолчанию истекают через 120 с; approvalTimeoutMs: 0 — ждать бесконечно.
  • Outbox гарантирует at-least-once: редкий повтор возможен при сбое между отправкой и записью ключа; типовые reload/батч закрыты дедупом.
  • Один chatId на строку max-notify; для нескольких получателей — отдельные профили/патчи.
  • Бюджет и алерты работают только когда Budget включён в настройках dsh-cost-meter.

Проверка

cd dsh-max-notify && npm test          # 353 unit tests
npm run check                          # синтаксис всех модулей
node tools/smoke.mjs --env ../.env     # read-only: GET /me, state, outbox
node tools/send-test.mjs "проверка"    # реальная отправка

TLS-цепочка проверена openssl verify (leaf → Russian Trusted Sub CA → Root CA); живая отправка — HTTP 200 с mid, markdown-разбор подтверждён GET /messages.

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

Лицензия

MIT — см. LICENSE.

Plugins relacionados