opencode-config/docs/decisions/073-pr-174-telegram-send-tool.md
Sergey 1bc8b8ed05
feat(telegram): add telegram-send plugin-tool for Bot API messaging (#174)
* feat(telegram): add CLI project with Bot API client

* feat(telegram): add telegram-send plugin-tool

* test(telegram): add unit tests for markdown, config, api

* chore(env): add TELEGRAM_CHAT_ID to .env.example

* docs(handoff): add handoff and ADR for telegram-send

* docs(handoff): set PR number 174

* docs: update project map for telegram-send tool

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-31 20:42:33 +03:00

37 lines
No EOL
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-073: telegram-send plugin-tool — Bot API messaging via CLI
## Статус
Accepted (PR #174)
## Контекст
Оркестратору нужен быстрый способ показывать пользователю результаты работы — сгенерированный `draw-image` PNG, .md-файл с архитектурой, текстовый вывод. Существующий способ показать файл — tunnel skill (запуск процесса + проброс порта через Cloudflare), что тяжело для разовой отправки и требует живого процесса.
В репо уже есть паттерн plugin-tool + CLI-проекта на примере `draw-image`: тонкая обёртка `.opencode/tools/draw-image.ts` дёргает CLI из `.opencode/draw-image/cli.ts` через `spawnSync("node", ["--experimental-strip-types", cliPath, ...args])`. Plugin-tools авто-дискаверятся opencode из папки `.opencode/tools/` — без записи в `opencode.json`, без MCP-сервера.
## Решение
Создан `telegram-send` plugin-tool + CLI-проект `.opencode/telegram/` по паттерну `draw-image`:
1. **Plugin-tool, не MCP-сервер**`.opencode/tools/telegram-send.ts` авто-дискаверится opencode; `spawnSync` запускает CLI как дочерний процесс; результат парсится из stdout; ошибка → `⚠️ telegram-send failed (exit N): <stderr>`. Не требует записи в `opencode.json`, не требует long-running процесса.
2. **Без runtime-зависимостей**`package.json` имеет только devDeps (`@types/node`, `typescript`, `vitest`). Рантайм использует встроенный `fetch`/`FormData`/`Blob`/`File` Node 22+. Это упрощает установку (только `npm install` для devDeps) и аудит.
3. **Один tool с параметром `action`**`action: "text" | "document" | "photo"` вместо трёх отдельных tools. Причины: единый контрак (`{ ok, message_id, chat_id }`), один набор env-настроек, меньше шума в списке tools оркестратора. Параметры `path`/`caption`/`text` условно-обязательные (зависят от `action`).
4. **CLI как тонкий слой над api.ts**`cli.ts` парсит argv, применяет `parse_mode` по умолчанию (`"MarkdownV2"`), диспетчеризует в `sendMessage`/`sendDocument`/`sendPhoto`. `api.ts` — низкоуровневый, не применяет дефолты (добавляет `parse_mode` в body только при явной передаче). Разделение: api.ts тестируется изолированно, cli.ts тестирует дефолты.
5. **`lib: ["ES2022", "DOM"]` в tsconfig** — DOM-типы нужны только для `fetch`/`BodyInit`/`Blob`/`FormData`/`File` (все используются в `src/api.ts`). Рантайм-значения берутся из Node 22+ глобалов, не из браузера. `allowImportingTsExtensions: true` — сознательный паттерн (как `draw-image`) для `node --experimental-strip-types`.
## Альтернативы
1. **MCP-сервер для Telegram** — отвергнуто: требует long-running процесса, записи в `opencode.json`, сложнее отладка. Plugin-tool проще и следует существующему паттерну `draw-image`.
2. **Прямой `fetch` из plugin-tool (без CLI)** — отвергнуто: plugin-tool выполняется в Bun plugin-host (`import.meta.dir` доступен), но `fetch` там может вести себя иначе; CLI-процесс на Node 22+ даёт предсказуемый рантайм с встроенным `fetch`. Плюс CLI тестируется изолированно (`npm test`).
3. **Внешние зависимости (`node-telegram-bot-api`, `telegraf`)** — отвергнуто: добавляют audit-поверхность, усложняют установку, избыточны для 3 endpoint'ов (`sendMessage`, `sendDocument`, `sendPhoto`). Встроенный `fetch` + `FormData` достаточны.
4. **Три отдельных tools (`telegram-send-text`, `telegram-send-document`, `telegram-send-photo`)** — отвергнуто: засоряет список tools, дублирует env-логику и контрак. Один tool с `action`-enum чище.
5. **Markdown → MarkdownV2 авто-конвертер** — отвергнуто (out-of-scope): пользователь сам экранирует через `escapeMarkdownV2` (экспортируется из `src/markdown.ts`) или использует `parse_mode: "plain"`/`"HTML"`. Конвертер — отдельная нетривиальная задача.