@retensy/mcp 0.36.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ MCP-сервер (+ скилл для Claude Code) для **сборки и пу
|
|
|
57
57
|
- 📰 **Публикации и VK**: `publications_usage` — месячная квота (общая для Telegram/MAX/Instagram/VK), `vk_status`/`vk_connect`/`vk_disconnect`/`vk_post` — подключение VK-сообщества токеном и публикация на стену.
|
|
58
58
|
- 🔗 **Ссылка вместо отказа**: что нельзя сделать через API (вход через Google/Instagram, оплата тарифа, вход в аккаунт) — инструмент возвращает прямую ссылку и одну строку, что сделать.
|
|
59
59
|
- 📝 **Статьи блога** (тот же токен `zmcp_…`): `article_publish`, `article_update`, `article_list`, `article_get` — публикация статей в Markdown (как README на GitHub) в раздел **/articles**.
|
|
60
|
-
- 🧠 **ИИ-агенты и база знаний**: `agent_list`/`agent_get`/`agent_create`/`agent_update`/`agent_publish`/`agent_health`/`agent_test_chat`/`agent_unanswered`, `agent_tool_calls`, `kb_docs`/`kb_add_qa`/`kb_add_text`/`kb_add_site`/`kb_reindex` — настройка ИИ-агента и его базы знаний (раздел «ИИ-агенты»).
|
|
60
|
+
- 🧠 **ИИ-агенты и база знаний**: `agent_list`/`agent_get`/`agent_create`/`agent_update`/`agent_publish`/`agent_health`/`agent_test_chat`/`agent_unanswered`/`agent_tests_run`/`agent_tests_list`, `agent_tool_calls`, `kb_docs`/`kb_add_qa`/`kb_add_text`/`kb_add_site`/`kb_reindex` — настройка ИИ-агента и его базы знаний (раздел «ИИ-агенты»).
|
|
61
61
|
- 📎 **Медиа**: `upload_file` грузит фото/видео/документы в библиотеку **/bots/files** (до 50 МБ) и возвращает публичный URL — его вставляешь в медиа-карточку сценария.
|
|
62
62
|
- 🌐 **Сайты из блоков** (раздел «Страницы»): создание, правка операциями (блоки, Zero-блок со свободной вёрсткой, код блока, папки страниц, дизайны, шаблоны из библиотеки), публикация и откат, свои домены, заявки из форм и куда их доставлять — инструменты `site_*` + скилл `build-site`.
|
|
63
63
|
- 🧠 **Скилл `build-bot-funnel`**: учит агента собирать корректный граф (типы узлов, ветки, кнопки, задержки) и проверять его перед публикацией. Поддерживает Telegram, MAX и Instagram.
|
|
@@ -135,7 +135,7 @@ MCP-сервер (+ скилл для Claude Code) для **сборки и пу
|
|
|
135
135
|
| Право | Что разрешает | Примеры инструментов |
|
|
136
136
|
|---|---|---|
|
|
137
137
|
| `read` | любое чтение: списки, карточки, аналитика, превью, поиск, `dry_run`. **Включает персональные данные**: подписчики, переписка в диалогах, заявки с сайтов и их файлы | `list_bots`, `get_graph`, `site_leads`, `dialog_messages`, `broadcast_preview` |
|
|
138
|
-
| `write:bots` | создание и изменение ботов, сценариев, цепочек, интеграций, ИИ-агентов, базы знаний, черновиков рассылок. Правка опубликованного сценария сразу меняет ответы бота подписчикам; можно сменить ключи и вебхуки интеграций; `agent_test_chat`
|
|
138
|
+
| `write:bots` | создание и изменение ботов, сценариев, цепочек, интеграций, ИИ-агентов, базы знаний, черновиков рассылок. Правка опубликованного сценария сразу меняет ответы бота подписчикам; можно сменить ключи и вебхуки интеграций; `agent_test_chat` и `agent_tests_run` тратят ИИ-бюджет, `integration_test` ходит во внешний сервис | `create_graph`, `publish_graph`, `chain_update`, `connect_integration`, `agent_test_chat` |
|
|
139
139
|
| `write:sites` | сайты, лиды, VK-лендинги, статьи | `site_create`, `site_edit`, `site_publish`, `vk_landing_update`, `article_publish` |
|
|
140
140
|
| `crm` | теги/переменные подписчиков, импорт, передача диалога оператору, записи. `booking_confirm`/`booking_reject` отправляют клиенту сообщение | `audience_tag_edit`, `bot_users_import`, `dialog_handoff`, `booking_create` |
|
|
141
141
|
| `broadcast` | всё, что доходит до живых людей без участия человека: рассылки, ответы, посты, а также **включённая цепочка без согласования постов** (approvalMode `NONE`/`AI_ONLY`) и **публикация/правка/активация сценария с `TRIGGER_SCHEDULE`** | `broadcast_send`, `dialog_reply`, `channel_post`, `vk_post`, `chain_approve`, `chain_enable` (без согласования) |
|
|
@@ -209,7 +209,7 @@ MCP-сервер (+ скилл для Claude Code) для **сборки и пу
|
|
|
209
209
|
| `graph_versions_list(graphId, [version], [compareTo])` | история версий сценария (снимки при публикации, правках живого графа, ручные); с `version:N` — сравнение с текущим графом или другой версией (`compareTo`). Право `read` |
|
|
210
210
|
| `graph_version_rollback(graphId, version)` | откат сценария на версию = публикация снимка (проверки как у `edit_graph_live`, текущее состояние сохраняется отдельной версией). Право `write:bots` |
|
|
211
211
|
| `import_funnel(botId, name, graphFile\|graph)` | всё за раз: create → update → dry-run → publish |
|
|
212
|
-
| `list_templates()` | готовые шаблоны воронок |
|
|
212
|
+
| `list_templates([niche], [channel], [query])` | готовые шаблоны воронок (~30, ниша и каналы в карточке; фильтры по нише, каналу, тексту); те же открыты публично на `/templates` |
|
|
213
213
|
| `create_graph_from_template(botId, templateId, name)` | граф из шаблона (DRAFT) |
|
|
214
214
|
| `clone_graph(graphId)` | копия графа в новый DRAFT |
|
|
215
215
|
| `rename_graph(graphId, name)` | переименовать сценарий |
|
|
@@ -257,6 +257,8 @@ MCP-сервер (+ скилл для Claude Code) для **сборки и пу
|
|
|
257
257
|
| `agent_health(agentId)` | счётчики документов/фрагментов базы знаний |
|
|
258
258
|
| `agent_test_chat(agentId, question, history?)` | проверить ответ в песочнице (**тратит бюджет ИИ** — не вызывай массово) |
|
|
259
259
|
| `agent_unanswered(agentId, days?)` | вопросы без ответа за период (7\|30\|90, по умолчанию 30) |
|
|
260
|
+
| `agent_tests_run(agentId, confirm, caseIds?, generate?, wait?, timeoutSec?)` | проверка агента ИИ-клиентами по тест-кейсам: диалог в песочнице, ИИ-судья (PASS/FAIL, причина, цитата), сравнение с прошлым прогоном. **Тратит бюджет ИИ** — нужен `confirm:true` |
|
|
261
|
+
| `agent_tests_list(agentId, runId?)` | тест-кейсы, история прогонов и полный прогон (последний или по `runId`) с регрессиями; ничего не тратит |
|
|
260
262
|
| `kb_docs(kbId)` | документы базы знаний агента (источник, статус, фрагменты) |
|
|
261
263
|
| `kb_add_qa(kbId, pairs)` | добавить пары вопрос-ответ (`pairs: [{question, answer}]`, до 200 за раз) |
|
|
262
264
|
| `kb_add_text(kbId, title, text)` | добавить источник «Текст/инструкция» |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retensy/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "MCP server to build and publish Telegram and MAX bot funnels/automations, broadcasts, service integrations, block-based websites (incl. free-layout Zero blocks, designs, templates, custom domains, form leads) and Markdown blog articles in the Retensy Bots service. Zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"scripts": {
|
|
22
22
|
"start": "node src/index.mjs",
|
|
23
23
|
"check": "node --check src/index.mjs",
|
|
24
|
-
"test": "node scripts/smoke.mjs && node scripts/telemetry.test.mjs && node scripts/live-edit-422.test.mjs && node scripts/broadcast-connect.test.mjs && node scripts/integration-core.test.mjs && node scripts/site-init.test.mjs && node scripts/ai-agents.test.mjs && node scripts/agent-write-tools.test.mjs && node scripts/battery-tools.test.mjs && node scripts/parity-tools.test.mjs && node scripts/parity-2.test.mjs && node scripts/validate-graph.test.mjs && node scripts/call-scenario.test.mjs && node scripts/audience-publications.test.mjs && node scripts/chains-analytics.test.mjs && node scripts/platform-decisions.test.mjs && node scripts/token-scopes.test.mjs && node scripts/secondary-graphs.test.mjs && node scripts/graph-versions.test.mjs",
|
|
24
|
+
"test": "node scripts/smoke.mjs && node scripts/telemetry.test.mjs && node scripts/live-edit-422.test.mjs && node scripts/broadcast-connect.test.mjs && node scripts/integration-core.test.mjs && node scripts/site-init.test.mjs && node scripts/ai-agents.test.mjs && node scripts/agent-write-tools.test.mjs && node scripts/battery-tools.test.mjs && node scripts/parity-tools.test.mjs && node scripts/parity-2.test.mjs && node scripts/validate-graph.test.mjs && node scripts/call-scenario.test.mjs && node scripts/audience-publications.test.mjs && node scripts/chains-analytics.test.mjs && node scripts/platform-decisions.test.mjs && node scripts/token-scopes.test.mjs && node scripts/secondary-graphs.test.mjs && node scripts/graph-versions.test.mjs && node scripts/templates-filter.test.mjs && node scripts/agent-tests.test.mjs",
|
|
25
25
|
"validate": "node skills/build-bot-funnel/validate.mjs"
|
|
26
26
|
},
|
|
27
27
|
"engines": {
|
|
@@ -35,7 +35,7 @@ description: Собрать воронку (сценарий) бота для с
|
|
|
35
35
|
- Пакет `ACTIONS` — до 30 действий (метки, профиль, HTTP, уведомления, интеграции GetCourse/amoCRM/Битрикс24/Google Sheets/Я.Метрика, приём оплат, модерация группы). Список — в schema.md. **Интеграции РАБОТАЮТ** (это не заглушки), но каждой нужен `connectionId` — возьми его через **`list_integrations`**; без него действие упадёт «не выбрано подключение». Для Google Таблиц вместо `connectionId` нужен `googleEmail` (аккаунт подключается в вебе).
|
|
36
36
|
- `AI_REPLY` («AI-агент») — два режима, поле `mode` (`"simple"`/не задан, либо `"agent"`). Платный узел в обоих режимах (`PREMIUM_NODE_FORBIDDEN` на бесплатном тарифе) и недоступен в Instagram-графах (нет в IG-allowlist). Тратит месячный AI-бюджет тарифа — он в токенах, не в рублях.
|
|
37
37
|
- **`mode` не задан или `"simple"`** — ответ модели по `systemPrompt`/`userPromptTemplate` (обязателен, иначе выход `error`). Исчерпание бюджета — не ошибка: узел шлёт `quotaFallbackText` (если задан) и идёт дальше по `next`, как обычно.
|
|
38
|
-
- **`mode: "agent"`** — поиск по подключённой базе знаний (`knowledgeBaseId`), ветки-действия (`actions[]`, каждому — своё ребро `action_<id>`), извлечение переменных из разговора (`extract[]`, значения — слова клиента, не проверенный факт) и готовая сводка на действии в `{{var.ai_summary}}` без отдельной настройки. Без найденных в базе фрагментов (нет базы, либо релевантность ниже порога) агент в ЛЮБОМ режиме (строгом и нет) уходит в `unknown` — модель даже не вызывается; исключение — узел с непустым `actions[]`: он и без фрагментов зовёт модель, чтобы та могла выбрать действие («запишите меня на завтра» слов из базы не содержит), а её ответ без фрагментов в любом режиме (и в нестрогом тоже) уходит в `unknown`; нестрогий режим лишь разрешает модели дополнять УЖЕ найденные фрагменты общими знаниями (кроме цен/сроков/обещаний), а не отвечать вовсе без базы. **У узла нет выхода `next`** — только `answered`/`action_<id>`/`unknown`/`budget_exhausted`/`error` (`error` — сбой модели/поиска, ИИ не настроен, headless-вебхук или исчерпанный бюджет без ветки `budget_exhausted`). Исчерпание бюджета — своя ветка `budget_exhausted` (если подключена) либо `error`, `quotaFallbackText` отправляется в обоих случаях. Если собираешь агента этим скиллом — обязательно веди себя по этому списку выходов, старый одиночный `AI_REPLY` без `mode` для агента не годится. `systemPrompt`: мягкая норма 10 000 символов (у бэкенда для неё нет отдельного предупреждения, только `validate.mjs` этого скилла warn'ит явно), жёсткий потолок 30 000 (`AGENT_PROMPT_TOO_LONG`, блокирует публикацию) — платформа сама добавляет защиту от инъекций/вытягивания инструкции, запрет обещать несделанное и формат под мессенджер, дублировать это в `systemPrompt` не нужно. Подробности всех полей и кодов ошибок (`AGENT_*`) — в schema.md/validation.md.
|
|
38
|
+
- **`mode: "agent"`** — поиск по подключённой базе знаний (`knowledgeBaseId`), ветки-действия (`actions[]`, каждому — своё ребро `action_<id>`), извлечение переменных из разговора (`extract[]`, значения — слова клиента, не проверенный факт) и готовая сводка на действии в `{{var.ai_summary}}` без отдельной настройки. Без найденных в базе фрагментов (нет базы, либо релевантность ниже порога) агент в ЛЮБОМ режиме (строгом и нет) уходит в `unknown` — модель даже не вызывается; исключение — узел с непустым `actions[]`: он и без фрагментов зовёт модель, чтобы та могла выбрать действие («запишите меня на завтра» слов из базы не содержит), а её ответ без фрагментов в любом режиме (и в нестрогом тоже) уходит в `unknown`; нестрогий режим лишь разрешает модели дополнять УЖЕ найденные фрагменты общими знаниями (кроме цен/сроков/обещаний), а не отвечать вовсе без базы. **У узла нет выхода `next`** — только `answered`/`action_<id>`/`unknown`/`budget_exhausted`/`error` (`error` — сбой модели/поиска, ИИ не настроен, headless-вебхук или исчерпанный бюджет без ветки `budget_exhausted`). Исчерпание бюджета — своя ветка `budget_exhausted` (если подключена) либо `error`, `quotaFallbackText` отправляется в обоих случаях. Перед публикацией агента можно прогнать проверку ИИ-клиентами: `agent_tests_list` (кейсы и история) → `agent_tests_run` с `confirm:true` (тратит бюджет ИИ; PASS/FAIL с причиной и цитатой, регрессии к прошлому прогону). Если собираешь агента этим скиллом — обязательно веди себя по этому списку выходов, старый одиночный `AI_REPLY` без `mode` для агента не годится. `systemPrompt`: мягкая норма 10 000 символов (у бэкенда для неё нет отдельного предупреждения, только `validate.mjs` этого скилла warn'ит явно), жёсткий потолок 30 000 (`AGENT_PROMPT_TOO_LONG`, блокирует публикацию) — платформа сама добавляет защиту от инъекций/вытягивания инструкции, запрет обещать несделанное и формат под мессенджер, дублировать это в `systemPrompt` не нужно. Подробности всех полей и кодов ошибок (`AGENT_*`) — в schema.md/validation.md.
|
|
39
39
|
- **Приём оплат** — действие `issue_invoice` внутри `ACTIONS` (НЕ отдельный узел: `YOOKASSA_PAYMENT` устарел). Деньги идут на кассу владельца бота; `connectionId` — подключение `provider=YOOKASSA` из `list_integrations`. Два режима, выбирай по задаче:
|
|
40
40
|
- **дождаться оплаты прямо в диалоге** — протяни от блока ветку `paid` (появятся выходы `paid`/`timeout`); сценарий встанет на паузу до подтверждения кассой;
|
|
41
41
|
- **не ждать** — ветку `paid` не рисуй, блок просто пришлёт счёт и пойдёт по `next`; выдать доступ потом сможет отдельный сценарий с триггером `TRIGGER_PAYMENT`.
|
|
@@ -61,7 +61,7 @@ description: Собрать воронку (сценарий) бота для с
|
|
|
61
61
|
5. **Залей и опубликуй через MCP `bot-graph`** (если он подключён и пользователь просит публикацию):
|
|
62
62
|
- `list_bots` → выбрать `botId` (или `create_graph` в существующем боте).
|
|
63
63
|
Конфликт токена (тот же Telegram-токен подключён ещё в BotHelp/Salebot/своём скрипте): `active:false` + `pausedReason:"TOKEN_CONFLICT"` — вебхук другого сервиса, бот на паузе (отвечать не будет); `pausedChannels` — выключены отдельные каналы; `conflictWarning:"TOKEN_CONFLICT_POLLING"` — бот работает, но часть сообщений забирает другая программа. Во всех случаях попроси пользователя отключить бота в том сервисе (или `/revoke` в @BotFather → `bot_change_token`), при паузе — потом `bot_resume`. Справка: `/docs#token-conflict`.
|
|
64
|
-
- `create_graph(botId, name)` → получить `graphId`. Либо стартуй с готовой основы: `list_templates` → `create_graph_from_template(botId, templateId, name)`.
|
|
64
|
+
- `create_graph(botId, name)` → получить `graphId`. Либо стартуй с готовой основы: `list_templates` (фильтры `niche`, `channel`, `query`; около 30 шаблонов под русские ниши: салон, клиника, недвижимость, школа, магазин, ресторан, авто, юрист, отзывы и др.) → `create_graph_from_template(botId, templateId, name)`. Подходящий шаблон почти всегда быстрее и надёжнее сборки с нуля: правь только тексты и ссылки. Шаблоны не содержат платных узлов (`AI_REPLY`, `CALL_WEBHOOK`), поэтому работают и на бесплатном тарифе.
|
|
65
65
|
- `update_graph(graphId, nodes, edges, canvasMeta)` → залить узлы/рёбра.
|
|
66
66
|
- `dry_run(graphId, kind:"command", value:"start")` → прогнать стартовую ветку, проверить `runStatus`. `dry_run` ничего не делает снаружи: внешние запросы, CRM, таблицы, письма, уведомления, счета и ответы ИИ пропускаются (у шага `skipped: "dry-run"`), переменные из их ответов остаются пустыми — это проверяется только живым прогоном.
|
|
67
67
|
- `publish_graph(graphId)` → при отказе инструмент вернёт ошибку `HTTP 422` со ВСЕМИ причинами построчно (`code@nodeId: message`) — разобрать, починить узлы, обновить, опубликовать снова.
|
|
@@ -542,3 +542,7 @@ node validate.mjs graph.json --platform=INSTAGRAM
|
|
|
542
542
|
|
|
543
543
|
## Подстановки в тексте
|
|
544
544
|
`{{from.first_name}}`, `{{from.username}}`, `{{var.<имя>}}`, либо `{Имя}` как плейсхолдер. Имена переменных/меток: `[a-z_][a-z0-9_]{0,63}` (var) и `[a-z0-9_-]{1,64}` (tag).
|
|
545
|
+
|
|
546
|
+
## Готовые шаблоны (list_templates)
|
|
547
|
+
|
|
548
|
+
Шаблоны лежат в бэкенде как JSON `{id, name, description, icon, niche, channels, en:{name,description}, graph:{name,nodes,edges}}` и проходят тот же `GraphValidator`, что и ваши графы. Это обычный граф формата выше, без новых типов узлов: id узлов `tpl_*`, кнопки `CALLBACK` с пустым `value` и рёбрами `btn_N`, вопросы с рёбрами `valid`/`invalid`. Платных узлов (`AI_REPLY`, `CALL_WEBHOOK`) в нише-шаблонах нет, кроме универсального `ai-agent` (у него `hasAi:true`). Ниша: beauty, medical, realty, education, ecommerce, fitness, restaurant, auto, legal, reviews, universal. Каналы: TELEGRAM, MAX, VK.
|
package/src/index.mjs
CHANGED
|
@@ -1056,7 +1056,7 @@ const TOOLS = [
|
|
|
1056
1056
|
{ name: "graph_version_rollback", description: "Откатить сценарий на версию (POST /api/bots/graphs/{graphId}/versions/{version}/rollback). Откат = публикация снимка: у ЖИВОГО графа бот переходит на ту версию сразу, и она проходит те же проверки, что edit_graph_live (валидатор, платные блоки, лимит блоков, платформа) — при ошибках HTTP 422 со всеми code@nodeId, граф НЕ изменён. Состояние ДО отката сервер сам сохраняет отдельной версией (savedCurrentAs), результат — версией reason ROLLBACK (newVersion), так что откат обратим тем же инструментом. Узлы получают ТЕ ЖЕ id, что были в снимке. Это действие на живом боте: перед вызовом покажи пользователю graph_versions_list (version:N — что изменится) и получи согласие. Нужно право write:bots.", inputSchema: { type: "object", properties: { graphId: { type: "string" }, version: { type: "integer", description: "Номер версии из graph_versions_list" } }, required: ["graphId", "version"] } },
|
|
1057
1057
|
{ name: "unpublish_graph", description: "Снять ДОПОЛНИТЕЛЬНЫЙ сценарий с публикации (POST /api/bots/graphs/{graphId}/unpublish): он снова черновик, лендинги и ссылки на него ведут в основной сценарий, подписчики в нём возвращаются в основной, его задержки отменяются. Основной сценарий так не снимается — HTTP 409.", inputSchema: { type: "object", properties: { graphId: { type: "string" } }, required: ["graphId"] } },
|
|
1058
1058
|
{ name: "import_funnel", description: "Всё за раз: создать граф, залить узлы/рёбра, (опц.) dry-run /start, опубликовать. Граф можно передать инлайном (graph) или файлом (graphFile).", inputSchema: { type: "object", properties: { botId: { type: "string" }, name: { type: "string" }, graph: { type: "object" }, graphFile: { type: "string", description: "Путь к локальному JSON графа вместо инлайн graph; поддерживается ~" }, dryRun: { type: "boolean" }, publish: { type: "boolean" } }, required: ["botId"] } },
|
|
1059
|
-
{ name: "list_templates", description: "Список готовых шаблонов воронок (id, имя,
|
|
1059
|
+
{ name: "list_templates", description: "Список готовых шаблонов воронок (id, имя, описание, ниша, каналы, nameEn/descriptionEn, hasAi). Около 30 шаблонов под русские ниши (запись в салон и клинику, квалификация в недвижимости, лид-магнит школы, заказ в магазине, бронь в ресторане, сбор отзывов и др.) плюс универсальные. Можно сузить: niche (beauty, medical, realty, education, ecommerce, fitness, restaurant, auto, legal, reviews, universal), channel (TELEGRAM, MAX, VK), query (подстрока в названии и описании). Те же шаблоны открыты публично на /templates.", inputSchema: { type: "object", properties: { niche: { type: "string" }, channel: { type: "string" }, query: { type: "string" } } } },
|
|
1060
1060
|
{ name: "create_graph_from_template", description: "Создать граф (DRAFT) из шаблона (см. list_templates). Возвращает граф с id — дальше правь через update_graph.", inputSchema: { type: "object", properties: { botId: { type: "string" }, templateId: { type: "string" }, name: { type: "string" } }, required: ["botId", "templateId"] } },
|
|
1061
1061
|
{ name: "rename_graph", description: "Переименовать сценарий (работает и для опубликованных — имя не влияет на исполнение).", inputSchema: { type: "object", properties: { graphId: { type: "string" }, name: { type: "string" } }, required: ["graphId", "name"] } },
|
|
1062
1062
|
{ name: "clone_graph", description: "Склонировать граф в новый DRAFT «… (copy)» — безопасно итерировать поверх опубликованного. Клон сценария-вебхука получает собственный путь и секрет вебхука.", inputSchema: { type: "object", properties: { graphId: { type: "string" } }, required: ["graphId"] } },
|
|
@@ -1109,6 +1109,8 @@ const TOOLS = [
|
|
|
1109
1109
|
{ name: "kb_add_site", description: "Добавить сайт в базу знаний обходом страниц (POST /api/bots/kb/{kbId}/docs/site): url (http/https, не внутренняя сеть), schedule — расписание повторного обхода: NEVER|DAILY|WEEKLY|MONTHLY (по умолчанию NEVER). Обход уходит в фон; документ появится в kb_docs со статусом PENDING.", inputSchema: { type: "object", properties: { kbId: { type: "string" }, url: { type: "string" }, schedule: { type: "string", enum: ["NEVER", "DAILY", "WEEKLY", "MONTHLY"] } }, required: ["kbId", "url"] } },
|
|
1110
1110
|
{ name: "kb_reindex", description: "Переиндексировать документ-файл базы знаний из сохранённого оригинала (POST /api/bots/kb/{kbId}/docs/{docId}/reindex) — «Повторить» после ошибки. headerRow — необязательно, для табличных файлов: номер строки с шапкой (1..50), если автоопределение ошиблось. Только для источника FILE.", inputSchema: { type: "object", properties: { kbId: { type: "string" }, docId: { type: "string" }, headerRow: { type: "number" } }, required: ["kbId", "docId"] } },
|
|
1111
1111
|
{ name: "agent_unanswered", description: "Вопросы без ответа агента за период (GET /api/bots/agents/{agentId}/unanswered): days — 7|30|90 (по умолчанию 30). Группы вопросов, на которые агент не нашёл ответ в базе знаний — подсказка, что туда добавить. Read-only.", inputSchema: { type: "object", properties: { agentId: { type: "string" }, days: { type: "number", enum: [7, 30, 90] } }, required: ["agentId"] } },
|
|
1112
|
+
{ name: "agent_tests_run", description: "Проверка агента ИИ-клиентами (POST /api/bots/agents/{agentId}/ai-tests/runs): ИИ играет клиентов по сохранённым тест-кейсам (персона + цель + критерии), ведёт диалог с агентом в песочнице, ИИ-судья ставит PASS/FAIL с причиной и цитатой; результат сравнивается с прошлым прогоном (регрессии). ТРАТИТ бюджет ИИ (до 120 вызовов на прогон, до 10 кейсов, до 30 прогонов в сутки; пробные ответы не используются) — поэтому нужен confirm:true. caseIds — какие кейсы гнать (по умолчанию все, максимум 10). wait (по умолчанию true) — дождаться конца прогона (до timeoutSec, по умолчанию 240) и вернуть итог; wait:false вернёт id прогона сразу — дальше agent_tests_list с runId. Кейсы создаёт владелец во вкладке «Проверка» или generate:N (1–10): сначала создаст N кейсов с ИИ (ещё один вызов ИИ), потом прогонит.", inputSchema: { type: "object", properties: { agentId: { type: "string" }, confirm: { type: "boolean", description: "true — подтверждение расхода бюджета ИИ" }, caseIds: { type: "array", items: { type: "string" } }, generate: { type: "number", description: "Создать столько кейсов с ИИ перед прогоном (1–10)" }, wait: { type: "boolean" }, timeoutSec: { type: "number" } }, required: ["agentId", "confirm"] } },
|
|
1113
|
+
{ name: "agent_tests_list", description: "Кейсы проверки ИИ-клиентами и история прогонов агента (GET /api/bots/agents/{agentId}/ai-tests/cases, /runs, /runs/{runId}): cases — кейсы, history — последние 20 прогонов (итоги без диалогов), run — полный прогон (runId или последний): по каждому кейсу verdict PASS/FAIL/ERROR, reason, quote, диалог, previousVerdict и regression (раньше проходил, теперь нет). Ничего не тратит. Read-only.", inputSchema: { type: "object", properties: { agentId: { type: "string" }, runId: { type: "string" } }, required: ["agentId"] } },
|
|
1112
1114
|
// ---- Боты ----
|
|
1113
1115
|
{ name: "create_bot", description: "Подключить бота по токену (POST /api/bots): platform TELEGRAM (токен от @BotFather) или MAX (токен от MasterBot в MAX). Вебхук настраивается сам; name — отображаемое имя (иначе @username). Возвращает бота с id. Число ботов ограничено тарифом — HTTP 402 со ссылкой на смену тарифа. platform WEB — чат-виджет для сайта без токена (POST /api/bots/web): вернёт botId, key и snippet — код вставки на сайт (у существующего виджета — web_widget_snippet). platform INSTAGRAM по токену не подключается — только входом через Instagram (OAuth) в кабинете (/bots/instagram), нужен Instagram-аккаунт Business или Creator — инструмент вернёт ссылку на кабинет вместо ошибки. platform VK — сообщество как полноценный канал (Callback API, НЕ путать с vk_connect — тот для публикаций на стену): token — токен СООБЩЕСТВА (Управление сообществом → Работа с API → Создать ключ, доступ «Сообщения сообщества»), groupId — числовой id сообщества (обязателен). После подключения нужно вручную включить Callback API в настройках сообщества — см. webhookSecret в ответе и URL /vk/hooks/{botId} (подробный чек-лист у разработчика). inactive (только TELEGRAM/MAX) — создать бота остановленным: токен проверяется безопасным getMe, вебхук/поллинг НЕ трогаются — живой вебхук бота в другом конструкторе (BotHelp и т.п.) не снимается. Нужно при переносе бота из другого сервиса: создай inactive:true, перенеси сценарии/подписчиков (migration_preview/migration_commit), потом bot_resume — это и есть переключение (cutover).", inputSchema: { type: "object", properties: { platform: { type: "string", enum: ["TELEGRAM", "MAX", "WEB", "INSTAGRAM", "VK"] }, token: { type: "string", description: "Токен бота/сообщества: 123456789:AA… (Telegram), токен MAX, или community token VK" }, groupId: { type: "string", description: "Только platform=VK: числовой id сообщества" }, name: { type: "string" }, inactive: { type: "boolean", description: "Только TELEGRAM/MAX: создать остановленным (перенос из другого конструктора) — включить потом через bot_resume" } }, required: ["platform"] } },
|
|
1114
1116
|
// ---- VK-лендинги (growth tools, Mini App) ----
|
|
@@ -1443,7 +1445,15 @@ async function handleCall(params) {
|
|
|
1443
1445
|
}
|
|
1444
1446
|
return okResult({ graphId, steps });
|
|
1445
1447
|
}
|
|
1446
|
-
case "list_templates":
|
|
1448
|
+
case "list_templates": {
|
|
1449
|
+
const all = await api("/api/bots/graph-templates");
|
|
1450
|
+
if (!Array.isArray(all) || !(a.niche || a.channel || a.query)) return okResult(all);
|
|
1451
|
+
const q = String(a.query || "").trim().toLowerCase();
|
|
1452
|
+
return okResult(all.filter((t) =>
|
|
1453
|
+
(!a.niche || t.niche === a.niche)
|
|
1454
|
+
&& (!a.channel || (Array.isArray(t.channels) && t.channels.includes(String(a.channel).toUpperCase())))
|
|
1455
|
+
&& (!q || `${t.name} ${t.description} ${t.nameEn || ""} ${t.descriptionEn || ""}`.toLowerCase().includes(q))));
|
|
1456
|
+
}
|
|
1447
1457
|
case "create_graph_from_template":
|
|
1448
1458
|
return okResult(await api(`/api/bots/${a.botId}/graphs/from-template`, { method: "POST", body: { templateId: a.templateId, name: a.name } }));
|
|
1449
1459
|
case "rename_graph":
|
|
@@ -1591,6 +1601,29 @@ async function handleCall(params) {
|
|
|
1591
1601
|
const qs = a.days != null ? `?days=${encodeURIComponent(a.days)}` : "";
|
|
1592
1602
|
return okResult(await api(`/api/bots/agents/${a.agentId}/unanswered${qs}`));
|
|
1593
1603
|
}
|
|
1604
|
+
case "agent_tests_list": {
|
|
1605
|
+
const base = `/api/bots/agents/${a.agentId}/ai-tests`;
|
|
1606
|
+
const [cases, history] = await Promise.all([api(`${base}/cases`), api(`${base}/runs`)]);
|
|
1607
|
+
const run = a.runId ? await api(`${base}/runs/${a.runId}`) : (await api(`${base}/runs/latest`)) || null;
|
|
1608
|
+
return okResult({ cases, history, run });
|
|
1609
|
+
}
|
|
1610
|
+
case "agent_tests_run": {
|
|
1611
|
+
if (a.confirm !== true) throw new Error("Проверка тратит бюджет ИИ (до 120 вызовов на прогон). Передай confirm:true, когда владелец согласен на расход.");
|
|
1612
|
+
const base = `/api/bots/agents/${a.agentId}/ai-tests`;
|
|
1613
|
+
if (a.generate != null) {
|
|
1614
|
+
const n = Number(a.generate);
|
|
1615
|
+
if (!Number.isInteger(n) || n < 1 || n > 10) throw new Error("generate — целое от 1 до 10.");
|
|
1616
|
+
await api(`${base}/generate`, { method: "POST", body: { count: n, confirmed: true } });
|
|
1617
|
+
}
|
|
1618
|
+
let run = await api(`${base}/runs`, { method: "POST", body: { caseIds: a.caseIds, confirmed: true, trigger: "MCP" } });
|
|
1619
|
+
if (a.wait === false) return okResult(run);
|
|
1620
|
+
const deadline = Date.now() + Math.min(Math.max(Number(a.timeoutSec) || 240, 10), 600) * 1000;
|
|
1621
|
+
while (run.status === "RUNNING" && Date.now() < deadline) {
|
|
1622
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
1623
|
+
run = await api(`${base}/runs/${run.id}`);
|
|
1624
|
+
}
|
|
1625
|
+
return okResult(run.status === "RUNNING" ? { ...run, note: "Прогон ещё идёт — смотри agent_tests_list с runId." } : run);
|
|
1626
|
+
}
|
|
1594
1627
|
case "kb_delete_doc": {
|
|
1595
1628
|
await api(`/api/bots/kb/${a.kbId}/docs/${a.docId}`, { method: "DELETE" });
|
|
1596
1629
|
return okResult(`🗑️ Документ ${a.docId} удалён из базы ${a.kbId}.`);
|