@besales/mcp 0.33.0 → 0.37.1

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.
Files changed (50) hide show
  1. package/README.md +45 -12
  2. package/dist/http/api-client.d.ts +2 -0
  3. package/dist/http/api-client.js +55 -0
  4. package/dist/http/api-client.js.map +1 -1
  5. package/dist/resources/docs/agent-behavior.md +7 -5
  6. package/dist/resources/docs/prompt-anatomy.md +4 -4
  7. package/dist/resources/docs/prompt-principles.md +22 -3
  8. package/dist/schemas/mcp-tools.json +1369 -98
  9. package/dist/skills/besales-dialogue-audit/SKILL.md +6 -0
  10. package/dist/tools/definitions/broadcast-analytics.d.ts +28 -7
  11. package/dist/tools/definitions/broadcast-analytics.js +399 -33
  12. package/dist/tools/definitions/broadcast-analytics.js.map +1 -1
  13. package/dist/tools/definitions/broadcast-mailing-variants.d.ts +19 -0
  14. package/dist/tools/definitions/broadcast-mailing-variants.js +107 -0
  15. package/dist/tools/definitions/broadcast-mailing-variants.js.map +1 -0
  16. package/dist/tools/definitions/dialogue-audit.d.ts +23 -0
  17. package/dist/tools/definitions/dialogue-audit.js +155 -0
  18. package/dist/tools/definitions/dialogue-audit.js.map +1 -0
  19. package/dist/tools/definitions/follow-up-setup.d.ts +27 -0
  20. package/dist/tools/definitions/follow-up-setup.js +76 -0
  21. package/dist/tools/definitions/follow-up-setup.js.map +1 -0
  22. package/dist/tools/definitions/follow-up.d.ts +19 -0
  23. package/dist/tools/definitions/follow-up.js +81 -3
  24. package/dist/tools/definitions/follow-up.js.map +1 -1
  25. package/dist/tools/definitions/getcourse-wave.d.ts +147 -0
  26. package/dist/tools/definitions/getcourse-wave.js +505 -0
  27. package/dist/tools/definitions/getcourse-wave.js.map +1 -0
  28. package/dist/tools/definitions/platform-setup.d.ts +92 -20
  29. package/dist/tools/definitions/platform-setup.js +132 -537
  30. package/dist/tools/definitions/platform-setup.js.map +1 -1
  31. package/dist/tools/definitions/scheduled-tasks.d.ts +9 -0
  32. package/dist/tools/definitions/scheduled-tasks.js +49 -2
  33. package/dist/tools/definitions/scheduled-tasks.js.map +1 -1
  34. package/dist/tools/definitions/session.js +6 -4
  35. package/dist/tools/definitions/session.js.map +1 -1
  36. package/dist/tools/definitions/shared.d.ts +75 -13
  37. package/dist/tools/definitions/shared.js +120 -7
  38. package/dist/tools/definitions/shared.js.map +1 -1
  39. package/dist/tools/definitions.d.ts +171 -26
  40. package/dist/tools/definitions.js +4 -0
  41. package/dist/tools/definitions.js.map +1 -1
  42. package/dist/tools/registry-mapping-cases-core.d.ts +38 -0
  43. package/dist/tools/registry-mapping-cases-core.js +700 -0
  44. package/dist/tools/registry-mapping-cases-core.js.map +1 -0
  45. package/dist/tools/registry-mapping-cases-platform.d.ts +2 -0
  46. package/dist/tools/registry-mapping-cases-platform.js +954 -0
  47. package/dist/tools/registry-mapping-cases-platform.js.map +1 -0
  48. package/dist/tools/registry.js +12 -6
  49. package/dist/tools/registry.js.map +1 -1
  50. package/package.json +2 -2
package/README.md CHANGED
@@ -132,11 +132,22 @@ Workspace selection precedence, per tool call:
132
132
  2. an explicit `workspace_id` argument (only when the env var is not set).
133
133
  3. the session binding set by the `besales_workspace_use` tool (in-memory, this
134
134
  session/process only — see below).
135
- 4. the global active workspace set by `besales-mcp use <id>`.
136
- 5. the only connected workspace (error if several are connected and none chosen).
137
-
138
- `active` is global across all env-less sessions, and `BESALES_WORKSPACE_ID`
139
- always overrides it. Get workspace ids from `besales-mcp connections`.
135
+ 4. the only connected workspace.
136
+ 5. otherwise the call is refused — several workspaces are connected and none was
137
+ chosen.
138
+
139
+ **The global `active` workspace is not an implicit fallback.** It is set on the
140
+ very first `connect` and never revisited, so using it silently would send calls
141
+ to whichever workspace you happened to connect first — returning another
142
+ workspace's data with no error at all. When several workspaces are connected and
143
+ nothing above selects one, the call fails closed; the error names the current
144
+ `active` so you can pass it explicitly if that is what you meant. With exactly
145
+ one connection nothing changes. `besales_workspace_current` reports
146
+ `source: "ambiguous"` and `workspace_id: null` in the same situation, so the
147
+ diagnostic never claims a binding the real call would not use.
148
+
149
+ `BESALES_WORKSPACE_ID` always overrides everything. Get workspace ids from
150
+ `besales-mcp connections`.
140
151
 
141
152
  ### GUI hosts without per-session env (e.g. Claude Desktop)
142
153
 
@@ -279,7 +290,7 @@ connect each once and pin sessions via `BESALES_WORKSPACE_ID` (or switch the
279
290
  global default with `besales-mcp use <id>`) — see
280
291
  [Multiple Workspaces](#multiple-workspaces).
281
292
 
282
- ## Available tools (160 tools by category)
293
+ ## Available tools (169 tools by category)
283
294
 
284
295
  Counts are derived from `src/schemas/mcp-tools.json` (`summary.tools_by_category`)
285
296
  and asserted in `src/tools/registry.spec.ts`:
@@ -288,7 +299,7 @@ and asserted in `src/tools/registry.spec.ts`:
288
299
  |---|---|---|
289
300
  | ICP (profiles, dialogue import, analysis) | 5 | incl. `besales_icp_analysis_*` external pair |
290
301
  | ICP — read (profile / segments / scenarios / samples) | 4 | `besales_icp_list` / `_get` / `_scenarios_list` / `_sample_messages` (read-only over existing GET `/api/v2/icp/*`) |
291
- | Prompt generation / analysis / lint / patch sessions | 13 | `besales_prompt_*`, `besales_qa_generation_*` external pairs |
302
+ | Prompt generation / analysis / lint / patch sessions | 18 | `besales_prompt_*`, `besales_qa_generation_*` external pairs; `besales_prompt_headroom` — lint headroom + section weights **before** building a draft; `besales_prompt_diff` — line-level divergence between two agents' prompts; `besales_prompt_batch_start` / `_status` / `_resume` — roll one edit across a fleet of agents as a background run |
292
303
  | Sandbox / simulation / test-scenario generation | 7 | `besales_sandbox_*`, `besales_simulation_*`, `besales_test_scenario_*` |
293
304
  | Model comparison (bake-off) | 4 | `besales_model_catalog_list` + `besales_model_comparison_run_start` / `_get` / `_eval_submit` (on-demand multi-model prompt comparison) |
294
305
  | Agent / router / triggers / behavior / facts | 14 | Platform Setup Bridge (incl. `besales_agent_clone`, `besales_behavior_update`, `besales_pipeline_settings_update`, `besales_platform_settings_update`) + `besales_facts_*` |
@@ -309,13 +320,23 @@ and asserted in `src/tools/registry.spec.ts`:
309
320
  | Context / overview / audit | 3 | `besales_workspace_overview`, `besales_platform_context_get`, `besales_audit_revert` |
310
321
  | Session / workspace binding | 2 | `besales_workspace_use`, `besales_workspace_current` (in-memory per-session, local — no backend) |
311
322
  | Dialogue audit | 2 | `besales_dialogues_query`, `besales_dialogue_transcript` — read-only transcript + trigger-action evidence |
312
- | Broadcast analytics | 2 | `besales_broadcast_analytics_get`, `besales_broadcast_cohorts_list` — authoritative read-only metrics from `/broadcast-analytics`, not transcript-derived counts |
313
- | GetCourse waves | 10 | `besales_getcourse_wave_import`, `besales_getcourse_wave_status`, `besales_getcourse_wave_run_start`, `besales_getcourse_wave_run_status`, `besales_getcourse_wave_run_contacts`, `besales_getcourse_wave_run_cancel`, `besales_getcourse_wave_run_batch_start`, `besales_getcourse_wave_run_batch_status`, `besales_getcourse_wave_run_batch_cancel`, `besales_getcourse_wave_run_batch_resume` |
323
+ | Broadcast analytics | 2 | `besales_broadcast_analytics_get`, `besales_broadcast_cohorts_list` — authoritative read-only aggregates, drill-downs, segment/product catalogs, insights and payment-candidate reports from `/broadcast-analytics`, not transcript-derived counts |
324
+ | GetCourse waves | 10 | `besales_getcourse_wave_import`, `besales_getcourse_wave_status`, `besales_getcourse_wave_run_start`, `besales_getcourse_wave_run_status`, `besales_getcourse_wave_run_contacts`, `besales_getcourse_wave_run_cancel`, `besales_getcourse_wave_run_batch_start`, `besales_getcourse_wave_run_batch_status`, `besales_getcourse_wave_run_batch_cancel`, `besales_getcourse_wave_run_batch_resume`; durable confirm использует стабильный `launch_key` + `dry_run_hash`, import/run/batch принимают `segment_description` |
314
325
  | Scheduled tasks | 2 | `besales_scheduled_task_list`, `besales_scheduled_task_update` — cron-driven dialogue analysis («суфлёр»): daily summary + hourly status written to the CRM timeline or as a hidden open-line message, never to the client |
315
326
  | Follow-up (read) | 2 | `besales_followup_sequence_list`, `besales_followup_step_stats` — read a sequence config before a read-modify-write upsert, and see per-step delivery/skip reasons |
316
327
 
317
328
  Recent capabilities:
318
329
 
330
+ - **Prompt lint diagnostics** — a rejected `besales_prompt_patch_commit` now carries the
331
+ backend's `lintIssues` (up to 3, e.g. the exact character count over the 80000 hard
332
+ limit) instead of a bare 400. `besales_prompt_headroom` answers the same question
333
+ *before* a draft is built; `besales_prompt_diff` compares two agents' prompts without
334
+ pulling both full texts into context.
335
+ - **Fleet prompt rollout** — `besales_prompt_batch_start` applies one set of patch
336
+ operations across many agents as a background run (33 agents × 3 calls do not fit the
337
+ 60s client timeout). Every agent is prepared and fully linted first; only those that
338
+ pass are committed. Poll `besales_prompt_batch_status`; roll forward the failures with
339
+ `besales_prompt_batch_resume` — never by starting a second run.
319
340
  - **OAuth PKCE provisioning** — `besales_platform_create_oauth_init` opens the
320
341
  authorization flow in the browser for Instagram/Avito so the OAuth code never
321
342
  passes through the LLM.
@@ -333,7 +354,19 @@ Recent capabilities:
333
354
  - **GetCourse wave-run batches** — queue 1–10 status-mode segments sequentially
334
355
  through `besales_getcourse_wave_run_batch_start`; use one `_batch_status` poll,
335
356
  reuse a generated `batch_key` on retry, and resume only after resolving two
336
- consecutive rejected segments.
357
+ consecutive rejected segments. `UNKNOWN` и небезопасный `FAILED` жёстко
358
+ блокируются между волнами; repeat mode не является обходом неопределённого исхода.
359
+ Контакты import/run/batch принимают `email`, `phone`, `first_name`, `last_name` и передают их
360
+ backend-у без потери snake_case→camelCase.
361
+ - **Broadcast mailing variants** — `besales_broadcast_mailing_variant_list/create/update/delete`;
362
+ архивирование через delete или `update(archived=true)` требует `explicit_confirmation=true`
363
+ управляют workspace-каталогом «Вариантов рассылки». Передавай выбранный UUID как
364
+ `mailing_variant_id` в direct, durable или batch GetCourse wave; analytics принимает тот же
365
+ фильтр. Удаление использованного варианта архивирует его и сохраняет историю когорт.
366
+ - **GetCourse school bindings** — `besales_platform_settings_update` принимает
367
+ `getcourse_settings.wave_field_bindings`: роли `launch_type/product/segment/funnel/channels`
368
+ связываются с numeric custom-field ID сделки; `product_value_source` выбирает код или название
369
+ продукта, а `null` очищает настройку школы.
337
370
 
338
371
  ## Resources
339
372
 
@@ -357,7 +390,7 @@ Inspect them locally:
357
390
  yarn dlx @modelcontextprotocol/inspector node bin/besales-mcp.js
358
391
  ```
359
392
 
360
- The Inspector should show 160 tools and 31 resources.
393
+ The Inspector should show 169 tools and 31 resources.
361
394
 
362
395
  ## Codex Dialogue Audit Skill
363
396
 
@@ -401,7 +434,7 @@ Claude Code, and Codex CLI are documented in
401
434
  - This package calls Animaly only through `ai-aniomaly` `/api/v2/*`.
402
435
  - Direct calls to `prompt-services` are intentionally out of scope.
403
436
 
404
- The package exposes 128 active MCP tools from `src/schemas/mcp-tools.json`.
437
+ The package exposes 169 active MCP tools from `src/schemas/mcp-tools.json`.
405
438
 
406
439
  ### Token scopes
407
440
 
@@ -1,4 +1,6 @@
1
1
  export declare const API_REQUEST_TIMEOUT_MS = 60000;
2
+ /** Сколько lint-замечаний включать в текст ошибки инструмента, чтобы он остался читаемым. */
3
+ export declare const LINT_ISSUES_IN_ERROR_LIMIT = 3;
2
4
  export type ApiMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
3
5
  export interface ApiTransportRequest {
4
6
  readonly method: ApiMethod;
@@ -2,6 +2,8 @@ import axios from 'axios';
2
2
  import { normalizeApiBaseUrl } from '../auth/oauth-client.js';
3
3
  import { logger } from '../utils/logger.js';
4
4
  export const API_REQUEST_TIMEOUT_MS = 60_000;
5
+ /** Сколько lint-замечаний включать в текст ошибки инструмента, чтобы он остался читаемым. */
6
+ export const LINT_ISSUES_IN_ERROR_LIMIT = 3;
5
7
  export class ApiClientError extends Error {
6
8
  status;
7
9
  responseMessage;
@@ -89,7 +91,60 @@ export function buildApiUrl(apiBaseUrl, path) {
89
91
  }
90
92
  return `${normalizedBaseUrl}${normalizedPath}`;
91
93
  }
94
+ /**
95
+ * Текст ошибки для инструмента: `message` из тела плюс диагностические поля, которые
96
+ * бэкенд кладёт рядом с ним.
97
+ *
98
+ * Раньше отдавался только `message`, из-за чего `lintIssues` при 400 на
99
+ * `POST /agents/{id}/prompt/drafts/{draftId}/commit` терялись, и вызывающий видел
100
+ * «Prompt failed lint validation» без причины и без цифры (например без «Промпт 81590
101
+ * символов — превышает жёсткий лимит 80000»).
102
+ */
92
103
  function getSafeResponseMessage(data) {
104
+ const baseMessage = extractResponseMessage(data);
105
+ const lintDetail = extractLintIssuesDetail(data);
106
+ if (baseMessage && lintDetail) {
107
+ return `${baseMessage} | ${lintDetail}`;
108
+ }
109
+ return baseMessage ?? lintDetail;
110
+ }
111
+ /**
112
+ * Диагностика из `lintIssues` — whitelist полей, а не тело целиком: в ответе может быть PII,
113
+ * и она не должна попадать в текст ошибки инструмента.
114
+ */
115
+ function extractLintIssuesDetail(data) {
116
+ if (!data || typeof data !== 'object') {
117
+ return undefined;
118
+ }
119
+ const issues = data.lintIssues;
120
+ if (!Array.isArray(issues) || issues.length === 0) {
121
+ return undefined;
122
+ }
123
+ const formatted = issues
124
+ .slice(0, LINT_ISSUES_IN_ERROR_LIMIT)
125
+ .map((issue) => formatLintIssue(issue))
126
+ .filter((item) => item !== undefined);
127
+ if (formatted.length === 0) {
128
+ return undefined;
129
+ }
130
+ const hidden = issues.length - formatted.length;
131
+ const suffix = hidden > 0 ? ` (и ещё ${hidden})` : '';
132
+ return `lint: ${formatted.join('; ')}${suffix}`;
133
+ }
134
+ function formatLintIssue(issue) {
135
+ if (!issue || typeof issue !== 'object') {
136
+ return undefined;
137
+ }
138
+ const { severity, category, message } = issue;
139
+ if (typeof message !== 'string' || message.length === 0) {
140
+ return undefined;
141
+ }
142
+ const prefix = [severity, category]
143
+ .filter((part) => typeof part === 'string' && part.length > 0)
144
+ .join('/');
145
+ return prefix ? `${prefix} — ${message}` : message;
146
+ }
147
+ function extractResponseMessage(data) {
93
148
  if (!data || typeof data !== 'object') {
94
149
  return undefined;
95
150
  }
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/http/api-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/http/api-client.ts"],"names":[],"mappings":"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"}
@@ -205,7 +205,7 @@
205
205
 
206
206
  | Поле | Дефолт | Описание |
207
207
  |---|---|---|
208
- | `botWaitingReturn` | 3 | Сколько часов бот молчит после сообщения оператора. Допустимые: `0`, `1`, `3`, `6`, `12`, `24`. `0` = до команды `/start`. |
208
+ | `botWaitingReturn` | 3 | Сколько часов бот молчит после сообщения оператора. Допустимые: `-1`, `0`, `1`, `3`, `6`, `12`, `24`. `-1` = ответ оператора вообще не отключает бота, `0` = до команды `/start`. |
209
209
  | `followUpWaitingReturn` | -1 | На сколько часов отключить follow-up после оператора. `-1` = не отключать, `0` = навсегда, `1`–`24` — часы. |
210
210
  | `skipTaskCreationOnCallOperator` | false | Если `true` — при `call_operator` система **только** меняет ответственного на оператора, без постановки задачи в CRM. Полезно, когда workflow в CRM ведётся через статусы воронки, а не через task'ы, и лишние «висящие» задачи на оператора засоряют его список дел. |
211
211
  | `anonymizationEnabled` | false | Обратимая PII-анонимизация LLM-пайплайна (per-platform). Если `true` — реальные имя/телефон/email клиента вырезаются из сообщений перед отправкой в LLM (заменяются токенами) и подставляются обратно в ответе и в аргументах tool-call (например, поля CRM). Ставится через секцию `privacy: { anonymization_enabled }` в `besales_behavior_update`. |
@@ -237,17 +237,18 @@
237
237
  | `PROCESS_WITH_LLM` | Запустить vision-модель (gpt-4.1-mini) и интерпретировать изображение в текст для LLM. |
238
238
  | `FIXED_RESPONSE` | Отправить фиксированный текст из `imageFixedResponseText`. |
239
239
 
240
- `PROCESS_WITH_LLM` для изображений запускает vision-модель. Для **видео** `PROCESS_WITH_LLM` обрабатывает **подпись (caption)** как обычный текст через LLM — само видео в модель не отправляется; нет подписи → вызывается оператор; работает на Telegram Bot/Personal, Wazzup, VK, Bitrix24Bot, Salebot, GetCourse (на Avito/Instagram видео → оператор). Для документов/аудио — только `SILENT` или `FIXED_RESPONSE`.
240
+ `PROCESS_WITH_LLM` есть у трёх типов из четырёх, и механика у каждого СВОЯ: изображение уходит в vision-модель; у **видео** обрабатывается **подпись (caption)** как обычный текст (само видео не отправляется, нет подписи → оператор; Telegram Bot/Personal, Wazzup, VK, Bitrix24Bot, Salebot, GetCourse — на Avito/Instagram видео → оператор); у **документа** обрабатывается **извлечённый текст файла** (сам файл не отправляется). У **аудио** этого значения нет вовсе — только `SILENT` или `FIXED_RESPONSE`.
241
241
 
242
242
  ### Видео / Документы / Аудио (`VideoHandlingBehavior`, `DocumentHandlingBehavior`, `AudioHandlingBehavior`)
243
243
 
244
- `DocumentHandlingBehavior` и `AudioHandlingBehavior` имеют значения `SILENT` / `FIXED_RESPONSE`. `VideoHandlingBehavior` дополнительно поддерживает `PROCESS_WITH_LLM`:
244
+ `AudioHandlingBehavior` имеет только `SILENT` / `FIXED_RESPONSE`. `VideoHandlingBehavior` и `DocumentHandlingBehavior` дополнительно поддерживают `PROCESS_WITH_LLM`:
245
245
 
246
246
  | Значение | Что делает |
247
247
  |---|---|
248
248
  | `SILENT` | Промолчать (default). |
249
249
  | `FIXED_RESPONSE` | Отправить фиксированный текст из соответствующего `*FixedResponseText`. |
250
- | `PROCESS_WITH_LLM` *(только video)* | Обработать **подпись** видео как текст через LLM (само видео не отправляется; нет подписи → оператор; Telegram/Wazzup/VK/Bitrix24/Salebot/GetCourse, кроме Avito/Instagram). |
250
+ | `PROCESS_WITH_LLM` *(video)* | Обработать **подпись** видео как текст через LLM (само видео не отправляется; нет подписи → оператор; Telegram/Wazzup/VK/Bitrix24/Salebot/GetCourse, кроме Avito/Instagram). |
251
+ | `PROCESS_WITH_LLM` *(document)* | Извлечь текст файла (PDF, DOCX, DOC, XLSX, XLS, CSV, TSV, TXT, MD) и обработать как обычное сообщение. Сам файл в модель не отправляется. Длинный документ передаётся не целиком — модель предупреждается об усечении. Скан без текстового слоя, неподдерживаемый формат и файл >20 МБ → оператор. На Avito документ приходит голой ссылкой: без расширения в ней разбор невозможен → оператор. |
251
252
 
252
253
  ```json
253
254
  {
@@ -376,11 +377,12 @@
376
377
  | `messageOpenDelay` только для Telegram Personal | На обычных Telegram Bot ничего не даёт. |
377
378
  | `messageDevide=true` без `messageChunkSeparator` | Не работает — нужен явный разделитель. |
378
379
  | LLM должен знать про `messageChunkSeparator` | Если включаете `messageDevide`, добавьте в `baseSystemPrompt` инструкцию: «Когда нужно разделить ответ на части, ставь между частями `%%%`». |
379
- | `imageHandlingBehavior=PROCESS_WITH_LLM` | Только для изображений (vision). Для видео/доков/аудио — `SILENT` или `FIXED_RESPONSE`. |
380
+ | `audioHandlingBehavior=PROCESS_WITH_LLM` | Такого значения нет — только `SILENT` или `FIXED_RESPONSE`, иначе 400. У image/video/document разбор есть, но механика у каждого своя (vision / подпись / текст файла). |
380
381
  | `urlHandlingBehavior=PROCESS_WITH_CRAWLER` | Может тормозить (внешний запрос). Не включать массово. |
381
382
  | `messageFilters` — до 20 правил | Применяются по `order`. |
382
383
  | `greetingButtons` — до 10 кнопок | Платформенный лимит. |
383
384
  | `botWaitingReturn=0` | Бот не вернётся автоматически — нужно явное `/start` от оператора. |
385
+ | `botWaitingReturn=-1` | Бот отвечает поверх оператора — берут в суфлёрских/квалификационных каналах. Стадию CRM «оператор перехватил» настройка НЕ отменяет: если у этой стадии выключен `isBotActive`, бот всё равно замолчит по стадийному гейту. |
384
386
  | `operatorSchedule.enabled=false` | Оператор «всегда доступен» — не блокировать `call_operator`. |
385
387
  | `aiErrorTargetStageId=null` | Не критично — система переведёт на первый этап. |
386
388
  | `skipTaskCreationOnCallOperator=true` | Только смена ответственного, без постановки задачи в CRM (для AmoCRM/Bitrix24). |
@@ -188,7 +188,7 @@ AI-сервис генерирует только **`baseSystemPrompt`**. Всё
188
188
  Доступные инструменты: ← LLM получает их через tools API
189
189
  - call_operator(reason)
190
190
  - handle_want_buy(productOrService, intent)
191
- - save_user_info(firstName, lastName, ...)
191
+ - save_user_info(name, surname, city, insight)
192
192
 
193
193
  Если клиент сказал «хочу купить» — вызови ← триггеры подставляются отдельно
194
194
  run_trigger с triggerId="abc-123".
@@ -224,11 +224,11 @@ run_trigger с triggerId="abc-123".
224
224
 
225
225
  | Параметр | Значение |
226
226
  |---|---|
227
- | Максимальная длина одного промпта | 60 000 символов (`PROMPT_LIMITS.MAX_PROMPT_LENGTH`) |
227
+ | Максимальная длина одного промпта | 80 000 символов (`PROMPT_LIMITS.MAX_PROMPT_LENGTH`) |
228
228
  | Максимум триггеров в промпте | 50 |
229
229
  | Максимум длины условия триггера | 500 символов |
230
230
 
231
- За длиной `baseSystemPrompt` следит `PromptLintService`: **warn** при превышении **25 000** символов (`PROMPT_LIMITS.SOFT_PROMPT_LENGTH`) и **hard_fail** (блокирует `prompt_finalize` / `prompt_patch_commit`) при превышении **60 000** (`PROMPT_LIMITS.MAX_PROMPT_LENGTH`). Держи `baseSystemPrompt` компактным — ориентир **20 000–25 000 символов**, вынося факты в Базу знаний (документы / Q&A), чтобы оставить место под системные блоки, RAG-контекст и историю.
231
+ За длиной `baseSystemPrompt` следит `PromptLintService`: **warn** при превышении **40 000** символов (`PROMPT_LIMITS.SOFT_PROMPT_LENGTH`) и **hard_fail** (блокирует `prompt_finalize` / `prompt_patch_commit`) при превышении **80 000** (`PROMPT_LIMITS.MAX_PROMPT_LENGTH`). Держи `baseSystemPrompt` компактным — ориентир **30 000–40 000 символов**, вынося факты в Базу знаний (документы / Q&A), чтобы оставить место под системные блоки, RAG-контекст и историю.
232
232
 
233
233
  ## 12. factualContext — активные факты агента
234
234
 
@@ -255,7 +255,7 @@ run_trigger с triggerId="abc-123".
255
255
  | `runtime_banned_term` | Агент в run-time произнёс §9-запрещённый термин (только post-run, не на prompt-level) | `hard_fail` | Transcript-lint в sandbox |
256
256
  | `agent_banned_term` | Терм из per-agent feedback sheet (`AgentFeedbackSheetLink` → §07 Google Sheets) | `warn` | Prompt-finalize, transcript-lint |
257
257
  | `scope_consistency` | Тон/branches противоречат `AgentChat.agentScope` (S4.12). Например, sale-агент пишет «я не могу помочь с покупкой». Regex-based | `warn` | Prompt-finalize |
258
- | `prompt_length` | Длина `baseSystemPrompt`: warn при > 25 000 символов, hard_fail при > 60 000 (`PROMPT_LIMITS`) | `warn` / `hard_fail` | Prompt-finalize |
258
+ | `prompt_length` | Длина `baseSystemPrompt`: warn при > 40 000 символов, hard_fail при > 80 000 (`PROMPT_LIMITS`) | `warn` / `hard_fail` | Prompt-finalize |
259
259
 
260
260
  ### 13.2. Severity-семантика
261
261
 
@@ -49,9 +49,28 @@
49
49
  - ❌ «по теме сосуды», «осуществляется приём заявок», «в рамках программы»
50
50
  - ✅ «про сосуды», «заявки принимаем», «в программе»
51
51
 
52
- **A4. Имена и бренд — на языке клиента.** Латиница в русском тексте читается как робот.
53
- - ❌ «помощница из Ksamata»
54
- - ✅ «помощница из Ксамата» (домены/URL вроде `site.ru` — исключение, их не переводим)
52
+ **A4. Только язык клиента — и в именах, и в обычных словах.** Латиница в русском тексте читается
53
+ как робот. Два разных случая, и второй опаснее, потому что его не ловит инструкция «отвечай на
54
+ языке клиента»: ответ формально на русском, модель считает это не сменой языка, а выбором точного
55
+ слова.
56
+ - ❌ «помощница из Ksamata» → ✅ «помощница из Ксамата» (имя/бренд)
57
+ - ❌ «куратор поддерживает в переписке **throughout** обучение» (реальный прод-случай 06.08.26)
58
+ → ✅ «куратор на связи в переписке всё время обучения»
59
+
60
+ Запрет на ЛЮБУЮ английскую вставку внутри фразы, даже когда она точнее: `throughout`, `however`,
61
+ `actually`, `basically`, `workflow`, `follow-up`, `mindset`, `check-in`. Механизм всегда один: у
62
+ слова нет однословного русского аналога, и модель тянется к компактности. Нет короткого аналога —
63
+ пиши длиннее обычными словами.
64
+
65
+ Туда же калька терминами вместо простых слов: ❌ «экспертиза», «локация», «коммуницировать» →
66
+ ✅ «опыт», «место», «расскажу». На аудитории 50+ это тот же эффект, что латиница.
67
+
68
+ Исключения обязательно называть в промпте явно, иначе агент начнёт переводить сервисы и ломать
69
+ ссылки: названия сервисов и банков, которые так и пишутся (Telegram, WhatsApp), домены и URL.
70
+
71
+ Проверять глазами бесполезно — одно слово в середине абзаца взгляд пропускает (так прод-случай и
72
+ доехал до заказчика). Гони по репликам агента поиск латиницы, вычитай ссылки и названия сервисов,
73
+ остаток должен быть пуст.
55
74
 
56
75
  **A5. Не повторяй уже сказанное.** Если ты уже описал состав/факт или задал вопрос — не описывай
57
76
  блоки снова и не задавай тот же вопрос второй раз. Каждое сообщение двигает диалог НОВЫМ шагом.