@besales/mcp 0.48.0 → 1.0.0-beta.2

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 (587) hide show
  1. package/README.md +109 -164
  2. package/README.onprem.ru.md +35 -0
  3. package/bin/besales-mcp-http.js +9 -0
  4. package/bin/besales-onprem.mjs +19 -0
  5. package/dist/auth/connection-store.d.ts +3 -1
  6. package/dist/auth/connection-store.js +9 -3
  7. package/dist/auth/connection-store.js.map +1 -1
  8. package/dist/auth/oauth-client.d.ts +20 -27
  9. package/dist/auth/oauth-client.js +31 -23
  10. package/dist/auth/oauth-client.js.map +1 -1
  11. package/dist/auth/session-workspace.d.ts +1 -0
  12. package/dist/auth/session-workspace.js +10 -1
  13. package/dist/auth/session-workspace.js.map +1 -1
  14. package/dist/auth/token-storage.js +4 -1
  15. package/dist/auth/token-storage.js.map +1 -1
  16. package/dist/cli.d.ts +1 -0
  17. package/dist/cli.js +80 -19
  18. package/dist/cli.js.map +1 -1
  19. package/dist/constants/crm-catalog.d.ts +2 -0
  20. package/dist/constants/crm-catalog.js +3 -0
  21. package/dist/constants/crm-catalog.js.map +1 -0
  22. package/dist/http/api-client.d.ts +52 -7
  23. package/dist/http/api-client.js +131 -66
  24. package/dist/http/api-client.js.map +1 -1
  25. package/dist/http/feedback-document-error.d.ts +26 -0
  26. package/dist/http/feedback-document-error.js +22 -0
  27. package/dist/http/feedback-document-error.js.map +1 -0
  28. package/dist/http-server.d.ts +15 -0
  29. package/dist/http-server.js +378 -0
  30. package/dist/http-server.js.map +1 -0
  31. package/dist/instructions/server-instructions.d.ts +1 -1
  32. package/dist/instructions/server-instructions.js +6 -3
  33. package/dist/instructions/server-instructions.js.map +1 -1
  34. package/dist/network/constants.d.ts +25 -0
  35. package/dist/network/constants.js +26 -0
  36. package/dist/network/constants.js.map +1 -0
  37. package/dist/network/failed-verifications.d.ts +10 -0
  38. package/dist/network/failed-verifications.js +37 -0
  39. package/dist/network/failed-verifications.js.map +1 -0
  40. package/dist/network/http-test-fixture.d.ts +3 -0
  41. package/dist/network/http-test-fixture.js +86 -0
  42. package/dist/network/http-test-fixture.js.map +1 -0
  43. package/dist/network/known-keys.d.ts +10 -0
  44. package/dist/network/known-keys.js +38 -0
  45. package/dist/network/known-keys.js.map +1 -0
  46. package/dist/network/memory-credentials.d.ts +11 -0
  47. package/dist/network/memory-credentials.js +24 -0
  48. package/dist/network/memory-credentials.js.map +1 -0
  49. package/dist/network/rate-limit.d.ts +23 -0
  50. package/dist/network/rate-limit.js +62 -0
  51. package/dist/network/rate-limit.js.map +1 -0
  52. package/dist/network/rejected-keys.d.ts +9 -0
  53. package/dist/network/rejected-keys.js +39 -0
  54. package/dist/network/rejected-keys.js.map +1 -0
  55. package/dist/network/request-work.d.ts +8 -0
  56. package/dist/network/request-work.js +20 -0
  57. package/dist/network/request-work.js.map +1 -0
  58. package/dist/network/successful-keys.d.ts +17 -0
  59. package/dist/network/successful-keys.js +47 -0
  60. package/dist/network/successful-keys.js.map +1 -0
  61. package/dist/resources/concepts/external-execution.md +3 -1
  62. package/dist/resources/concepts/feedback-sheets.md +21 -12
  63. package/dist/resources/concepts/icp.md +8 -1
  64. package/dist/resources/concepts/sandbox.md +15 -6
  65. package/dist/resources/concepts/triggers.md +8 -0
  66. package/dist/resources/concepts/workbook-classification.md +104 -50
  67. package/dist/resources/docs/agent-behavior.md +51 -382
  68. package/dist/resources/docs/campaigns.md +9 -16
  69. package/dist/resources/docs/crm-integration.md +39 -523
  70. package/dist/resources/docs/files-and-uploads.md +23 -286
  71. package/dist/resources/docs/follow-up.md +47 -12
  72. package/dist/resources/docs/knowledge-base.md +52 -521
  73. package/dist/resources/docs/pipeline-builder.md +26 -216
  74. package/dist/resources/docs/pipeline-settings-deep.md +27 -220
  75. package/dist/resources/docs/platforms.md +106 -519
  76. package/dist/resources/docs/prompt-anatomy.md +39 -285
  77. package/dist/resources/docs/routing.md +8 -16
  78. package/dist/resources/docs/trigger-actions.md +40 -24
  79. package/dist/resources/docs/variables.md +8 -12
  80. package/dist/resources/operator-edit.contract.d.ts +7 -0
  81. package/dist/resources/operator-edit.contract.js +8 -0
  82. package/dist/resources/operator-edit.contract.js.map +1 -0
  83. package/dist/resources/registry.js +20 -4
  84. package/dist/resources/registry.js.map +1 -1
  85. package/dist/resources/workflows/audit-dialogues.md +23 -12
  86. package/dist/resources/workflows/compare-models.md +6 -6
  87. package/dist/resources/workflows/connect-crm-from-scratch.md +15 -12
  88. package/dist/resources/workflows/connect-datasource-from-scratch.md +5 -4
  89. package/dist/resources/workflows/extract-from-document.md +8 -6
  90. package/dist/resources/workflows/operator-edit.md +15 -0
  91. package/dist/resources/workflows/platform-setup-from-scratch.md +59 -70
  92. package/dist/resources/workflows/production-readiness-check.md +25 -15
  93. package/dist/schemas/mcp-tools.json +9902 -4734
  94. package/dist/schemas/voice-actions-api.contract.json +248 -0
  95. package/dist/shared/constants/broadcast-reason.constants.d.ts +2 -0
  96. package/dist/shared/constants/broadcast-reason.constants.js +47 -0
  97. package/dist/shared/constants/broadcast-reason.constants.js.map +1 -0
  98. package/dist/shared/constants/crm-stage-pool.constants.d.ts +2 -0
  99. package/dist/shared/constants/crm-stage-pool.constants.js +3 -0
  100. package/dist/shared/constants/crm-stage-pool.constants.js.map +1 -0
  101. package/dist/shared/constants/followup-note.constants.d.ts +3 -0
  102. package/dist/shared/constants/followup-note.constants.js +4 -0
  103. package/dist/shared/constants/followup-note.constants.js.map +1 -0
  104. package/dist/shared/constants/followup-session.constants.d.ts +2 -0
  105. package/dist/shared/constants/followup-session.constants.js +3 -0
  106. package/dist/shared/constants/followup-session.constants.js.map +1 -0
  107. package/dist/shared/constants/funnel-analytics.constants.d.ts +2 -0
  108. package/dist/shared/constants/funnel-analytics.constants.js +3 -0
  109. package/dist/shared/constants/funnel-analytics.constants.js.map +1 -0
  110. package/dist/shared/constants/message-filter.constants.d.ts +7 -0
  111. package/dist/shared/constants/message-filter.constants.js +8 -0
  112. package/dist/shared/constants/message-filter.constants.js.map +1 -0
  113. package/dist/shared/utils/trigger-repeat-mapping.d.ts +72 -0
  114. package/dist/shared/utils/trigger-repeat-mapping.js +53 -0
  115. package/dist/shared/utils/trigger-repeat-mapping.js.map +1 -0
  116. package/dist/skills/besales-dialogue-audit/SKILL.md +31 -20
  117. package/dist/tasks/task-state-store.js +5 -0
  118. package/dist/tasks/task-state-store.js.map +1 -1
  119. package/dist/tools/annotations.js +4 -3
  120. package/dist/tools/annotations.js.map +1 -1
  121. package/dist/tools/definitions/agent-design.d.ts +78 -21
  122. package/dist/tools/definitions/agent-design.js +246 -90
  123. package/dist/tools/definitions/agent-design.js.map +1 -1
  124. package/dist/tools/definitions/agent-model-notice.d.ts +5 -0
  125. package/dist/tools/definitions/agent-model-notice.js +31 -0
  126. package/dist/tools/definitions/agent-model-notice.js.map +1 -0
  127. package/dist/tools/definitions/agent-models.d.ts +5 -0
  128. package/dist/tools/definitions/agent-models.js +26 -0
  129. package/dist/tools/definitions/agent-models.js.map +1 -0
  130. package/dist/tools/definitions/agent-settings.d.ts +85 -0
  131. package/dist/tools/definitions/agent-settings.js +187 -0
  132. package/dist/tools/definitions/agent-settings.js.map +1 -0
  133. package/dist/tools/definitions/ai-costs.d.ts +12 -0
  134. package/dist/tools/definitions/ai-costs.js +142 -0
  135. package/dist/tools/definitions/ai-costs.js.map +1 -0
  136. package/dist/tools/definitions/api-tool-request.d.ts +15 -0
  137. package/dist/tools/definitions/api-tool-request.js +2 -0
  138. package/dist/tools/definitions/api-tool-request.js.map +1 -0
  139. package/dist/tools/definitions/behavior-shipped-form.d.ts +182 -0
  140. package/dist/tools/definitions/behavior-shipped-form.js +185 -0
  141. package/dist/tools/definitions/behavior-shipped-form.js.map +1 -0
  142. package/dist/tools/definitions/broadcast-alerts.d.ts +6 -0
  143. package/dist/tools/definitions/broadcast-alerts.js +72 -0
  144. package/dist/tools/definitions/broadcast-alerts.js.map +1 -0
  145. package/dist/tools/definitions/broadcast-analytics.d.ts +102 -18
  146. package/dist/tools/definitions/broadcast-analytics.js +732 -431
  147. package/dist/tools/definitions/broadcast-analytics.js.map +1 -1
  148. package/dist/tools/definitions/broadcast-scheduler.d.ts +10 -13
  149. package/dist/tools/definitions/broadcast-scheduler.js +196 -154
  150. package/dist/tools/definitions/broadcast-scheduler.js.map +1 -1
  151. package/dist/tools/definitions/call-operator-task.schema.d.ts +11 -0
  152. package/dist/tools/definitions/call-operator-task.schema.js +30 -0
  153. package/dist/tools/definitions/call-operator-task.schema.js.map +1 -0
  154. package/dist/tools/definitions/contacts.d.ts +3 -0
  155. package/dist/tools/definitions/contacts.js +57 -31
  156. package/dist/tools/definitions/contacts.js.map +1 -1
  157. package/dist/tools/definitions/crm-platform.d.ts +28 -41
  158. package/dist/tools/definitions/crm-platform.js +235 -368
  159. package/dist/tools/definitions/crm-platform.js.map +1 -1
  160. package/dist/tools/definitions/crm-stage-pool.messages.d.ts +39 -0
  161. package/dist/tools/definitions/crm-stage-pool.messages.js +43 -0
  162. package/dist/tools/definitions/crm-stage-pool.messages.js.map +1 -0
  163. package/dist/tools/definitions/crm-stage-pool.schema.d.ts +64 -0
  164. package/dist/tools/definitions/crm-stage-pool.schema.js +109 -0
  165. package/dist/tools/definitions/crm-stage-pool.schema.js.map +1 -0
  166. package/dist/tools/definitions/custom-reports.d.ts +12 -0
  167. package/dist/tools/definitions/custom-reports.js +68 -0
  168. package/dist/tools/definitions/custom-reports.js.map +1 -0
  169. package/dist/tools/definitions/datasource.d.ts +2 -1
  170. package/dist/tools/definitions/datasource.js +28 -13
  171. package/dist/tools/definitions/datasource.js.map +1 -1
  172. package/dist/tools/definitions/dialog-review-findings-response.d.ts +14 -0
  173. package/dist/tools/definitions/dialog-review-findings-response.js +23 -0
  174. package/dist/tools/definitions/dialog-review-findings-response.js.map +1 -0
  175. package/dist/tools/definitions/dialog-review-safe-response.d.ts +5 -0
  176. package/dist/tools/definitions/dialog-review-safe-response.js +152 -0
  177. package/dist/tools/definitions/dialog-review-safe-response.js.map +1 -0
  178. package/dist/tools/definitions/dialog-review.d.ts +49 -0
  179. package/dist/tools/definitions/dialog-review.js +383 -0
  180. package/dist/tools/definitions/dialog-review.js.map +1 -0
  181. package/dist/tools/definitions/dialogue-analysis.d.ts +46 -0
  182. package/dist/tools/definitions/dialogue-analysis.js +170 -0
  183. package/dist/tools/definitions/dialogue-analysis.js.map +1 -0
  184. package/dist/tools/definitions/dialogue-audit-agent-scope.d.ts +7 -0
  185. package/dist/tools/definitions/dialogue-audit-agent-scope.js +41 -0
  186. package/dist/tools/definitions/dialogue-audit-agent-scope.js.map +1 -0
  187. package/dist/tools/definitions/dialogue-audit-alias.d.ts +67 -0
  188. package/dist/tools/definitions/dialogue-audit-alias.js +559 -0
  189. package/dist/tools/definitions/dialogue-audit-alias.js.map +1 -0
  190. package/dist/tools/definitions/dialogue-export.d.ts +7 -1
  191. package/dist/tools/definitions/dialogue-export.js +89 -32
  192. package/dist/tools/definitions/dialogue-export.js.map +1 -1
  193. package/dist/tools/definitions/dialogue-followup-state.d.ts +9 -0
  194. package/dist/tools/definitions/dialogue-followup-state.js +69 -0
  195. package/dist/tools/definitions/dialogue-followup-state.js.map +1 -0
  196. package/dist/tools/definitions/edit-version-transport.test-fixtures.d.ts +13 -0
  197. package/dist/tools/definitions/edit-version-transport.test-fixtures.js +292 -0
  198. package/dist/tools/definitions/edit-version-transport.test-fixtures.js.map +1 -0
  199. package/dist/tools/definitions/edit-version.d.ts +5 -0
  200. package/dist/tools/definitions/edit-version.js +20 -0
  201. package/dist/tools/definitions/edit-version.js.map +1 -0
  202. package/dist/tools/definitions/external-api-channels.js +17 -15
  203. package/dist/tools/definitions/external-api-channels.js.map +1 -1
  204. package/dist/tools/definitions/feedback-document-access.d.ts +16 -0
  205. package/dist/tools/definitions/feedback-document-access.js +63 -0
  206. package/dist/tools/definitions/feedback-document-access.js.map +1 -0
  207. package/dist/tools/definitions/fixtures/shipped-setup-status.d.ts +3 -0
  208. package/dist/tools/definitions/fixtures/shipped-setup-status.js +9 -0
  209. package/dist/tools/definitions/fixtures/shipped-setup-status.js.map +1 -0
  210. package/dist/tools/definitions/follow-up-config.d.ts +79 -0
  211. package/dist/tools/definitions/follow-up-config.js +258 -0
  212. package/dist/tools/definitions/follow-up-config.js.map +1 -0
  213. package/dist/tools/definitions/follow-up-funnel-test.d.ts +4 -3
  214. package/dist/tools/definitions/follow-up-funnel-test.js +65 -52
  215. package/dist/tools/definitions/follow-up-funnel-test.js.map +1 -1
  216. package/dist/tools/definitions/follow-up-promotion-instructions.d.ts +2 -0
  217. package/dist/tools/definitions/follow-up-promotion-instructions.js +7 -0
  218. package/dist/tools/definitions/follow-up-promotion-instructions.js.map +1 -0
  219. package/dist/tools/definitions/follow-up-setup.d.ts +4 -28
  220. package/dist/tools/definitions/follow-up-setup.js +20 -87
  221. package/dist/tools/definitions/follow-up-setup.js.map +1 -1
  222. package/dist/tools/definitions/follow-up.d.ts +20 -122
  223. package/dist/tools/definitions/follow-up.js +200 -357
  224. package/dist/tools/definitions/follow-up.js.map +1 -1
  225. package/dist/tools/definitions/followup-getcourse-compat.d.ts +29 -0
  226. package/dist/tools/definitions/followup-getcourse-compat.js +62 -0
  227. package/dist/tools/definitions/followup-getcourse-compat.js.map +1 -0
  228. package/dist/tools/definitions/followup-sequence-config.schema.d.ts +10 -0
  229. package/dist/tools/definitions/followup-sequence-config.schema.js +14 -0
  230. package/dist/tools/definitions/followup-sequence-config.schema.js.map +1 -0
  231. package/dist/tools/definitions/funnel-analytics.d.ts +18 -0
  232. package/dist/tools/definitions/funnel-analytics.js +150 -0
  233. package/dist/tools/definitions/funnel-analytics.js.map +1 -0
  234. package/dist/tools/definitions/getcourse-anchor-refresh.d.ts +5 -9
  235. package/dist/tools/definitions/getcourse-anchor-refresh.js +26 -31
  236. package/dist/tools/definitions/getcourse-anchor-refresh.js.map +1 -1
  237. package/dist/tools/definitions/getcourse-cold-outbound-settings.d.ts +46 -0
  238. package/dist/tools/definitions/getcourse-cold-outbound-settings.js +37 -0
  239. package/dist/tools/definitions/getcourse-cold-outbound-settings.js.map +1 -0
  240. package/dist/tools/definitions/getcourse-cold-welcome.d.ts +14 -29
  241. package/dist/tools/definitions/getcourse-cold-welcome.js +180 -254
  242. package/dist/tools/definitions/getcourse-cold-welcome.js.map +1 -1
  243. package/dist/tools/definitions/getcourse-wave-welcome.messages.d.ts +10 -0
  244. package/dist/tools/definitions/getcourse-wave-welcome.messages.js +17 -0
  245. package/dist/tools/definitions/getcourse-wave-welcome.messages.js.map +1 -0
  246. package/dist/tools/definitions/help.js.map +1 -1
  247. package/dist/tools/definitions/icp-import-source.d.ts +75 -0
  248. package/dist/tools/definitions/icp-import-source.js +88 -0
  249. package/dist/tools/definitions/icp-import-source.js.map +1 -0
  250. package/dist/tools/definitions/inbound-analytics.d.ts +13 -0
  251. package/dist/tools/definitions/inbound-analytics.js +55 -0
  252. package/dist/tools/definitions/inbound-analytics.js.map +1 -0
  253. package/dist/tools/definitions/instagram-comment.templates.d.ts +19 -0
  254. package/dist/tools/definitions/instagram-comment.templates.js +34 -0
  255. package/dist/tools/definitions/instagram-comment.templates.js.map +1 -0
  256. package/dist/tools/definitions/instagram-settings-compat.d.ts +33 -0
  257. package/dist/tools/definitions/instagram-settings-compat.js +7 -0
  258. package/dist/tools/definitions/instagram-settings-compat.js.map +1 -0
  259. package/dist/tools/definitions/knowledge-chunking.d.ts +42 -0
  260. package/dist/tools/definitions/knowledge-chunking.js +83 -0
  261. package/dist/tools/definitions/knowledge-chunking.js.map +1 -0
  262. package/dist/tools/definitions/knowledge-space-search-fields.d.ts +12 -0
  263. package/dist/tools/definitions/knowledge-space-search-fields.js +30 -0
  264. package/dist/tools/definitions/knowledge-space-search-fields.js.map +1 -0
  265. package/dist/tools/definitions/knowledge.d.ts +24 -14
  266. package/dist/tools/definitions/knowledge.js +342 -233
  267. package/dist/tools/definitions/knowledge.js.map +1 -1
  268. package/dist/tools/definitions/legacy-trigger-repeat.d.ts +17 -0
  269. package/dist/tools/definitions/legacy-trigger-repeat.js +53 -0
  270. package/dist/tools/definitions/legacy-trigger-repeat.js.map +1 -0
  271. package/dist/tools/definitions/link-tracking.d.ts +8 -0
  272. package/dist/tools/definitions/link-tracking.js +141 -38
  273. package/dist/tools/definitions/link-tracking.js.map +1 -1
  274. package/dist/tools/definitions/mailing-variant-content.d.ts +75 -0
  275. package/dist/tools/definitions/mailing-variant-content.js +73 -0
  276. package/dist/tools/definitions/mailing-variant-content.js.map +1 -0
  277. package/dist/tools/definitions/model-comparison.d.ts +1 -0
  278. package/dist/tools/definitions/model-comparison.js +4 -5
  279. package/dist/tools/definitions/model-comparison.js.map +1 -1
  280. package/dist/tools/definitions/money-currency.d.ts +5 -0
  281. package/dist/tools/definitions/money-currency.js +10 -0
  282. package/dist/tools/definitions/money-currency.js.map +1 -0
  283. package/dist/tools/definitions/operator-workflow.d.ts +5 -5
  284. package/dist/tools/definitions/operator-workflow.js +80 -27
  285. package/dist/tools/definitions/operator-workflow.js.map +1 -1
  286. package/dist/tools/definitions/platform-funnel-analytics.d.ts +42 -0
  287. package/dist/tools/definitions/platform-funnel-analytics.js +72 -0
  288. package/dist/tools/definitions/platform-funnel-analytics.js.map +1 -0
  289. package/dist/tools/definitions/platform-getcourse-wave-field-bindings.d.ts +42 -0
  290. package/dist/tools/definitions/platform-getcourse-wave-field-bindings.js +51 -0
  291. package/dist/tools/definitions/platform-getcourse-wave-field-bindings.js.map +1 -0
  292. package/dist/tools/definitions/platform-settings-limits.d.ts +5 -0
  293. package/dist/tools/definitions/platform-settings-limits.js +6 -0
  294. package/dist/tools/definitions/platform-settings-limits.js.map +1 -0
  295. package/dist/tools/definitions/platform-settings-shipped-form.d.ts +37 -0
  296. package/dist/tools/definitions/platform-settings-shipped-form.js +310 -0
  297. package/dist/tools/definitions/platform-settings-shipped-form.js.map +1 -0
  298. package/dist/tools/definitions/platform-settings-update.d.ts +300 -0
  299. package/dist/tools/definitions/platform-settings-update.js +134 -0
  300. package/dist/tools/definitions/platform-settings-update.js.map +1 -0
  301. package/dist/tools/definitions/{getcourse-wave.d.ts → platform-setup-wave.d.ts} +75 -6
  302. package/dist/tools/definitions/platform-setup-wave.js +1079 -0
  303. package/dist/tools/definitions/platform-setup-wave.js.map +1 -0
  304. package/dist/tools/definitions/platform-setup.d.ts +686 -224
  305. package/dist/tools/definitions/platform-setup.js +313 -752
  306. package/dist/tools/definitions/platform-setup.js.map +1 -1
  307. package/dist/tools/definitions/platform-widget-page-rules.schema.d.ts +10 -0
  308. package/dist/tools/definitions/platform-widget-page-rules.schema.js +7 -0
  309. package/dist/tools/definitions/platform-widget-page-rules.schema.js.map +1 -0
  310. package/dist/tools/definitions/prompt-authoring.constants.d.ts +2 -0
  311. package/dist/tools/definitions/prompt-authoring.constants.js +3 -0
  312. package/dist/tools/definitions/prompt-authoring.constants.js.map +1 -0
  313. package/dist/tools/definitions/prompt-batch-controls.d.ts +5 -0
  314. package/dist/tools/definitions/prompt-batch-controls.js +40 -0
  315. package/dist/tools/definitions/prompt-batch-controls.js.map +1 -0
  316. package/dist/tools/definitions/prompt-draft-authoring.d.ts +5 -0
  317. package/dist/tools/definitions/prompt-draft-authoring.js +24 -0
  318. package/dist/tools/definitions/prompt-draft-authoring.js.map +1 -0
  319. package/dist/tools/definitions/prompt-text-projection.d.ts +11 -0
  320. package/dist/tools/definitions/prompt-text-projection.js +62 -0
  321. package/dist/tools/definitions/prompt-text-projection.js.map +1 -0
  322. package/dist/tools/definitions/reviewer-paid.d.ts +19 -0
  323. package/dist/tools/definitions/reviewer-paid.js +115 -0
  324. package/dist/tools/definitions/reviewer-paid.js.map +1 -0
  325. package/dist/tools/definitions/routing-condition-projection.d.ts +31 -0
  326. package/dist/tools/definitions/routing-condition-projection.js +97 -0
  327. package/dist/tools/definitions/routing-condition-projection.js.map +1 -0
  328. package/dist/tools/definitions/schedule-selection-hints.d.ts +3 -0
  329. package/dist/tools/definitions/schedule-selection-hints.js +42 -0
  330. package/dist/tools/definitions/schedule-selection-hints.js.map +1 -0
  331. package/dist/tools/definitions/{scheduled-tasks.d.ts → scheduled-task-alias.d.ts} +12 -10
  332. package/dist/tools/definitions/scheduled-task-alias.js +207 -0
  333. package/dist/tools/definitions/scheduled-task-alias.js.map +1 -0
  334. package/dist/tools/definitions/session.js +3 -3
  335. package/dist/tools/definitions/session.js.map +1 -1
  336. package/dist/tools/definitions/setup-init-operation.schema.d.ts +2 -0
  337. package/dist/tools/definitions/setup-init-operation.schema.js +6 -0
  338. package/dist/tools/definitions/setup-init-operation.schema.js.map +1 -0
  339. package/dist/tools/definitions/shared-input.helpers.d.ts +51 -0
  340. package/dist/tools/definitions/shared-input.helpers.js +323 -0
  341. package/dist/tools/definitions/shared-input.helpers.js.map +1 -0
  342. package/dist/tools/definitions/shared.d.ts +396 -307
  343. package/dist/tools/definitions/shared.js +430 -652
  344. package/dist/tools/definitions/shared.js.map +1 -1
  345. package/dist/tools/definitions/shipped-output-names.d.ts +19 -0
  346. package/dist/tools/definitions/shipped-output-names.js +123 -0
  347. package/dist/tools/definitions/shipped-output-names.js.map +1 -0
  348. package/dist/tools/definitions/task-state.d.ts +5 -5
  349. package/dist/tools/definitions/task-state.js +2 -1
  350. package/dist/tools/definitions/task-state.js.map +1 -1
  351. package/dist/tools/definitions/telegram-personal-capacity.d.ts +4 -0
  352. package/dist/tools/definitions/telegram-personal-capacity.js +18 -0
  353. package/dist/tools/definitions/telegram-personal-capacity.js.map +1 -0
  354. package/dist/tools/definitions/telegram-pool-policy.d.ts +8 -0
  355. package/dist/tools/definitions/telegram-pool-policy.js +56 -0
  356. package/dist/tools/definitions/telegram-pool-policy.js.map +1 -0
  357. package/dist/tools/definitions/touch-history-alias.d.ts +4 -0
  358. package/dist/tools/definitions/touch-history-alias.js +99 -0
  359. package/dist/tools/definitions/touch-history-alias.js.map +1 -0
  360. package/dist/tools/definitions/trigger-action-item.schema.d.ts +254 -0
  361. package/dist/tools/definitions/trigger-action-item.schema.js +121 -0
  362. package/dist/tools/definitions/trigger-action-item.schema.js.map +1 -0
  363. package/dist/tools/definitions/trigger-argument.schema.d.ts +14 -0
  364. package/dist/tools/definitions/trigger-argument.schema.js +23 -0
  365. package/dist/tools/definitions/trigger-argument.schema.js.map +1 -0
  366. package/dist/tools/definitions/trigger-claim-alias.d.ts +10 -0
  367. package/dist/tools/definitions/trigger-claim-alias.js +90 -0
  368. package/dist/tools/definitions/trigger-claim-alias.js.map +1 -0
  369. package/dist/tools/definitions/trigger-echo-projection.d.ts +1 -0
  370. package/dist/tools/definitions/trigger-echo-projection.js +41 -0
  371. package/dist/tools/definitions/trigger-echo-projection.js.map +1 -0
  372. package/dist/tools/definitions/trigger-upsert.tool.d.ts +29 -0
  373. package/dist/tools/definitions/trigger-upsert.tool.js +122 -0
  374. package/dist/tools/definitions/trigger-upsert.tool.js.map +1 -0
  375. package/dist/tools/definitions/v15-port-descriptions.d.ts +11 -0
  376. package/dist/tools/definitions/v15-port-descriptions.js +30 -0
  377. package/dist/tools/definitions/v15-port-descriptions.js.map +1 -0
  378. package/dist/tools/definitions/variables.d.ts +44 -0
  379. package/dist/tools/definitions/variables.js +310 -0
  380. package/dist/tools/definitions/variables.js.map +1 -0
  381. package/dist/tools/definitions/voice-action-input.d.ts +9 -0
  382. package/dist/tools/definitions/voice-action-input.js +141 -0
  383. package/dist/tools/definitions/voice-action-input.js.map +1 -0
  384. package/dist/tools/definitions/widget-customization-compat.d.ts +51 -0
  385. package/dist/tools/definitions/widget-customization-compat.js +23 -0
  386. package/dist/tools/definitions/widget-customization-compat.js.map +1 -0
  387. package/dist/tools/definitions.d.ts +1089 -636
  388. package/dist/tools/definitions.js +57 -27
  389. package/dist/tools/definitions.js.map +1 -1
  390. package/dist/tools/description-localization.js +3 -2
  391. package/dist/tools/description-localization.js.map +1 -1
  392. package/dist/tools/follow-up-request.d.ts +19 -0
  393. package/dist/tools/follow-up-request.js +81 -0
  394. package/dist/tools/follow-up-request.js.map +1 -0
  395. package/dist/tools/followup-revision.d.ts +4 -0
  396. package/dist/tools/followup-revision.js +29 -0
  397. package/dist/tools/followup-revision.js.map +1 -0
  398. package/dist/tools/incomplete-list.js +4 -0
  399. package/dist/tools/incomplete-list.js.map +1 -1
  400. package/dist/tools/inventory.js +47 -11
  401. package/dist/tools/inventory.js.map +1 -1
  402. package/dist/tools/operation-recovery.d.ts +4 -0
  403. package/dist/tools/operation-recovery.js +33 -0
  404. package/dist/tools/operation-recovery.js.map +1 -0
  405. package/dist/tools/registry-mapping-primary.cases.d.ts +2 -0
  406. package/dist/tools/registry-mapping-primary.cases.js +753 -0
  407. package/dist/tools/registry-mapping-primary.cases.js.map +1 -0
  408. package/dist/tools/registry-mapping-secondary.cases.d.ts +2 -0
  409. package/dist/tools/registry-mapping-secondary.cases.js +626 -0
  410. package/dist/tools/registry-mapping-secondary.cases.js.map +1 -0
  411. package/dist/tools/registry-mapping.cases.d.ts +8 -0
  412. package/dist/tools/registry-mapping.cases.js +13 -0
  413. package/dist/tools/registry-mapping.cases.js.map +1 -0
  414. package/dist/tools/registry-test-fixtures.d.ts +50 -0
  415. package/dist/tools/registry-test-fixtures.js +120 -0
  416. package/dist/tools/registry-test-fixtures.js.map +1 -0
  417. package/dist/tools/registry.d.ts +2 -0
  418. package/dist/tools/registry.js +82 -52
  419. package/dist/tools/registry.js.map +1 -1
  420. package/dist/tools/result.d.ts +1 -0
  421. package/dist/tools/result.js +90 -22
  422. package/dist/tools/result.js.map +1 -1
  423. package/dist/tools/toolsets.d.ts +16 -0
  424. package/dist/tools/toolsets.js +25 -1
  425. package/dist/tools/toolsets.js.map +1 -1
  426. package/dist/types/api-contract.gen.d.ts +105875 -22205
  427. package/dist/utils/credential-signatures.d.ts +3 -0
  428. package/dist/utils/credential-signatures.js +10 -0
  429. package/dist/utils/credential-signatures.js.map +1 -0
  430. package/dist/utils/data-source-column-name.d.ts +10 -0
  431. package/dist/utils/data-source-column-name.js +36 -0
  432. package/dist/utils/data-source-column-name.js.map +1 -0
  433. package/dist/utils/logger.d.ts +1 -0
  434. package/dist/utils/logger.js +32 -8
  435. package/dist/utils/logger.js.map +1 -1
  436. package/dist/utils/secret-read-boundary.d.ts +2 -0
  437. package/dist/utils/secret-read-boundary.js +88 -0
  438. package/dist/utils/secret-read-boundary.js.map +1 -0
  439. package/dist/utils/setup-secrets.d.ts +4 -0
  440. package/dist/utils/setup-secrets.js +40 -0
  441. package/dist/utils/setup-secrets.js.map +1 -0
  442. package/docs/agent-models.md +9 -0
  443. package/docs/agent-usage-guide.full.ru.md +1 -4
  444. package/docs/analytics-contract.md +67 -0
  445. package/docs/async-operation-lifecycle.md +10 -3
  446. package/docs/connect.ru.md +144 -4
  447. package/docs/contact-company-profile.md +17 -0
  448. package/docs/contact-recommendations.md +7 -0
  449. package/docs/crm-stage-pool.md +73 -0
  450. package/docs/customer-data.md +61 -0
  451. package/docs/edit-versions.md +36 -0
  452. package/docs/failure-semantics.md +17 -9
  453. package/docs/help-navigation.md +15 -42
  454. package/docs/host-compatibility-matrix.md +72 -93
  455. package/docs/host-setup.md +33 -35
  456. package/docs/invariants/public-api-and-contracts.md +16 -0
  457. package/docs/legacy-action-settings.md +21 -0
  458. package/docs/main-transfer-dependencies.md +38 -0
  459. package/docs/mcp2-parity.md +50 -0
  460. package/docs/modules/analytics.md +79 -0
  461. package/docs/modules/besales-mcp.md +137 -0
  462. package/docs/modules/dialog-review-report.md +38 -0
  463. package/docs/modules/dialogue-followup-adapters.md +39 -0
  464. package/docs/modules/message-reactions.md +17 -0
  465. package/docs/modules/network-mode.md +284 -0
  466. package/docs/modules/prompt-batch-and-dialogue-controls.md +69 -0
  467. package/docs/pii-policy.md +21 -16
  468. package/docs/response-size-budget.md +197 -7
  469. package/docs/secret-read-boundary.md +102 -0
  470. package/docs/task-state.md +7 -2
  471. package/docs/telegram-pool-policy.md +19 -0
  472. package/docs/tool-effects.md +15 -9
  473. package/docs/tool-surface.md +205 -4
  474. package/docs/voice-actions-and-inbox.md +95 -0
  475. package/docs/wazzup-instagram-comments.md +26 -0
  476. package/package.json +17 -10
  477. package/scripts/api-source-loader.spec.mjs +40 -0
  478. package/scripts/audit-bridge-controls.mjs +129 -0
  479. package/scripts/audit-revert-mutants.mjs +107 -0
  480. package/scripts/bridge-api-input.spec.mjs +98 -0
  481. package/scripts/bridge-controls-mutants.mjs +130 -0
  482. package/scripts/brx3-shipped-refusals.spec.mjs +149 -0
  483. package/scripts/brx4-ledger-payload.spec.mjs +127 -0
  484. package/scripts/build-onprem.mjs +108 -0
  485. package/scripts/connect-clients.sh +141 -0
  486. package/scripts/connect-scopes.mjs +166 -0
  487. package/scripts/connect-scopes.spec.mjs +83 -0
  488. package/scripts/emit-personal-link-carrier.mjs +31 -0
  489. package/scripts/emit-setup-init-schemas.mjs +24 -0
  490. package/scripts/emit-tool-routes.mjs +878 -0
  491. package/scripts/emit-tool-routes.spec.mjs +300 -0
  492. package/scripts/followup-registry.spec.mjs +107 -0
  493. package/scripts/generate-crm-rotation-contract.mjs +98 -0
  494. package/scripts/generate-followup-session-contract.mjs +16 -0
  495. package/scripts/icp-import-verification/mutate.cjs +70 -0
  496. package/scripts/import-secret-read-contract.mjs +53 -0
  497. package/scripts/install-claude-desktop.js +1 -1
  498. package/scripts/lag-decisions.mjs +37 -0
  499. package/scripts/lag-decisions.spec.mjs +87 -0
  500. package/scripts/lag-open-task-owners.mjs +46 -0
  501. package/scripts/lag-open-task-owners.spec.mjs +78 -0
  502. package/scripts/lag-payload.mjs +10 -0
  503. package/scripts/legacy-action-lag.spec.mjs +22 -0
  504. package/scripts/legacy-field-refusal.shipped.spec.mjs +99 -0
  505. package/scripts/mcpcompat-handler.mjs +34 -0
  506. package/scripts/mcpcompat-loader.mjs +36 -0
  507. package/scripts/mcpcompat-typescript.mjs +3 -0
  508. package/scripts/platform-settings-shipped-parity.spec.mjs +89 -0
  509. package/scripts/prbr-round1-recheck.spec.mjs +605 -0
  510. package/scripts/prbr-shipped-compatibility.spec.mjs +276 -0
  511. package/scripts/publish-mcp-registry.mjs +98 -0
  512. package/scripts/publish-mcp-registry.spec.mjs +68 -0
  513. package/scripts/record-scheduled-task-call.mjs +26 -0
  514. package/scripts/refusal-probe.mjs +17 -0
  515. package/scripts/refusal-probe.spec.mjs +29 -0
  516. package/scripts/registry-diff.mjs +502 -0
  517. package/scripts/registry-diff.spec.mjs +787 -0
  518. package/scripts/request-query.mjs +43 -0
  519. package/scripts/request-query.spec.mjs +82 -0
  520. package/scripts/route-lag.mjs +23 -0
  521. package/scripts/route-lag.spec.mjs +30 -0
  522. package/scripts/sample-args.mjs +174 -0
  523. package/scripts/sample-args.spec.mjs +160 -0
  524. package/scripts/shipped-definitions.mjs +197 -0
  525. package/scripts/shipped-definitions.spec.mjs +57 -0
  526. package/scripts/shipped-inputs.spec.mjs +136 -0
  527. package/scripts/shipped-recordings.spec.mjs +19 -0
  528. package/scripts/shipped-ref.d.mts +5 -0
  529. package/scripts/shipped-ref.mjs +20 -0
  530. package/scripts/shipped-ref.spec.mjs +59 -0
  531. package/scripts/shipped-registry.mjs +107 -0
  532. package/scripts/shipped-sample-candidates.mjs +69 -0
  533. package/scripts/shipped-sample-candidates.spec.mjs +117 -0
  534. package/scripts/shipped-sample.mjs +868 -0
  535. package/scripts/shipped-sample.spec.mjs +451 -0
  536. package/scripts/sync-agent-model-schemas.mjs +72 -0
  537. package/scripts/sync-api-contracts.mjs +85 -0
  538. package/scripts/sync-api-contracts.spec.mjs +144 -0
  539. package/scripts/sync-contract-ledger-schemas.mjs +161 -0
  540. package/scripts/sync-crm-stage-pool-schema.mjs +85 -0
  541. package/scripts/sync-prompt-draft-schema.mjs +92 -0
  542. package/scripts/sync-route-map.mjs +94 -0
  543. package/scripts/sync-schema-descriptions.mjs +25 -0
  544. package/scripts/sync-tool-inventory.mjs +27 -0
  545. package/scripts/sync-trigger-argument-schema.mjs +121 -0
  546. package/scripts/sync-trigger-repeat-mapping.mjs +12 -0
  547. package/scripts/sync-voice-actions-contract.mjs +67 -0
  548. package/scripts/sync-voice-actions-tools.mjs +97 -0
  549. package/scripts/sync-wave-id-schemas.mjs +55 -0
  550. package/scripts/tool-input-schemas.mjs +46 -0
  551. package/scripts/tool-input-schemas.spec.mjs +50 -0
  552. package/scripts/verify-followup-adapters.mjs +235 -0
  553. package/scripts/verify-secret-read-import.mjs +84 -0
  554. package/scripts/verify-secret-read-mutants.mjs +143 -0
  555. package/dist/tools/definitions/analytics.d.ts +0 -40
  556. package/dist/tools/definitions/analytics.js +0 -233
  557. package/dist/tools/definitions/analytics.js.map +0 -1
  558. package/dist/tools/definitions/broadcast-mailing-variants.d.ts +0 -41
  559. package/dist/tools/definitions/broadcast-mailing-variants.js +0 -194
  560. package/dist/tools/definitions/broadcast-mailing-variants.js.map +0 -1
  561. package/dist/tools/definitions/dialogue-audit.d.ts +0 -38
  562. package/dist/tools/definitions/dialogue-audit.js +0 -292
  563. package/dist/tools/definitions/dialogue-audit.js.map +0 -1
  564. package/dist/tools/definitions/getcourse-wave.js +0 -519
  565. package/dist/tools/definitions/getcourse-wave.js.map +0 -1
  566. package/dist/tools/definitions/operational-overview.d.ts +0 -3
  567. package/dist/tools/definitions/operational-overview.js +0 -23
  568. package/dist/tools/definitions/operational-overview.js.map +0 -1
  569. package/dist/tools/definitions/scheduled-tasks.js +0 -173
  570. package/dist/tools/definitions/scheduled-tasks.js.map +0 -1
  571. package/dist/tools/definitions/trigger-contact-claims.d.ts +0 -7
  572. package/dist/tools/definitions/trigger-contact-claims.js +0 -60
  573. package/dist/tools/definitions/trigger-contact-claims.js.map +0 -1
  574. package/dist/tools/registry-mapping-cases-core.d.ts +0 -38
  575. package/dist/tools/registry-mapping-cases-core.js +0 -963
  576. package/dist/tools/registry-mapping-cases-core.js.map +0 -1
  577. package/dist/tools/registry-mapping-cases-platform.d.ts +0 -2
  578. package/dist/tools/registry-mapping-cases-platform.js +0 -1052
  579. package/dist/tools/registry-mapping-cases-platform.js.map +0 -1
  580. package/dist/tools/trigger-action-config.d.ts +0 -49
  581. package/dist/tools/trigger-action-config.js +0 -171
  582. package/dist/tools/trigger-action-config.js.map +0 -1
  583. package/docs/evals/model-behavior-scorecard.md +0 -80
  584. package/docs/operation-coverage.md +0 -114
  585. package/scripts/mock-credentials.js +0 -77
  586. package/scripts/model-eval-server.js +0 -213
  587. package/scripts/run-model-eval.js +0 -447
@@ -1,11 +1,17 @@
1
- // Schemas, helpers, snake→camel mappers and the ToolDefinition contract
2
- // shared by all definition modules. Split out of the former monolithic
3
- // definitions.ts to keep each file under the 1200-line project limit.
1
+ import { compactObject } from './shared-input.helpers.js';
2
+ import { instagramCommentTemplatesSchema } from './instagram-comment.templates.js';
3
+ // Общие схемы, перевод snake→camel и контракт ToolDefinition отделены от общего списка определений: единая форма между модулями и ограничение размера каждого файла.
4
4
  import { z } from 'zod';
5
+ import { MESSAGE_FILTER_SOURCE_MAX_LENGTH, MESSAGE_FILTER_TARGET_MAX_LENGTH, } from '../../shared/constants/message-filter.constants.js';
6
+ import { platformGetcourseWaveFieldBindingsSchema } from './platform-getcourse-wave-field-bindings.js';
7
+ import { PLATFORM_FINISH_AUTO_MAX_DAYS } from './platform-settings-limits.js';
8
+ import { platformWidgetPageRulesSchema } from './platform-widget-page-rules.schema.js';
5
9
  export const uuidSchema = z.string().uuid();
10
+ /** Preserved knowledge-space IDs keep hex 8-4-4-4-12 without RFC version/variant constraints. */
11
+ export const knowledgeSpaceIdSchema = z.guid().meta({ format: 'uuid' });
6
12
  export const anyObjectSchema = z.object({}).passthrough();
7
13
  export const optionalAnyObjectSchema = anyObjectSchema.optional();
8
- export const outcomeSchema = z.enum(['won', 'lost', 'in_progress']);
14
+ export const outcomeSchema = z.enum(['won', 'lost', 'in_progress', 'unknown']);
9
15
  export const platformSetupConfirmationSchema = {
10
16
  explicit_confirmation: z.boolean().optional(),
11
17
  confirmation_reason: z.string().optional(),
@@ -20,12 +26,26 @@ export const PROMPT_DIFF_MAX_LINES_LIMIT = 1000;
20
26
  * Больший `limit` сервер отвергнет валидацией, поэтому граница объявлена и здесь.
21
27
  */
22
28
  export const VARIABLES_MAX_PAGE_SIZE = 200;
23
- /** Максимальный размер явно запрошенной страницы списка агентов платформы. */
24
- export const PLATFORM_AGENTS_MAX_PAGE_SIZE = 200;
29
+ /**
30
+ * Верхняя граница страницы перечня агентов канала — совпадает с `CHANNEL_AGENTS_LIST_MAX_LIMIT`
31
+ * бэкенда. Умолчания у самой ручки нет: без `limit` перечень приходит целиком.
32
+ */
33
+ export const CHANNEL_AGENTS_MAX_PAGE_SIZE = 200;
34
+ /** Верхняя граница страницы сценариев ICP — совпадает с `ICP_SCENARIOS_LIST_MAX_LIMIT` бэкенда. */
35
+ export const ICP_SCENARIOS_MAX_PAGE_SIZE = 200;
36
+ /** Верхняя граница страницы воронок и стадий — совпадает с `CRM_PIPELINES_LIST_MAX_LIMIT` бэкенда. */
37
+ export const CRM_PIPELINES_MAX_PAGE_SIZE = 200;
38
+ /** Верхняя граница страницы цепочек дожима — совпадает с `FOLLOWUP_SEQUENCES_LIST_MAX_LIMIT`. */
39
+ export const FOLLOWUP_SEQUENCES_MAX_PAGE_SIZE = 200;
25
40
  /** Потолок агентов в одном пакетном прогоне — должен совпадать с `PROMPT_BATCH_MAX_AGENTS`. */
26
41
  export const PROMPT_BATCH_MAX_AGENTS = 200;
27
42
  /** Длина ключа идемпотентности пакетного прогона — должна совпадать с DTO бэкенда. */
28
43
  export const PROMPT_BATCH_IDEMPOTENCY_KEY_MAX_LENGTH = 200;
44
+ /**
45
+ * Потолок срока доверия ответу школы (сутки). Совпадает с сервером: иначе мост пропустил бы
46
+ * значение, которое сервер отвергает, либо наоборот.
47
+ */
48
+ export const GETCOURSE_REACHABILITY_TTL_DAYS_MAX = 365;
29
49
  /**
30
50
  * Одна patch-операция промпта. Общая для `besales_prompt_patch_apply` и
31
51
  * `besales_prompt_batch_start`: две копии разъехались бы при добавлении нового типа.
@@ -85,9 +105,8 @@ export const apiKeyPlatformTypeSchema = z.enum([
85
105
  ]);
86
106
  // v1.5 Increment 5b Phase 2 — OAuth-каналы (авторизация в браузере, код мимо LLM).
87
107
  export const oauthPlatformTypeSchema = z.enum(['Instagram', 'Avito']);
88
- // v1.5 Increment 5c — CRM provisioning через Setup URL pattern (секреты в браузере).
89
- // GETCOURSE/TELEGRAM — API-key; AMOCRM/BITRIX24 — вставка credentials (5c Phase 2, не OAuth-redirect).
90
- export const provisionableCrmTypeSchema = z.enum(['GETCOURSE', 'TELEGRAM', 'AMOCRM', 'BITRIX24']);
108
+ // CRM provisioning через Setup URL pattern: секреты вводятся только в браузере.
109
+ export const provisionableCrmTypeSchema = z.enum(['GETCOURSE', 'AMOCRM', 'BITRIX24']);
91
110
  export const fieldSpecialPurposeSchema = z.enum([
92
111
  'phone',
93
112
  'telegramId',
@@ -177,18 +196,33 @@ export const icpAnalysisPersonaSchema = z
177
196
  /**
178
197
  * Машинные ожидания реплики: что раннер песочницы обязан увидеть в ответе агента на неё.
179
198
  *
180
- * ⚠️ Без этой схемы поле не просто «не валидируется», а ИСЧЕЗАЕТ: zod стрипает неизвестные ключи
181
- * молча, и ожидания не доехали бы до backend вовсе. Вторая точка потери — маппинг сабмита, где
182
- * реплики пересобираются по явному списку полей.
199
+ * ⚠️ Без схемы поле не просто «не проверяется», а ИСЧЕЗАЕТ: zod молча срезает неизвестные ключи,
200
+ * и рубрика не доехала бы до сервера вовсе. Вторая точка потери — сборка тела отправки, где
201
+ * реплики пересобираются по явному списку полей: там `expect` перечислен отдельно.
202
+ *
203
+ * ⛔ Принимаются ровно ТРИ правила — те, что сервер открывает генератору сценариев
204
+ * (`GENERATED_SCENARIO_EXPECTATION_KEYS`, `additionalProperties: false`): два по тексту ответа и
205
+ * запрет ранней передачи оператору, у которого единственная цель — `call_operator` (песочница
206
+ * проверяет его по сработавшему действию с шагом передачи). Идентификаторов действий и имён
207
+ * инструментов генератор не знает, и выдуманная цель краснела бы на исправном агенте: правила по
208
+ * действиям ставит оператор. Хранилище сервера знает ШЕСТЬ имён — это реестр ХРАНЕНИЯ, а не то,
209
+ * что сервер показывает пишущей стороне.
210
+ *
211
+ * ⚠️ Отгруженный клиент объявляет все шесть, и сервер их принимает; сужение здесь повторяет
212
+ * контракт генератора, а не обещает модели цели, которых она не знает.
183
213
  */
184
- export const scenarioTurnExpectationSchema = z.object({
185
- triggers: z.array(z.string().min(1)).optional(),
186
- noTriggers: z.array(z.string().min(1)).optional(),
187
- tools: z.array(z.string().min(1)).optional(),
188
- noTools: z.array(z.string().min(1)).optional(),
214
+ export const scenarioTurnExpectationSchema = z
215
+ .object({
216
+ noTools: z
217
+ .array(z.enum(['call_operator']))
218
+ .min(1)
219
+ .optional(),
189
220
  answerContains: z.array(z.string().min(1)).optional(),
190
221
  answerNotContains: z.array(z.string().min(1)).optional(),
191
- });
222
+ })
223
+ // ⛔ Строгая: незнакомое правило отвергается С ИМЕНЕМ, а не срезается молча. Молчаливое срезание
224
+ // и есть тот случай, когда пишущая сторона считает правило заданным, а проверять его некому.
225
+ .strict();
192
226
  export const scenarioSituationSchema = z.object({
193
227
  role: z.enum(['client', 'agent']),
194
228
  text: z.string().min(1).max(4000),
@@ -209,7 +243,21 @@ export const generatedScenarioSchema = z
209
243
  ...rest,
210
244
  segment_ids: segment_ids ?? segmentIds,
211
245
  }));
212
- export const sandboxFindingSchema = z.object({
246
+ /**
247
+ * Находка песочницы — КАНОН сервера, а не прежняя форма ветки v2.
248
+ *
249
+ * ⛔ Рубрика — РОВНО семь категорий отгруженного контракта. `missed_trigger` убрана: сервер её
250
+ * отвергает, то есть ветка v2 предлагала модели категорию, на которой вызов падал целиком.
251
+ * `missed_context` добавлена — она в каноне и была недостижима. Прежняя `wrong_pipeline_transition`
252
+ * НЕ рекламируется сознательно: сервер её принимает ради уже сохранённых находок, но его задание
253
+ * называет модели семь категорий, и предлагать восьмую значило бы спорить с этим решением.
254
+ *
255
+ * ⛔ Текст находки называется `description`; прежнее имя `message` принимается тоже, потому что
256
+ * им пользуется отгруженный клиент, стоящий у людей сейчас. Требуется РОВНО ОДНО из двух: без
257
+ * этого правила находка без текста уходила бы на сервер пустой.
258
+ */
259
+ export const sandboxFindingSchema = z
260
+ .object({
213
261
  scenario_id: uuidSchema.optional(),
214
262
  scenarioId: uuidSchema.optional(),
215
263
  category: z.enum([
@@ -229,8 +277,9 @@ export const sandboxFindingSchema = z.object({
229
277
  suggestion: z.string().optional(),
230
278
  turn_index: z.number().int().optional(),
231
279
  turnIndex: z.number().int().optional(),
232
- }).refine((finding) => finding.description !== undefined || finding.message !== undefined, {
233
- message: 'description is required',
280
+ })
281
+ .refine((finding) => finding.description !== undefined || finding.message !== undefined, {
282
+ message: 'Находка обязана нести текст: description (канон) либо message (прежнее имя)',
234
283
  path: ['description'],
235
284
  });
236
285
  export const simulationFindingSchema = z.object({
@@ -260,11 +309,11 @@ export const routingRuleLeadStatusSchema = z.object({
260
309
  // Одно условие правила роутинга «по значению переменной» (CUSTOM_VARIABLE).
261
310
  // Одно правило = N условий, объединяемых condition_logic (ALL=И / ANY=ИЛИ).
262
311
  // Внутри условия значения объединяются по ИЛИ (variable_values) — вместе с condition_logic=ALL
263
- // это даёт «И из ИЛИ»: AI_TOPIC ∈ [дбо] AND WAVE_SEGMENT ∈ [post-web, post-web-2].
264
- // variable_value — legacy-форма на одно значение; ровно одна из двух форм на условие.
265
- // Обе формы принимаются вместе, если СОГЛАСОВАНЫ (скаляр = первое значение набора): ответ API и
266
- // besales_platform_context_get отдают оба поля, поэтому клиент «прочитал → поправил → отправил»
267
- // естественно шлёт оба. Жёсткий XOR ломал бы обычный сценарий правки. Противоречие — отказ.
312
+ // это даёт «И из ИЛИ»: тема ∈ [дбо] AND сегмент ∈ [post-web, post-web-2].
313
+ // variable_value — форма на одно значение; ровно одна из двух форм на условие обязательна.
314
+ // Обе формы принимаются вместе, если СОГЛАСОВАНЫ (скаляр = первое значение набора): ответ API
315
+ // отдаёт оба поля, поэтому клиент «прочитал → поправил → отправил» естественно шлёт оба.
316
+ // Жёсткий выбор одной формы ломал бы обычный сценарий правки. Противоречие — отказ.
268
317
  export const routingRuleConditionSchema = z
269
318
  .object({
270
319
  custom_variable_id: z.string().uuid(),
@@ -276,9 +325,14 @@ export const routingRuleConditionSchema = z
276
325
  })
277
326
  .refine((cond) => cond.variable_values === undefined ||
278
327
  cond.variable_value === undefined ||
279
- cond.variable_values[0]?.trim().toLowerCase() === cond.variable_value.trim().toLowerCase(), {
280
- message: 'variable_value не совпадает с variable_values[0]. Присылайте одну форму либо согласованные',
328
+ // Сравнение идёт с первым НЕПУСТЫМ элементом — тем же, который останется набором после
329
+ // чистки на стороне API. Иначе мост отвергал бы форму, которую API принимает.
330
+ firstMeaningfulValue(cond.variable_values) === cond.variable_value.trim().toLowerCase(), {
331
+ message: 'variable_value не совпадает с первым значением variable_values. Присылайте одну форму либо согласованные',
281
332
  });
333
+ function firstMeaningfulValue(values) {
334
+ return values.map((value) => value.trim().toLowerCase()).find((value) => value !== '');
335
+ }
282
336
  export const agentToolPatchSchema = z.object({
283
337
  tool_id: z.string(),
284
338
  priority: z.number().int().min(1).max(100).optional(),
@@ -303,9 +357,7 @@ export const agentRuntimeConfigSchema = z.object({
303
357
  qa_min_score: z.number().min(0).max(1).optional(),
304
358
  qa_context_limit: z.number().int().min(1).max(10).optional(),
305
359
  max_response_symbols: z.number().int().min(1).optional(),
306
- reasoning_effort: z
307
- .enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'])
308
- .optional(),
360
+ reasoning_effort: z.enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']).optional(),
309
361
  verbosity: z.enum(['low', 'medium', 'high']).optional(),
310
362
  enable_thinking: z.boolean().optional(),
311
363
  timezone: z.string().optional(),
@@ -338,79 +390,172 @@ export const agentScopeSchema = z.enum([
338
390
  'complaint',
339
391
  'other',
340
392
  ]);
341
- // Behavior typed sections (Group C.1)
342
- export const behaviorGreetingButtonSchema = z.object({
393
+ // Behavior typed sections — КАНОН v2 (spec 02 § 5.2).
394
+ //
395
+ // ⛔ Имена полей = имена Zod-схем секций besales-api, а не отгруженные имена v1.5. Причина не в
396
+ // чистоте: у части полей вместе с именем сменилась ЕДИНИЦА (задержки уехали из секунд в
397
+ // миллисекунды), и сохрани мы старое имя — оператор, задавший 10, получил бы десять миллисекунд
398
+ // вместо десяти секунд, молча и без единой ошибки.
399
+ //
400
+ // ⛔ Все поля НЕОБЯЗАТЕЛЬНЫ, потому что сервер сливает присланное с текущим значением секции.
401
+ // Обязательность зеркалить нельзя: она запретила бы правку одного поля — то самое, ради чего
402
+ // инструмент и существует.
403
+ //
404
+ // ⛔ `schema_version` принимается, но перезаписывается: снимок из besales_platform_context_get его
405
+ // СОДЕРЖИТ, и строгая схема без этого поля отвергла бы собственный же прочитанный снимок.
406
+ const behaviorSchemaVersion = { schema_version: z.literal(1).optional() };
407
+ export const behaviorGreetingButtonSchema = z
408
+ .object({
343
409
  id: z.string(),
344
410
  label: z.string(),
345
411
  text: z.string(),
346
412
  order: z.number().int(),
347
- });
348
- export const behaviorGreetingSchema = z.object({
349
- bot_greeting: z.string().optional(),
350
- greeting_file_id: uuidSchema.nullable().optional(),
351
- greeting_buttons: z.array(behaviorGreetingButtonSchema).optional(),
352
- greeting_buttons_keyboard_type: z.enum(['INLINE', 'REPLY']).optional(),
413
+ })
414
+ .strict();
415
+ export const behaviorGreetingSchema = z
416
+ .object({
417
+ ...behaviorSchemaVersion,
418
+ text: z.string().optional(),
419
+ // null очищает картинку приветствия: сервер удаляет ключ, а не пишет пустоту.
420
+ file_id: z.string().nullable().optional(),
421
+ buttons: z.array(behaviorGreetingButtonSchema).optional(),
422
+ keyboard_type: z.enum(['INLINE', 'REPLY']).optional(),
353
423
  popup_delay_seconds: z.number().int().min(0).optional(),
354
- });
355
- /**
356
- * Набор стратегий у каждого типа вложения свой. `PROCESS_WITH_LLM` разбирает вложение
357
- * по-разному: image → vision-модель, video → подпись как текст, document → извлечённый текст
358
- * файла. У аудио такого значения на бэкенде нет вовсе, и запрос отвергается 400. Общая схема
359
- * на все четыре типа предлагала значение везде, из-за чего агент слал заведомо невалидный
360
- * payload (прод, 2026-08-10).
361
- */
362
- const mediaHandlerCommonFields = {
363
- fixed_response_text: z.string().optional(),
424
+ // Отдаёт ли канал offMessage, когда ИИ выключен. Поле есть в v2 и у него живой читатель;
425
+ // у отгруженного инструмента его не было вовсе.
426
+ send_off_message_when_ai_disabled: z.boolean().optional(),
427
+ })
428
+ .strict();
429
+ const behaviorMediaHandlerFields = {
430
+ fixed_response_text: z.string().nullable().optional(),
364
431
  call_operator: z.boolean().optional(),
365
- operator_comment: z.string().optional(),
432
+ operator_comment: z.string().nullable().optional(),
366
433
  };
367
- export const behaviorMediaHandlerSchema = z.object({
368
- behavior: z.enum(['SILENT', 'PROCESS_WITH_LLM', 'FIXED_RESPONSE']),
369
- ...mediaHandlerCommonFields,
370
- });
371
- export const behaviorPlainMediaHandlerSchema = z.object({
372
- behavior: z.enum(['SILENT', 'FIXED_RESPONSE']),
373
- ...mediaHandlerCommonFields,
374
- });
375
- export const behaviorMediaHandlingSchema = z.object({
434
+ /**
435
+ * Обработчик вложения, у которого есть разбор моделью: картинка (кадр уходит зрячей модели),
436
+ * видео (в модель уходит подпись) и документ (в модель уходит ИЗВЛЕЧЁННЫЙ ТЕКСТ, сам файл — нет).
437
+ *
438
+ * ⚠️ У картинки и документа `PROCESS_WITH_LLM` означает: воркспейс соглашается отправлять в модель
439
+ * содержимое присланных файлов, включая персональные данные ТРЕТЬИХ ЛИЦ. Обезличивание подменяет
440
+ * известные значения контакта и распознаёт имена и контакты эвристикой, но полноты на содержимом
441
+ * чужого файла не гарантирует. Поэтому включение требует `explicit_confirmation`.
442
+ */
443
+ export const behaviorMediaHandlerSchema = z
444
+ .object({
445
+ behavior: z.enum(['SILENT', 'PROCESS_WITH_LLM', 'FIXED_RESPONSE']).optional(),
446
+ ...behaviorMediaHandlerFields,
447
+ })
448
+ .strict();
449
+ /**
450
+ * Обработчик вложения БЕЗ разбора моделью — сегодня это только звук.
451
+ *
452
+ * ⛔ Отдельная схема, а не общая: разбирать в аудиофайле нечего (голосовые обрабатывает
453
+ * распознавание речи), и общий набор значений заставлял бы агента слать заведомо невалидный
454
+ * запрос — сервер отвергает `PROCESS_WITH_LLM` у звука своей схемой.
455
+ */
456
+ export const behaviorPlainMediaHandlerSchema = z
457
+ .object({
458
+ behavior: z.enum(['SILENT', 'FIXED_RESPONSE']).optional(),
459
+ ...behaviorMediaHandlerFields,
460
+ })
461
+ .strict();
462
+ export const behaviorMediaHandlingSchema = z
463
+ .object({
464
+ ...behaviorSchemaVersion,
376
465
  image: behaviorMediaHandlerSchema.optional(),
377
466
  video: behaviorMediaHandlerSchema.optional(),
378
467
  audio: behaviorPlainMediaHandlerSchema.optional(),
379
468
  document: behaviorMediaHandlerSchema.optional(),
380
- });
381
- export const behaviorUrlHandlingSchema = z.object({
382
- behavior: z.enum(['PASS_THROUGH', 'SILENT', 'FIXED_RESPONSE', 'PROCESS_WITH_CRAWLER']),
383
- fixed_response_text: z.string().optional(),
469
+ })
470
+ .strict();
471
+ export const behaviorUnsupportedInputHandlingSchema = z
472
+ .object({
473
+ ...behaviorSchemaVersion,
474
+ behavior: z.enum(['SILENT', 'AS_TEXT', 'FIXED_RESPONSE']).optional(),
475
+ fixed_response_text: z.string().nullable().optional(),
476
+ call_operator: z.boolean().optional(),
477
+ operator_comment: z.string().nullable().optional(),
478
+ })
479
+ .strict();
480
+ export const behaviorUrlHandlingSchema = z
481
+ .object({
482
+ ...behaviorSchemaVersion,
483
+ behavior: z
484
+ .enum(['PASS_THROUGH', 'SILENT', 'FIXED_RESPONSE', 'PROCESS_WITH_CRAWLER'])
485
+ .optional(),
486
+ fixed_response_text: z.string().nullable().optional(),
384
487
  call_operator: z.boolean().optional(),
385
- operator_comment: z.string().optional(),
488
+ operator_comment: z.string().nullable().optional(),
386
489
  use_youtube_data_api: z.boolean().optional(),
387
- });
388
- export const behaviorErrorHandlingSchema = z.object({
490
+ })
491
+ .strict();
492
+ export const behaviorErrorHandlingSchema = z
493
+ .object({
494
+ ...behaviorSchemaVersion,
389
495
  ai_error_behavior: z.enum(['SILENT', 'SEND_ERROR_MESSAGE']).optional(),
390
- ai_error_custom_message: z.string().optional(),
391
- call_operator_with_error: z.boolean().optional(),
392
- ai_error_target_stage_id: z.number().int().nullable().optional(),
393
- });
394
- export const behaviorDayAvailabilitySchema = z.object({
496
+ custom_message: z.string().nullable().optional(),
497
+ call_operator: z.boolean().optional(),
498
+ // Цель сбоя модели: пара «воронка + статус» либо статус без воронки — «стадия с этим кодом в текущей воронке
499
+ // сделки» (так понимала номер прежняя система). null снимает цель.
500
+ ai_error_target: z
501
+ .object({ pipeline_id: z.string().min(1).optional(), status_id: z.string().min(1) })
502
+ .strict()
503
+ .nullable()
504
+ .optional(),
505
+ // Прежнее поле отгруженного моста — номер стадии прежней системы. Переводит его в цель СЕРВЕР (по каталогу
506
+ // подключения CRM канала; неоднозначность и неизвестный номер — отказ с адресом поля); null или 0 снимает цель.
507
+ // Вместе с ai_error_target не присылается.
508
+ ai_error_target_stage_id: z.number().int().nonnegative().nullable().optional(),
509
+ })
510
+ .strict();
511
+ /**
512
+ * ⛔ У РАБОЧЕГО дня обязательны ОБА времени и строго в формате `HH:MM`. Схема хранения приняла бы
513
+ * и `active: true` без времён, и запись вида `9:00` — а читатель расписания на таком дне считает
514
+ * НЕСТРОГИМ всё расписание целиком и объявляет оператора доступным ВСЕГДА. То есть один
515
+ * неаккуратный день молча выключает расписание на всю неделю, без ошибки и без предупреждения.
516
+ */
517
+ export const behaviorDayAvailabilitySchema = z
518
+ .object({
395
519
  active: z.boolean(),
396
- start_time: z.string().optional(),
397
- end_time: z.string().optional(),
398
- });
399
- export const behaviorWeekAvailabilitySchema = z.object({
400
- monday: behaviorDayAvailabilitySchema.optional(),
401
- tuesday: behaviorDayAvailabilitySchema.optional(),
402
- wednesday: behaviorDayAvailabilitySchema.optional(),
403
- thursday: behaviorDayAvailabilitySchema.optional(),
404
- friday: behaviorDayAvailabilitySchema.optional(),
405
- saturday: behaviorDayAvailabilitySchema.optional(),
406
- sunday: behaviorDayAvailabilitySchema.optional(),
520
+ start_time: z
521
+ .string()
522
+ .regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/u)
523
+ .optional(),
524
+ end_time: z
525
+ .string()
526
+ .regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/u)
527
+ .optional(),
528
+ })
529
+ .strict()
530
+ .refine((day) => !day.active || (day.start_time !== undefined && day.end_time !== undefined), {
531
+ message: 'у рабочего дня обязательны start_time и end_time в формате HH:MM',
407
532
  });
408
- export const behaviorOperatorScheduleSchema = z.object({
533
+ /**
534
+ * ⛔ Ключи дня пришпилены к канону `MON..SUN`. Хранилище приняло бы ЛЮБУЮ строку
535
+ * (`z.record(z.string(), …)`), а читатель при чужом ключе объявляет оператора доступным ВСЕГДА —
536
+ * то есть расписание, выставленное с ключами `monday…sunday`, молча не работало бы: ни ошибки,
537
+ * ни предупреждения, ни строки в логе.
538
+ */
539
+ export const behaviorWeekAvailabilitySchema = z
540
+ .object({
541
+ MON: behaviorDayAvailabilitySchema.optional(),
542
+ TUE: behaviorDayAvailabilitySchema.optional(),
543
+ WED: behaviorDayAvailabilitySchema.optional(),
544
+ THU: behaviorDayAvailabilitySchema.optional(),
545
+ FRI: behaviorDayAvailabilitySchema.optional(),
546
+ SAT: behaviorDayAvailabilitySchema.optional(),
547
+ SUN: behaviorDayAvailabilitySchema.optional(),
548
+ })
549
+ .strict();
550
+ export const behaviorOperatorScheduleSchema = z
551
+ .object({
552
+ ...behaviorSchemaVersion,
409
553
  enabled: z.boolean().optional(),
410
554
  availability: behaviorWeekAvailabilitySchema.optional(),
411
- unavailable_message: z.string().optional(),
412
- // -1 — ответ оператора не отключает бота, 0 — молчать до /start, далее часы паузы.
413
- bot_waiting_return_hours: z.union([
555
+ unavailable_message: z.string().nullable().optional(),
556
+ // -1 — ответ оператора НЕ отключает бота; 0 — молчать до /start; далее часы паузы.
557
+ bot_waiting_return_hours: z
558
+ .union([
414
559
  z.literal(-1),
415
560
  z.literal(0),
416
561
  z.literal(1),
@@ -418,32 +563,81 @@ export const behaviorOperatorScheduleSchema = z.object({
418
563
  z.literal(6),
419
564
  z.literal(12),
420
565
  z.literal(24),
421
- ]).optional(),
422
- follow_up_waiting_return_hours: z.number().int().optional(),
423
- skip_task_creation_on_call_operator: z.boolean().optional(),
424
- });
425
- export const behaviorTypingBehaviorSchema = z.object({
566
+ ])
567
+ .optional(),
568
+ followup_waiting_return_hours: z.number().int().optional(),
569
+ // Замолкает ли агент после реплики живого оператора. Отсутствие поля означает КАНОН
570
+ // «замолкать», поэтому выключение требует `explicit_confirmation`.
571
+ pause_agent_on_operator_reply: z.boolean().optional(),
572
+ })
573
+ .strict();
574
+ export const behaviorTypingBehaviorSchema = z
575
+ .object({
576
+ ...behaviorSchemaVersion,
577
+ typing_speed: z.enum(['slow', 'medium', 'fast', 'instant']).optional(),
426
578
  waiting_answer_time: z.number().int().min(0).optional(),
427
579
  can_interrupt: z.boolean().optional(),
428
- message_devide: z.boolean().optional(),
429
- typing_speed: z.enum(['slow', 'medium', 'fast']).optional(),
430
- fake_delay: z.number().int().min(0).optional(),
431
- message_open_delay: z.number().int().min(0).optional(),
432
- go_offline: z.string().optional(),
433
- });
434
- export const behaviorMessageFilterSchema = z.object({
580
+ // ⚠️ Секунды v1.5 стали МИЛЛИСЕКУНДАМИ — единица видна в имени намеренно.
581
+ fake_delay_ms: z.number().int().min(0).optional(),
582
+ message_open_delay_ms: z.number().int().min(0).optional(),
583
+ })
584
+ .strict();
585
+ export const behaviorMessageFilterSchema = z
586
+ .object({
435
587
  id: z.string(),
436
- source: z.string(),
437
- target: z.string(),
588
+ // Границы зеркалят схему хранения.
589
+ source: z.string().min(1).max(MESSAGE_FILTER_SOURCE_MAX_LENGTH),
590
+ target: z.string().max(MESSAGE_FILTER_TARGET_MAX_LENGTH),
438
591
  enabled: z.boolean(),
439
592
  order: z.number().int(),
440
- });
441
- export const behaviorMessageSplittingSchema = z.object({
442
- message_chunk_separator: z.string().optional(),
443
- });
444
- export const behaviorPrivacySchema = z.object({
593
+ })
594
+ .strict();
595
+ export const behaviorMessageFiltersSchema = z
596
+ .object({
597
+ ...behaviorSchemaVersion,
598
+ // Переехало из расписания оператора: в v2 признак живёт здесь.
599
+ skip_task_creation_on_call_operator: z.boolean().optional(),
600
+ rules: z.array(behaviorMessageFilterSchema).optional(),
601
+ })
602
+ .strict();
603
+ export const behaviorMessageSplittingSchema = z
604
+ .object({
605
+ ...behaviorSchemaVersion,
606
+ // Переехало из «печатает»: в v1.5 это было `message_devide`.
607
+ enabled: z.boolean().optional(),
608
+ mode: z.enum(['PARAGRAPH', 'SEPARATOR']).optional(),
609
+ separator: z.string().optional(),
610
+ // Максимум означает «не дробить дополнительно»: у v1.5 отдельного предела не было.
611
+ // Границы зеркалят схему хранения.
612
+ max_chunk_size: z.number().int().min(100).max(100_000).optional(),
613
+ delay_between_ms: z.number().int().min(0).max(60_000).optional(),
614
+ })
615
+ .strict();
616
+ /**
617
+ * CRM-поведение канала в инструменте поведения — только входящий фильтр по сделке GetCourse («бот отвечает только
618
+ * тем, у кого есть подходящая сделка»). Раздел СЛИВАЕТСЯ с сохранённым CRM-поведением канала; у канала без привязанной
619
+ * CRM сливать не с чем, и сервер ответит отказом с перечнем недостающих полей. Полноту включённого фильтра и
620
+ * подтверждение смены включённости и типа держит сервер.
621
+ */
622
+ export const behaviorCrmSchema = z
623
+ .object({
624
+ ...behaviorSchemaVersion,
625
+ inbound_deal_filter: z
626
+ .object({
627
+ enabled: z.boolean(),
628
+ type: z.enum(['NONE', 'TAG', 'CUSTOM_FIELD']),
629
+ value: z.string().nullable().optional(),
630
+ field_id: z.string().nullable().optional(),
631
+ })
632
+ .strict()
633
+ .optional(),
634
+ })
635
+ .strict();
636
+ export const behaviorPrivacySchema = z
637
+ .object({
638
+ ...behaviorSchemaVersion,
445
639
  anonymization_enabled: z.boolean().optional(),
446
- contact_name_personalization_mode: z.enum(['OFF', 'SHADOW', 'ENABLED']).optional(),
640
+ personalization_mode: z.enum(['OFF', 'SHADOW', 'ENABLED']).optional(),
447
641
  // Типы PII, выключенные из анонимизации (отдаются в LLM как есть).
448
642
  // Именные типы всегда защищены и не входят в OFF-список.
449
643
  anonymization_disabled_types: z
@@ -461,7 +655,8 @@ export const behaviorPrivacySchema = z.object({
461
655
  'SOCIAL_ID',
462
656
  ]))
463
657
  .optional(),
464
- });
658
+ })
659
+ .strict();
465
660
  // Pipeline settings typed sections (Group C.3)
466
661
  export const pipelineCrmBehaviorSchema = z.object({
467
662
  active_pipeline_ids: z.array(z.string()).optional(),
@@ -473,19 +668,19 @@ export const pipelineCrmBehaviorSchema = z.object({
473
668
  export const pipelineAutoFinishSchema = z.object({
474
669
  finish_auto_noanswer: z.boolean().optional(),
475
670
  finish_auto_timeout: z.boolean().optional(),
476
- finish_auto_days: z.number().int().min(1).optional(),
671
+ finish_auto_days: z.number().int().min(1).max(PLATFORM_FINISH_AUTO_MAX_DAYS).optional(),
477
672
  send_finish_auto_note_to_crm: z.boolean().optional(),
478
673
  finish_auto_note_template: z.string().nullable().optional(),
479
674
  });
480
675
  // Platform settings typed sections (Group C.2 + Increment 4c per-channel)
676
+ /**
677
+ * Кто из людей вообще доходит до агента.
678
+ *
679
+ * ⛔ Выключатели канала и ответов агента (`is_active`, `is_ai_enabled`) СЮДА НЕ ВХОДЯТ — их дом
680
+ * `general_settings`. Отсюда приёмник их не принимает и отвечал отказом на весь запрос.
681
+ */
481
682
  export const platformAccessControlSchema = z
482
683
  .object({
483
- // У Instagram это НАМЕРЕНИЕ держать канал включённым, а не факт работы: эффективная
484
- // активность = намерение И подтверждённая подписка на вебхуки. Прочитав `is_active` обратно
485
- // через `besales_platform_context_get`, можно увидеть `false` при успешно сохранённом `true` —
486
- // это не отказ операции, а неподтверждённая подписка (лечится resubscribe).
487
- is_active: z.boolean().optional(),
488
- is_ai_enabled: z.boolean().optional(),
489
684
  is_user_filter_enabled: z.boolean().optional(),
490
685
  filtered_user_ids: z.array(z.string()).optional(),
491
686
  // v1.5 Increment 4c — TelegramBot only (hard 400 на других)
@@ -501,6 +696,7 @@ export const platformVariablesConfigSchema = z
501
696
  export const platformCrmBehaviorSchema = z
502
697
  .object({
503
698
  send_to_crm: z.boolean().optional(),
699
+ create_deal_on_first_outbound: z.boolean().optional(),
504
700
  use_cross_platform_history: z.boolean().optional(),
505
701
  responsible_assignee_strategy: z
506
702
  .enum(['ROUND_ROBIN', 'LEAST_BUSY', 'RANDOM', 'FIXED', 'OPERATOR_SPECIFIC'])
@@ -512,106 +708,107 @@ export const platformCrmBehaviorSchema = z
512
708
  failed_note_template: z.string().nullable().optional(),
513
709
  send_operator_takeover_note_to_crm: z.boolean().optional(),
514
710
  operator_takeover_note_template: z.string().nullable().optional(),
711
+ finish_auto_enabled: z.boolean().optional(),
712
+ finish_auto_days: z.number().int().min(1).max(PLATFORM_FINISH_AUTO_MAX_DAYS).optional(),
713
+ send_finish_auto_note_to_crm: z.boolean().optional(),
714
+ finish_auto_note_template: z.string().nullable().optional(),
715
+ getcourse_create_deal_payment_tracking_enabled: z.boolean().optional(),
716
+ getcourse_status_deal_fallback_enabled: z.boolean().optional(),
515
717
  // v1.5 Increment 4c — deal marker (любой CRM-aware channel)
516
718
  deal_marker_type: z.enum(['NONE', 'TAG', 'CUSTOM_FIELD']).optional(),
517
719
  deal_marker_value: z.string().nullable().optional(),
518
720
  deal_marker_field_id: z.string().nullable().optional(),
519
- // Inbound deal-фильтр (GetCourse): агент отвечает только контактам, у которых в активной
520
- // сделке есть поле=значение (CUSTOM_FIELD) или тег (TAG). Для не-GetCourse каналов — no-op.
521
- // Включённый фильтр требует type≠NONE + value (для CUSTOM_FIELD ещё field_id) — иначе 400.
721
+ // Входящий фильтр по сделке (GetCourse) — прежние имена отгруженного моста; сервер хранит его в
722
+ // crm_behavior.inbound_deal_filter. Включённый фильтр обязан быть полным; включённость и тип — опасные поля.
522
723
  inbound_deal_filter_enabled: z.boolean().optional(),
523
724
  inbound_deal_filter_type: z.enum(['NONE', 'TAG', 'CUSTOM_FIELD']).optional(),
524
725
  inbound_deal_filter_value: z.string().nullable().optional(),
525
726
  inbound_deal_filter_field_id: z.string().nullable().optional(),
526
727
  })
527
728
  .strict();
729
+ /**
730
+ * Маркетинговая секция виджета — РОВНО два поля, которые принимает besales-api.
731
+ *
732
+ * ⛔ Список сайтов, лимит обращений, признак «передавать адрес страницы» и оформление ЖИВУТ НЕ
733
+ * ЗДЕСЬ, а в `general_settings`: их приёмник — конфигурация подключения канала, а не поведение.
734
+ * Прежде все шесть полей уезжали сюда под именами `webWidget*`, которых приёмная сторона не знает
735
+ * ни одного, и любое из них давало отказ «удалите неизвестные поля» на ВЕСЬ запрос — то есть ни
736
+ * одна настройка виджета через мост не записывалась.
737
+ *
738
+ * ⛔ `null` здесь не принимается: приёмник объявляет оба поля необязательными, но НЕ нулевыми, а
739
+ * проекция пишет `null` значением, а не удаляет ключ. Мост, принявший `null`, обещал бы очистку,
740
+ * которой не бывает.
741
+ */
528
742
  export const platformWidgetMarketingSchema = z
529
743
  .object({
530
- web_widget_allowed_origins: anyObjectSchema.nullable().optional(),
531
- web_widget_show_page_info: z.boolean().optional(),
532
- web_widget_rate_limit_per_minute: z.number().int().min(1).max(600).optional(),
533
- web_widget_customization: anyObjectSchema.nullable().optional(),
534
- web_widget_marketing_field_mappings: anyObjectSchema.nullable().optional(),
535
- web_widget_entry_url_variable_mapping: anyObjectSchema.nullable().optional(),
536
- })
537
- .strict();
538
- /** Предел длины одного готового текста ответа на комментарий: зеркало бэкенда (Instagram усекает приватный ответ). */
539
- export const INSTAGRAM_COMMENT_TEMPLATE_MAX_LENGTH = 500;
540
- const instagramCommentLocalizedTextSchema = z
541
- .object({
542
- ru: z.string().max(INSTAGRAM_COMMENT_TEMPLATE_MAX_LENGTH).optional(),
543
- uz: z.string().max(INSTAGRAM_COMMENT_TEMPLATE_MAX_LENGTH).optional(),
544
- uz_cyrl: z.string().max(INSTAGRAM_COMMENT_TEMPLATE_MAX_LENGTH).optional(),
744
+ marketing_field_mappings: anyObjectSchema.optional(),
745
+ entry_url_variable_mapping: anyObjectSchema.optional(),
545
746
  })
546
747
  .strict();
547
748
  /**
548
- * Готовые тексты, которые уходят клиенту дословно, без участия модели (способ ответа
549
- * PUBLIC_AND_DM): личное сообщение автору комментария, личное сообщение автору жалобы и
550
- * единственный публичный ответ на жалобу. Пустой объект очищает поле.
749
+ * Оформление виджета — одиннадцать разделов ровно теми именами, которыми их принимает
750
+ * `general_settings.customization`.
751
+ *
752
+ * ⚠️ Внутренность раздела мост НЕ переописывает: это был бы второй реестр против схемы хранения
753
+ * besales-api, и он разошёлся бы с ней на первой же правке. Раздел сливается с сохранённым, так
754
+ * что частичное значение законно; пустой объект не сбрасывает ничего.
551
755
  */
552
- export const platformInstagramCommentTemplatesSchema = z
756
+ export const platformWidgetCustomizationSchema = z
553
757
  .object({
554
- dm: instagramCommentLocalizedTextSchema.optional(),
555
- dm_complaint: instagramCommentLocalizedTextSchema.optional(),
556
- public_complaint: instagramCommentLocalizedTextSchema.optional(),
758
+ button: anyObjectSchema.optional(),
759
+ window: anyObjectSchema.optional(),
760
+ theme: anyObjectSchema.optional(),
761
+ welcome_state: anyObjectSchema.optional(),
762
+ pre_chat_form: anyObjectSchema.optional(),
763
+ offline_state: anyObjectSchema.optional(),
764
+ languages: anyObjectSchema.optional(),
765
+ widget_ux: anyObjectSchema.optional(),
766
+ gdpr: anyObjectSchema.optional(),
767
+ embed: anyObjectSchema.optional(),
768
+ advanced: anyObjectSchema.optional(),
557
769
  })
558
770
  .strict();
559
771
  export const platformInstagramCommentSchema = z
560
772
  .object({
561
773
  reply_to_instagram_comments: z.boolean().optional(),
562
774
  instagram_comment_handling_mode: z.string().nullable().optional(),
563
- instagram_comment_reply_method: z.string().nullable().optional(),
564
- instagram_comment_keywords: anyObjectSchema.nullable().optional(),
565
- instagram_comment_templates: platformInstagramCommentTemplatesSchema
566
- .describe('Готовые тексты ответов на комментарии Instagram (способ PUBLIC_AND_DM). ПОЛНАЯ ЗАМЕНА: переданный объект записывается целиком, непереданные виды и языки пропадают; пустой объект очищает. Сначала прочитай текущие тексты через besales_platform_context_get и передай всё, что должно остаться.')
775
+ instagram_comment_reply_method: z
776
+ .enum(['DM_ONLY', 'PUBLIC_REPLY', 'BOTH', 'PUBLIC_AND_DM'])
567
777
  .optional(),
778
+ instagram_comment_templates: instagramCommentTemplatesSchema.nullable().optional(),
779
+ instagram_comment_keywords: z.array(z.string()).nullable().optional(),
568
780
  reply_to_story_mentions: z.boolean().optional(),
569
781
  })
570
782
  .strict();
571
783
  /**
572
- * Ссылка на стадию CRM ПОЛНЫМ композитом.
784
+ * Общие настройки канала. Четыре поля справедливы для любого канала, остальные — веб-виджет.
573
785
  *
574
- * ⚠️ Голый `status_id` не годится: статусы 142/143 и одноимённые стадии есть в КАЖДОЙ
575
- * воронке, и выбор по номеру попал бы не туда.
576
- */
577
- export const funnelStageRefSchema = z
578
- .object({
579
- pipeline_crm_id: z.string().min(1),
580
- pipeline_id: z.number().int(),
581
- status_id: z.number().int(),
582
- })
583
- .strict();
584
- /**
585
- * Настройки раздела «Воронка канала».
786
+ * ⛔ Список сайтов — МАССИВ строк, и проверка его формы остаётся на приёмной стороне. Здесь список
787
+ * объявлялся объектом, из-за чего отвергался мостом ещё до отправки. Элементом законны голый домен
788
+ * (`site.ru`), домен с портом (`site.ru:8443`), полный адрес (`https://site.ru`) и `*`, поэтому
789
+ * проверка «это URL» была бы ошибкой — она отвергла бы три законные формы из четырёх.
790
+ *
791
+ * ⚠️ Пустой список — законное значение со смыслом «не работать нигде»; приёмник его принимает, и
792
+ * мост не вправе быть строже.
586
793
  *
587
- * ⚠️ `null` у `decision_gate`/`path_target_stage` — СБРОС; отсутствие поля — «не трогать».
588
- * Бэкенд ДЕЛЕГИРУЕТ запись сервисам раздела, поэтому здесь нет своей валидации стадий:
589
- * «стадии разные» и «стадия есть в каталоге площадки» проверяет он, и второй набор правил
590
- * рядом разошёлся бы с первым.
794
+ * Лимит обращений — целое число от 1 до 600, как на приёмной стороне.
591
795
  */
592
- export const platformFunnelAnalyticsSchema = z
593
- .object({
594
- decision_gate: z
595
- .object({
596
- submitted: funnelStageRefSchema,
597
- approved: funnelStageRefSchema,
598
- rejected: funnelStageRefSchema,
599
- })
600
- .strict()
601
- .nullable()
602
- .optional(),
603
- path_target_stage: funnelStageRefSchema.nullable().optional(),
604
- engaged_inbound_count: z.number().int().min(2).max(20).nullable().optional(),
605
- stuck_threshold_hours: z.number().int().min(1).max(720).nullable().optional(),
606
- })
607
- .strict();
608
- // v1.5 Increment 4c — per-channel typed sections
609
796
  export const platformGeneralSettingsSchema = z
610
797
  .object({
611
798
  name: z.string().nullable().optional(),
612
799
  off_message: z.string().nullable().optional(),
613
800
  timezone: z.string().optional(),
614
801
  is_active: z.boolean().optional(),
802
+ // Выключатель ответов агента. Прежде жил в `access_control`, откуда приёмник его не принимает.
803
+ is_ai_enabled: z.boolean().optional(),
804
+ // Реестр поддерживаемых стран принадлежит API; мост передаёт строку либо снимает настройку.
805
+ phone_parsing_country: z.string().nullable().optional(),
806
+ // Веб-виджет.
807
+ allowed_origins: z.array(z.string()).optional(),
808
+ page_rules: platformWidgetPageRulesSchema.nullable().optional(),
809
+ rate_limit: z.number().int().positive().max(600).optional(),
810
+ show_page_info: z.boolean().optional(),
811
+ customization: platformWidgetCustomizationSchema.optional(),
615
812
  })
616
813
  .strict();
617
814
  export const platformSalebotSettingsSchema = z
@@ -640,25 +837,7 @@ export const platformBitrix24BotSettingsSchema = z
640
837
  ignore_crm_stage_gate: z.boolean().optional(),
641
838
  })
642
839
  .strict();
643
- /**
644
- * ⚠️ УСТАРЕЛО с 23.08.2026 и на поведение НЕ влияет. Оставлено, потому что API поле ещё
645
- * принимает, а старые записи его несут; снять можно только вместе с клиентами.
646
- *
647
- * Режим применялся ко ВСЕМУ списку разом: `RESTRICT` умел лишь сужать уже посчитанный выбор, а
648
- * Email/WhatsApp/SMS в него не попадали ни у кого (`bot_link` школы отдаёт vk/telegram/max) — то
649
- * есть их отметка была молчаливым no-op. Теперь список значит «слать сюда», а судьбу КАЖДОГО
650
- * канала решает сервер по фактам о контакте. «Отправить ещё и на почту» = добавить Email в
651
- * `channels` И перечислить мессенджеры явно; предлагать `ADD` больше НЕ нужно.
652
- */
653
- export const coldWelcomeChannelsModeEnum = z.enum(['RESTRICT', 'ADD']);
654
- /**
655
- * Режим правила предохранителя холодных отправок.
656
- *
657
- * OFF — правило выключено; WARN — сработавшее правило только записывается в аудит, отправка
658
- * идёт; BLOCK — отправка останавливается. По умолчанию `active_series` = BLOCK (правило,
659
- * из-за нарушения которого пришла жалоба клиента), остальные = WARN.
660
- */
661
- export const guardModeEnum = z.enum(['OFF', 'WARN', 'BLOCK']);
840
+ // Этот набор сверяется с контрактом в wave-transports.spec.ts; трогая его, смотри туда.
662
841
  export const getcourseTransportEnum = z.enum([
663
842
  'Site',
664
843
  'Email',
@@ -677,22 +856,6 @@ export const platformGetcourseDepartmentSchema = z
677
856
  label: z.string(),
678
857
  })
679
858
  .strict();
680
- const platformGetcourseWaveFieldBindingSchema = z
681
- .object({
682
- field_id: z.number().int().positive().max(2_147_483_647),
683
- field_label: z.string().trim().min(1),
684
- })
685
- .strict();
686
- const platformGetcourseWaveFieldBindingsSchema = z
687
- .object({
688
- product_value_source: z.enum(['CODE', 'NAME']),
689
- launch_type: platformGetcourseWaveFieldBindingSchema.optional(),
690
- product: platformGetcourseWaveFieldBindingSchema.optional(),
691
- segment: platformGetcourseWaveFieldBindingSchema.optional(),
692
- funnel: platformGetcourseWaveFieldBindingSchema.optional(),
693
- channels: platformGetcourseWaveFieldBindingSchema.optional(),
694
- })
695
- .strict();
696
859
  export const platformGetcourseSettingsSchema = z
697
860
  .object({
698
861
  account_domain: z.string().nullable().optional(),
@@ -702,8 +865,8 @@ export const platformGetcourseSettingsSchema = z
702
865
  departments: z.array(platformGetcourseDepartmentSchema).nullable().optional(),
703
866
  template_user_id: z.number().int().nullable().optional(),
704
867
  template_deal_id: z.number().int().nullable().optional(),
705
- // School-scoped bindings: роль durable-волны → custom field ID сделки GetCourse.
706
- // null очищает все bindings; undefined оставляет текущую настройку без изменений.
868
+ // Привязки ролей волны к полям сделки: объект ЗАМЕНЯЕТ сохранённые привязки целиком, null
869
+ // снимает все, отсутствие поля — «не трогать».
707
870
  wave_field_bindings: platformGetcourseWaveFieldBindingsSchema.nullable().optional(),
708
871
  // Phase 2 — маппинг «поле сделки GetCourse → платформенная переменная»: значение поля активной
709
872
  // сделки контакта читается в per-contact переменную (напр. AI_TOPIC → webinar_topic).
@@ -719,32 +882,36 @@ export const platformGetcourseSettingsSchema = z
719
882
  // Department-routing: id отдела GetCourse Inbox для авто-переноса прошедших inbound-фильтр
720
883
  // диалогов (+ авто-размьют filter-muted). null → выключено. Требует inbound-фильтр включённым.
721
884
  target_department_id: z.number().int().positive().nullable().optional(),
885
+ // Отдел ЖИВЫХ ЛЮДЕЙ: туда уезжает диалог, когда его передают человеку. null → передача
886
+ // выключена (ни одного обращения к школе).
887
+ // ⛔ Не путать с `target_department_id`: тот — отдел ВОРОНКИ, куда авто-перенос кладёт диалоги
888
+ // прошедших входящий фильтр сделки. Совпадение значений бэкенд отвергает: авто-перенос
889
+ // положил бы диалог прямо в очередь сотрудников, минуя все гейты передачи человеку.
890
+ operator_department_id: z.number().int().positive().nullable().optional(),
722
891
  // Ночная проверка доставки волн (04:00 МСК): крон читает кастомные поля сделки per-транспорт
723
892
  // (=1 → отправка была); аналитика рассылок платформы при включении учитывает только DELIVERED.
724
893
  delivery_check_enabled: z.boolean().optional(),
725
- // ПРЕДОХРАНИТЕЛИ ХОЛОДНЫХ ОТПРАВОК: не писать посреди вебинарной серии, поверх работы
726
- // менеджера по действующей заявке и оплатившему этот продукт. null → «не настраивали»,
727
- // действующее значение берётся из дефолта (active_series = BLOCK, остальные = WARN).
728
- guard_active_series: guardModeEnum.nullable().optional(),
729
- guard_active_application: guardModeEnum.nullable().optional(),
730
- guard_paid: guardModeEnum.nullable().optional(),
731
- /**
732
- * ТИХИЙ ПЕРИОД площадки в сутках: не писать человеку N суток после НАШЕГО касания —
733
- * отправки или шага календарной цепочки. Считается ПО ЧЕЛОВЕКУ; волна школы касанием НЕ
734
- * считается. `null` = «не настраивали», действующее значение 0 (правила нет); рекомендация
735
- * владельца — 7. Расписание судится своим `cooldown_days`, а не этим числом.
736
- */
737
- quiet_days: z.number().int().min(0).nullable().optional(),
738
894
  /**
739
- * СРОК ДОВЕРИЯ ОТВЕТУ ШКОЛЫ: сколько суток считать действующим её «привязанных мессенджеров
740
- * нет». Пока ответ свеж, импорт контакт не заводит и школу о нём не дёргает, а отбор
741
- * расписания не берёт его в подачу. `null` = «не настраивали», действующее значение 7;
742
- * 0 = спрашивать школу каждый раз.
895
+ * СРОК ДОВЕРИЯ ОТВЕТУ ШКОЛЫ: сколько суток считать действующим её ответ «выбранными каналами
896
+ * человека не достать». Пока ответ свеж, импорт человека без карточки не заводит и школу о нём
897
+ * не спрашивает. `null` = «не настраивали», действующее значение 7; 0 = спрашивать школу каждый
898
+ * раз. Граница 0…365 — та же, что у сервера.
743
899
  */
744
- reachability_ttl_days: z.number().int().min(0).max(365).nullable().optional(),
900
+ reachability_ttl_days: z
901
+ .number()
902
+ .int()
903
+ .min(0)
904
+ .max(GETCOURSE_REACHABILITY_TTL_DAYS_MAX)
905
+ .nullable()
906
+ .optional(),
745
907
  // «Транспорт → точное НАЗВАНИЕ кастомного поля сделки» (id в read-API GetCourse нет):
746
908
  // { "Telegram": "Отправлено ТГ", "VK": "Отправлено ВК" }. Очистка — пустым объектом {}.
747
- delivery_field_map: z.record(getcourseTransportEnum, z.string()).optional(),
909
+ // ⚠️ ИМЕННО `partialRecord`. В zod 4 `record(enum, …)` требует ВСЕ ключи перечисления, поэтому
910
+ // отгруженная версия отвергала и очистку `{}`, и пример из собственного описания
911
+ // (`{"Telegram":"Отправлено ТГ"}`) — десять и девять ошибок соответственно, ещё до HTTP.
912
+ // Поле было недостижимо с момента появления; JSON-схема реестра исчерпывающесть не выражала,
913
+ // поэтому клиент видел «поле необязательное», а мост его отвергал.
914
+ delivery_field_map: z.partialRecord(getcourseTransportEnum, z.string()).optional(),
748
915
  // Ручной мьют бота по контактному полю GetCourse: оператор меняет кастом-поле контакта в GK →
749
916
  // AI молчит (снятие — когда поле снова «вкл»/пусто). manual_mute_field_id = id (числовой строкой)
750
917
  // ИЛИ имя поля; manual_mute_value = стоп-значение(я) через запятую; manual_mute_active_value —
@@ -754,436 +921,47 @@ export const platformGetcourseSettingsSchema = z
754
921
  manual_mute_value: z.string().nullable().optional(),
755
922
  manual_mute_active_value: z.string().nullable().optional(),
756
923
  // Создание отсутствующего заказа в status-волне: контакт БЕЗ единой сделки иначе не получает
757
- // сообщение (поля проставлять некуда). Заказ создаётся по ПРЕДЛОЖЕНИЮ — legacy /pl/api/deals
758
- // иначе заказ не создаёт; бесплатное предложение даёт нулевую сумму. Воронка и этап —
759
- // необязательные уточнения (по умолчанию воронка предложения), внешние id GetCourse.
760
- // Создаёт РЕАЛЬНЫЕ заказы в школе → dangerous, требует explicit_confirmation.
924
+ // сообщение (поля проставлять некуда). Заказ создаётся по ПРЕДЛОЖЕНИЮ; воронка и этап —
925
+ // необязательные уточнения и задаются только парой. Создаёт РЕАЛЬНЫЕ заказы в школе →
926
+ // dangerous, требует explicit_confirmation.
761
927
  create_missing_deal_enabled: z.boolean().optional(),
762
928
  create_missing_deal_offer_id: z.number().int().positive().nullable().optional(),
763
929
  create_missing_deal_funnel_id: z.number().int().positive().nullable().optional(),
764
930
  create_missing_deal_stage_id: z.number().int().positive().nullable().optional(),
765
- // Офферы, оплата заказов с которыми засчитывается нам независимо от автора заказа (агент
766
- // или менеджер руками). Пустой массив = выключить. Набор действует на ШКОЛУ целиком.
767
- // Меняет денежную атрибуцию задним числом → dangerous, требует explicit_confirmation.
931
+ // Деньги канала: набор предложений, оплата которых — выручка ЭТОГО канала (буква в букву как у отгруженного
932
+ // клиента, иначе сравнение схем дало бы новую строку отставания), и момент начала зачёта — поле ветки v2 (у
933
+ // прежней системы дата жила у школы и выставлялась руками). Порядок «сначала дата, потом набор» держит сервер.
934
+ // Меняют деньги задним числом → explicit_confirmation. У канала виджета те же два поля — метка продажи (сервер
935
+ // хранит её своими ключами: метка только добавляет выручку).
768
936
  revenue_offer_ids: z.array(z.number().int().positive()).optional(),
937
+ revenue_offers_paid_since: z.string().datetime({ offset: true }).nullable().optional(),
769
938
  })
770
939
  .strict();
771
940
  // Knowledge tables (Group A.5)
772
- export const knowledgeTableSourceSchema = z.object({
941
+ // ⛔ Отказы живут в СХЕМЕ с путём, а не в конструкторе запроса: отказ без пути не называет поле, и сверка с
942
+ // отгруженным клиентом не может объявить его строкой отставания. `table_schema` прежний сервер лишь резервировал и не
943
+ // читал: принимаем копию, канонический конструктор её не передаёт. NATIVE прежний сервер отвергал сам.
944
+ export const knowledgeTableSourceSchema = z
945
+ .object({
773
946
  kind: z.enum(['GOOGLE_SHEETS', 'NATIVE']),
774
947
  spreadsheet_url: z.string().optional(),
775
948
  table_schema: anyObjectSchema.optional(),
776
- });
777
- export function defineTool(definition) {
778
- return definition;
779
- }
780
- export function compactObject(value) {
781
- return Object.fromEntries(Object.entries(value).filter(([, entryValue]) => entryValue !== undefined));
782
- }
783
- export function compactMetadata(metadata) {
784
- if (!metadata) {
785
- return undefined;
786
- }
787
- const compacted = compactObject({
788
- totalTokens: metadata.total_tokens,
789
- models: metadata.models,
790
- });
791
- return Object.keys(compacted).length === 0 ? undefined : compacted;
792
- }
793
- export function setupConfirmation(input) {
794
- return compactObject({
795
- explicitConfirmation: input.explicit_confirmation,
796
- confirmationReason: input.confirmation_reason,
797
- });
798
- }
799
- export function withInstructions(response, instructions) {
800
- const text = instructions.join('\n');
801
- if (response && typeof response === 'object' && !Array.isArray(response)) {
802
- return {
803
- ...response,
804
- instructions: text,
805
- };
806
- }
807
- return {
808
- result: response,
809
- instructions: text,
810
- };
811
- }
812
- export function buildKnowledgeSpaceListQuery(scopeType, channelId) {
813
- const params = new URLSearchParams();
814
- if (scopeType)
815
- params.set('scope_type', scopeType);
816
- if (channelId)
817
- params.set('channel_id', channelId);
818
- const query = params.toString();
819
- return query.length > 0 ? `?${query}` : '';
820
- }
821
- export function buildListQuery(params) {
822
- const search = new URLSearchParams();
823
- for (const [key, value] of Object.entries(params)) {
824
- if (value === undefined) {
825
- continue;
826
- }
827
- // ⚠️ Массив уходит ПОВТОРЯЮЩИМИСЯ параметрами (`?f=A&f=B`) — именно так его читает бэкенд.
828
- // `String(['A','B'])` дал бы одну строку "A,B", и мультифильтр молча не сматчил бы ничего:
829
- // ответ 200, список пуст, ошибки нет.
830
- if (Array.isArray(value)) {
831
- for (const item of value) {
832
- search.append(key, item);
833
- }
834
- continue;
835
- }
836
- search.set(key, String(value));
837
- }
838
- const query = search.toString();
839
- return query.length > 0 ? `?${query}` : '';
840
- }
841
- export function buildVariableListQuery(scope, platformId, filter, limit, cursor) {
842
- const params = new URLSearchParams();
843
- params.set('scope', scope);
844
- if (platformId) {
845
- params.set('platformId', platformId);
846
- }
847
- if (filter) {
848
- params.set('filter', filter);
849
- }
850
- if (limit !== undefined) {
851
- params.set('limit', String(limit));
852
- }
853
- if (cursor) {
854
- params.set('cursor', cursor);
855
- }
856
- const queryString = params.toString();
857
- return queryString ? `?${queryString}` : '';
858
- }
859
- export function buildVariableScopeQuery(scope, platformId) {
860
- const params = new URLSearchParams();
861
- params.set('scope', scope);
862
- if (platformId) {
863
- params.set('platformId', platformId);
949
+ })
950
+ .superRefine((source, ctx) => {
951
+ if (source.kind === 'NATIVE') {
952
+ ctx.addIssue({
953
+ code: z.ZodIssueCode.custom,
954
+ path: ['kind'],
955
+ message: 'NATIVE-таблицы пока не поддерживаются v2: используй GOOGLE_SHEETS; поддержка NATIVE придёт отдельным маршрутом.',
956
+ });
864
957
  }
865
- return `?${params.toString()}`;
866
- }
867
- export function buildFileListQuery(input) {
868
- const params = new URLSearchParams();
869
- if (input.file_type)
870
- params.set('file_type', input.file_type);
871
- if (input.source)
872
- params.set('source', input.source);
873
- if (input.section_id !== undefined)
874
- params.set('section_id', input.section_id);
875
- if (input.limit !== undefined)
876
- params.set('limit', String(input.limit));
877
- if (input.offset !== undefined)
878
- params.set('offset', String(input.offset));
879
- const queryString = params.toString();
880
- return queryString ? `?${queryString}` : '';
881
- }
882
- // ============================================================
883
- // v1.5 Increment 3 — snake_case → camelCase input mappers
884
- // ============================================================
885
- export function mapRuntimeConfigInput(input) {
886
- return compactObject({
887
- temperature: input.temperature,
888
- maxTokens: input.max_tokens,
889
- memoryHistorySize: input.memory_history_size,
890
- ragTopK: input.rag_top_k,
891
- ragMinScore: input.rag_min_score,
892
- qaMinScore: input.qa_min_score,
893
- qaContextLimit: input.qa_context_limit,
894
- maxResponseSymbols: input.max_response_symbols,
895
- reasoningEffort: input.reasoning_effort,
896
- verbosity: input.verbosity,
897
- enableThinking: input.enable_thinking,
898
- timezone: input.timezone,
899
- languageCode: input.language_code,
900
- summarizeEvery: input.summarize_every,
901
- summaryMaxSize: input.summary_max_size,
902
- useSummary: input.use_summary,
903
- includeCrmFieldsInMemory: input.include_crm_fields_in_memory,
904
- includeTriggerContext: input.include_trigger_context,
905
- });
906
- }
907
- export function mapOutputConfigInput(input) {
908
- const buttonGenerator = input.button_generator;
909
- return compactObject({
910
- displayName: input.display_name,
911
- responseMode: input.response_mode,
912
- buttonGenerator: buttonGenerator
913
- ? compactObject({
914
- enabled: buttonGenerator.enabled,
915
- maxButtons: buttonGenerator.max_buttons,
916
- keyboardType: buttonGenerator.keyboard_type,
917
- dynamic: buttonGenerator.dynamic,
918
- })
919
- : undefined,
920
- });
921
- }
922
- export function mapBehaviorGreetingInput(input) {
923
- return compactObject({
924
- botGreeting: input.bot_greeting,
925
- greetingFileId: input.greeting_file_id,
926
- greetingButtons: input.greeting_buttons,
927
- greetingButtonsKeyboardType: input.greeting_buttons_keyboard_type,
928
- popupDelaySeconds: input.popup_delay_seconds,
929
- });
930
- }
931
- export function mapMediaHandlerInput(input) {
932
- if (!input)
933
- return undefined;
934
- return compactObject({
935
- behavior: input.behavior,
936
- fixedResponseText: input.fixed_response_text,
937
- callOperator: input.call_operator,
938
- operatorComment: input.operator_comment,
939
- });
940
- }
941
- export function mapBehaviorMediaHandlingInput(input) {
942
- return compactObject({
943
- image: mapMediaHandlerInput(input.image),
944
- video: mapMediaHandlerInput(input.video),
945
- audio: mapMediaHandlerInput(input.audio),
946
- document: mapMediaHandlerInput(input.document),
947
- });
948
- }
949
- export function mapBehaviorUrlHandlingInput(input) {
950
- return compactObject({
951
- behavior: input.behavior,
952
- fixedResponseText: input.fixed_response_text,
953
- callOperator: input.call_operator,
954
- operatorComment: input.operator_comment,
955
- useYoutubeDataApi: input.use_youtube_data_api,
956
- });
957
- }
958
- export function mapBehaviorErrorHandlingInput(input) {
959
- return compactObject({
960
- aiErrorBehavior: input.ai_error_behavior,
961
- aiErrorCustomMessage: input.ai_error_custom_message,
962
- callOperatorWithError: input.call_operator_with_error,
963
- aiErrorTargetStageId: input.ai_error_target_stage_id,
964
- });
965
- }
966
- export function mapBehaviorOperatorScheduleInput(input) {
967
- return compactObject({
968
- enabled: input.enabled,
969
- availability: input.availability,
970
- unavailableMessage: input.unavailable_message,
971
- botWaitingReturnHours: input.bot_waiting_return_hours,
972
- followUpWaitingReturnHours: input.follow_up_waiting_return_hours,
973
- skipTaskCreationOnCallOperator: input.skip_task_creation_on_call_operator,
974
- });
975
- }
976
- export function mapBehaviorTypingInput(input) {
977
- return compactObject({
978
- waitingAnswerTime: input.waiting_answer_time,
979
- canInterrupt: input.can_interrupt,
980
- messageDevide: input.message_devide,
981
- typingSpeed: input.typing_speed,
982
- fakeDelay: input.fake_delay,
983
- messageOpenDelay: input.message_open_delay,
984
- goOffline: input.go_offline,
985
- });
986
- }
987
- export function mapPipelineCrmBehaviorInput(input) {
988
- return compactObject({
989
- activePipelineIds: input.active_pipeline_ids,
990
- filterEnabled: input.filter_enabled,
991
- statusMovement: input.status_movement,
992
- createDefaults: input.create_defaults,
993
- global: input.global,
994
- });
995
- }
996
- export function mapPipelineAutoFinishInput(input) {
997
- return compactObject({
998
- finishAutoNoanswer: input.finish_auto_noanswer,
999
- finishAutoTimeout: input.finish_auto_timeout,
1000
- finishAutoDays: input.finish_auto_days,
1001
- sendFinishAutoNoteToCrm: input.send_finish_auto_note_to_crm,
1002
- finishAutoNoteTemplate: input.finish_auto_note_template,
1003
- });
1004
- }
1005
- export function mapPlatformAccessControlInput(input) {
1006
- return compactObject({
1007
- isActive: input.is_active,
1008
- isAiEnabled: input.is_ai_enabled,
1009
- isUserFilterEnabled: input.is_user_filter_enabled,
1010
- filteredUserIds: input.filtered_user_ids,
1011
- // v1.5 Increment 4c
1012
- enableCleanupCommands: input.enable_cleanup_commands,
1013
- });
1014
- }
1015
- export function mapPlatformVariablesConfigInput(input) {
1016
- return compactObject({
1017
- enableDynamicVariables: input.enable_dynamic_variables,
1018
- clearDynamicVarsOnHistoryClear: input.clear_dynamic_vars_on_history_clear,
1019
- });
1020
- }
1021
- export function mapPlatformCrmBehaviorInput(input) {
1022
- return compactObject({
1023
- sendToCrm: input.send_to_crm,
1024
- useCrossPlatformHistory: input.use_cross_platform_history,
1025
- responsibleAssigneeStrategy: input.responsible_assignee_strategy,
1026
- fixedResponsibleId: input.fixed_responsible_id,
1027
- sendStartNoteToCrm: input.send_start_note_to_crm,
1028
- startNoteTemplate: input.start_note_template,
1029
- sendFailedNoteToCrm: input.send_failed_note_to_crm,
1030
- failedNoteTemplate: input.failed_note_template,
1031
- sendOperatorTakeoverNoteToCrm: input.send_operator_takeover_note_to_crm,
1032
- operatorTakeoverNoteTemplate: input.operator_takeover_note_template,
1033
- // v1.5 Increment 4c — deal marker
1034
- dealMarkerType: input.deal_marker_type,
1035
- dealMarkerValue: input.deal_marker_value,
1036
- dealMarkerFieldId: input.deal_marker_field_id,
1037
- // Inbound deal-фильтр (GetCourse)
1038
- inboundDealFilterEnabled: input.inbound_deal_filter_enabled,
1039
- inboundDealFilterType: input.inbound_deal_filter_type,
1040
- inboundDealFilterValue: input.inbound_deal_filter_value,
1041
- inboundDealFilterFieldId: input.inbound_deal_filter_field_id,
1042
- });
1043
- }
1044
- export function mapPlatformWidgetMarketingInput(input) {
1045
- return compactObject({
1046
- webWidgetAllowedOrigins: input.web_widget_allowed_origins,
1047
- webWidgetShowPageInfo: input.web_widget_show_page_info,
1048
- webWidgetRateLimitPerMinute: input.web_widget_rate_limit_per_minute,
1049
- webWidgetCustomization: input.web_widget_customization,
1050
- webWidgetMarketingFieldMappings: input.web_widget_marketing_field_mappings,
1051
- webWidgetEntryUrlVariableMapping: input.web_widget_entry_url_variable_mapping,
1052
- });
1053
- }
1054
- function mapInstagramCommentLocalizedText(input) {
1055
- if (!input) {
1056
- return undefined;
958
+ if (source.kind === 'GOOGLE_SHEETS' && !source.spreadsheet_url) {
959
+ ctx.addIssue({
960
+ code: z.ZodIssueCode.custom,
961
+ path: ['spreadsheet_url'],
962
+ message: 'Для GOOGLE_SHEETS обязателен source.spreadsheet_url.',
963
+ });
1057
964
  }
1058
- return compactObject({ ru: input.ru, uz: input.uz, uzCyrl: input.uz_cyrl });
1059
- }
1060
- export function mapPlatformInstagramCommentInput(input) {
1061
- const templates = input.instagram_comment_templates;
1062
- return compactObject({
1063
- replyToInstagramComments: input.reply_to_instagram_comments,
1064
- instagramCommentHandlingMode: input.instagram_comment_handling_mode,
1065
- instagramCommentReplyMethod: input.instagram_comment_reply_method,
1066
- instagramCommentKeywords: input.instagram_comment_keywords,
1067
- // Пустой объект остаётся пустым объектом: именно он очищает поле на бэкенде.
1068
- instagramCommentTemplates: templates
1069
- ? compactObject({
1070
- dm: mapInstagramCommentLocalizedText(templates.dm),
1071
- dmComplaint: mapInstagramCommentLocalizedText(templates.dm_complaint),
1072
- publicComplaint: mapInstagramCommentLocalizedText(templates.public_complaint),
1073
- })
1074
- : undefined,
1075
- replyToStoryMentions: input.reply_to_story_mentions,
1076
- });
1077
- }
1078
- const mapFunnelStageRef = (ref) => ref == null
1079
- ? ref
1080
- : {
1081
- pipelineCrmId: ref.pipeline_crm_id,
1082
- pipelineId: ref.pipeline_id,
1083
- statusId: ref.status_id,
1084
- };
1085
- export function mapPlatformFunnelAnalyticsInput(input) {
1086
- // ⚠️ `compactObject` выбрасывает только `undefined`: `null` доезжает до бэкенда и означает
1087
- // СБРОС. Схлопни мы их — «сбросить ворота» стало бы неотличимо от «не трогать их».
1088
- return compactObject({
1089
- decisionGate: input.decision_gate === undefined
1090
- ? undefined
1091
- : input.decision_gate === null
1092
- ? null
1093
- : {
1094
- submitted: mapFunnelStageRef(input.decision_gate.submitted),
1095
- approved: mapFunnelStageRef(input.decision_gate.approved),
1096
- rejected: mapFunnelStageRef(input.decision_gate.rejected),
1097
- },
1098
- pathTargetStage: mapFunnelStageRef(input.path_target_stage),
1099
- engagedInboundCount: input.engaged_inbound_count,
1100
- stuckThresholdHours: input.stuck_threshold_hours,
1101
- });
1102
- }
1103
- // v1.5 Increment 4c — per-channel typed section mappers
1104
- export function mapPlatformGeneralSettingsInput(input) {
1105
- return compactObject({
1106
- name: input.name,
1107
- offMessage: input.off_message,
1108
- timezone: input.timezone,
1109
- isActive: input.is_active,
1110
- });
1111
- }
1112
- export function mapPlatformSalebotSettingsInput(input) {
1113
- return compactObject({
1114
- projectId: input.project_id,
1115
- groupId: input.group_id,
1116
- });
1117
- }
1118
- export function mapPlatformSmsgorodSettingsInput(input) {
1119
- return compactObject({
1120
- channel: input.channel,
1121
- sender: input.sender,
1122
- });
1123
- }
1124
- export function mapPlatformBitrix24BotSettingsInput(input) {
1125
- return compactObject({
1126
- botId: input.bot_id,
1127
- botCode: input.bot_code,
1128
- botName: input.bot_name,
1129
- openLineId: input.open_line_id,
1130
- ignoreCrmStageGate: input.ignore_crm_stage_gate,
1131
- });
1132
- }
1133
- export function mapPlatformGetcourseSettingsInput(input) {
1134
- const mapWaveFieldBinding = (binding) => binding
1135
- ? {
1136
- fieldId: binding.field_id,
1137
- fieldLabel: binding.field_label,
1138
- }
1139
- : undefined;
1140
- return compactObject({
1141
- accountDomain: input.account_domain,
1142
- employeeUserId: input.employee_user_id,
1143
- availableTransports: input.available_transports,
1144
- defaultTransport: input.default_transport,
1145
- departments: input.departments,
1146
- templateUserId: input.template_user_id,
1147
- templateDealId: input.template_deal_id,
1148
- waveFieldBindings: input.wave_field_bindings == null
1149
- ? input.wave_field_bindings
1150
- : compactObject({
1151
- productValueSource: input.wave_field_bindings.product_value_source,
1152
- launchType: mapWaveFieldBinding(input.wave_field_bindings.launch_type),
1153
- product: mapWaveFieldBinding(input.wave_field_bindings.product),
1154
- segment: mapWaveFieldBinding(input.wave_field_bindings.segment),
1155
- funnel: mapWaveFieldBinding(input.wave_field_bindings.funnel),
1156
- channels: mapWaveFieldBinding(input.wave_field_bindings.channels),
1157
- }),
1158
- // null → очистить маппинг; undefined → не трогать (compactObject стрипнет); массив → snake→camel.
1159
- fieldVariableMap: input.field_variable_map == null
1160
- ? input.field_variable_map
1161
- : input.field_variable_map.map((entry) => ({
1162
- getcourseFieldName: entry.getcourse_field_name,
1163
- variableName: entry.variable_name,
1164
- })),
1165
- targetDepartmentId: input.target_department_id,
1166
- deliveryCheckEnabled: input.delivery_check_enabled,
1167
- guardActiveSeries: input.guard_active_series,
1168
- guardActiveApplication: input.guard_active_application,
1169
- guardPaid: input.guard_paid,
1170
- quietDays: input.quiet_days,
1171
- reachabilityTtlDays: input.reachability_ttl_days,
1172
- // Ключи map — значения enum транспортов (совпадают с camelCase-контрактом бэка) → as-is
1173
- deliveryFieldMap: input.delivery_field_map,
1174
- // Ручной мьют GetCourse: null → очистить поле; undefined → не трогать (compactObject стрипнет).
1175
- manualMuteEnabled: input.manual_mute_enabled,
1176
- manualMuteFieldId: input.manual_mute_field_id,
1177
- manualMuteValue: input.manual_mute_value,
1178
- manualMuteActiveValue: input.manual_mute_active_value,
1179
- // Создание отсутствующего заказа: null → очистить, undefined → не трогать
1180
- createMissingDealEnabled: input.create_missing_deal_enabled,
1181
- createMissingDealOfferId: input.create_missing_deal_offer_id,
1182
- createMissingDealFunnelId: input.create_missing_deal_funnel_id,
1183
- createMissingDealStageId: input.create_missing_deal_stage_id,
1184
- // Офферы зачёта выручки: пустой массив — валидное значение «выключить», поэтому передаём
1185
- // как есть; undefined отстрипнет compactObject.
1186
- revenueOfferIds: input.revenue_offer_ids,
1187
- });
1188
- }
965
+ });
966
+ export * from './shared-input.helpers.js';
1189
967
  //# sourceMappingURL=shared.js.map