@besales/mcp 0.48.0 → 1.0.0-beta.4

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 (604) hide show
  1. package/README.md +117 -163
  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 +54 -7
  23. package/dist/http/api-client.js +132 -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 +43 -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 +149 -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 +12389 -6657
  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 +81 -24
  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 +29 -39
  158. package/dist/tools/definitions/crm-platform.js +249 -352
  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/dialogue-reprocess.d.ts +5 -0
  197. package/dist/tools/definitions/dialogue-reprocess.js +107 -0
  198. package/dist/tools/definitions/dialogue-reprocess.js.map +1 -0
  199. package/dist/tools/definitions/edit-version-transport.test-fixtures.d.ts +13 -0
  200. package/dist/tools/definitions/edit-version-transport.test-fixtures.js +292 -0
  201. package/dist/tools/definitions/edit-version-transport.test-fixtures.js.map +1 -0
  202. package/dist/tools/definitions/edit-version.d.ts +5 -0
  203. package/dist/tools/definitions/edit-version.js +20 -0
  204. package/dist/tools/definitions/edit-version.js.map +1 -0
  205. package/dist/tools/definitions/external-api-channels.js +17 -15
  206. package/dist/tools/definitions/external-api-channels.js.map +1 -1
  207. package/dist/tools/definitions/feedback-document-access.d.ts +16 -0
  208. package/dist/tools/definitions/feedback-document-access.js +63 -0
  209. package/dist/tools/definitions/feedback-document-access.js.map +1 -0
  210. package/dist/tools/definitions/fixtures/shipped-setup-status.d.ts +3 -0
  211. package/dist/tools/definitions/fixtures/shipped-setup-status.js +9 -0
  212. package/dist/tools/definitions/fixtures/shipped-setup-status.js.map +1 -0
  213. package/dist/tools/definitions/follow-up-config.d.ts +79 -0
  214. package/dist/tools/definitions/follow-up-config.js +258 -0
  215. package/dist/tools/definitions/follow-up-config.js.map +1 -0
  216. package/dist/tools/definitions/follow-up-funnel-test.d.ts +4 -3
  217. package/dist/tools/definitions/follow-up-funnel-test.js +65 -52
  218. package/dist/tools/definitions/follow-up-funnel-test.js.map +1 -1
  219. package/dist/tools/definitions/follow-up-promotion-instructions.d.ts +2 -0
  220. package/dist/tools/definitions/follow-up-promotion-instructions.js +7 -0
  221. package/dist/tools/definitions/follow-up-promotion-instructions.js.map +1 -0
  222. package/dist/tools/definitions/follow-up-setup.d.ts +4 -28
  223. package/dist/tools/definitions/follow-up-setup.js +20 -87
  224. package/dist/tools/definitions/follow-up-setup.js.map +1 -1
  225. package/dist/tools/definitions/follow-up.d.ts +20 -122
  226. package/dist/tools/definitions/follow-up.js +200 -357
  227. package/dist/tools/definitions/follow-up.js.map +1 -1
  228. package/dist/tools/definitions/followup-getcourse-compat.d.ts +29 -0
  229. package/dist/tools/definitions/followup-getcourse-compat.js +62 -0
  230. package/dist/tools/definitions/followup-getcourse-compat.js.map +1 -0
  231. package/dist/tools/definitions/followup-sequence-config.schema.d.ts +10 -0
  232. package/dist/tools/definitions/followup-sequence-config.schema.js +14 -0
  233. package/dist/tools/definitions/followup-sequence-config.schema.js.map +1 -0
  234. package/dist/tools/definitions/funnel-analytics.d.ts +18 -0
  235. package/dist/tools/definitions/funnel-analytics.js +150 -0
  236. package/dist/tools/definitions/funnel-analytics.js.map +1 -0
  237. package/dist/tools/definitions/getcourse-anchor-refresh.d.ts +5 -9
  238. package/dist/tools/definitions/getcourse-anchor-refresh.js +26 -31
  239. package/dist/tools/definitions/getcourse-anchor-refresh.js.map +1 -1
  240. package/dist/tools/definitions/getcourse-cold-outbound-settings.d.ts +46 -0
  241. package/dist/tools/definitions/getcourse-cold-outbound-settings.js +37 -0
  242. package/dist/tools/definitions/getcourse-cold-outbound-settings.js.map +1 -0
  243. package/dist/tools/definitions/getcourse-cold-welcome.d.ts +14 -29
  244. package/dist/tools/definitions/getcourse-cold-welcome.js +190 -253
  245. package/dist/tools/definitions/getcourse-cold-welcome.js.map +1 -1
  246. package/dist/tools/definitions/getcourse-wave-welcome.messages.d.ts +10 -0
  247. package/dist/tools/definitions/getcourse-wave-welcome.messages.js +17 -0
  248. package/dist/tools/definitions/getcourse-wave-welcome.messages.js.map +1 -0
  249. package/dist/tools/definitions/help.js.map +1 -1
  250. package/dist/tools/definitions/icp-import-source.d.ts +75 -0
  251. package/dist/tools/definitions/icp-import-source.js +88 -0
  252. package/dist/tools/definitions/icp-import-source.js.map +1 -0
  253. package/dist/tools/definitions/inbound-analytics.d.ts +13 -0
  254. package/dist/tools/definitions/inbound-analytics.js +55 -0
  255. package/dist/tools/definitions/inbound-analytics.js.map +1 -0
  256. package/dist/tools/definitions/instagram-comment.templates.d.ts +19 -0
  257. package/dist/tools/definitions/instagram-comment.templates.js +34 -0
  258. package/dist/tools/definitions/instagram-comment.templates.js.map +1 -0
  259. package/dist/tools/definitions/instagram-settings-compat.d.ts +33 -0
  260. package/dist/tools/definitions/instagram-settings-compat.js +7 -0
  261. package/dist/tools/definitions/instagram-settings-compat.js.map +1 -0
  262. package/dist/tools/definitions/knowledge-chunking.d.ts +42 -0
  263. package/dist/tools/definitions/knowledge-chunking.js +83 -0
  264. package/dist/tools/definitions/knowledge-chunking.js.map +1 -0
  265. package/dist/tools/definitions/knowledge-space-search-fields.d.ts +12 -0
  266. package/dist/tools/definitions/knowledge-space-search-fields.js +30 -0
  267. package/dist/tools/definitions/knowledge-space-search-fields.js.map +1 -0
  268. package/dist/tools/definitions/knowledge.d.ts +24 -14
  269. package/dist/tools/definitions/knowledge.js +342 -233
  270. package/dist/tools/definitions/knowledge.js.map +1 -1
  271. package/dist/tools/definitions/legacy-trigger-repeat.d.ts +17 -0
  272. package/dist/tools/definitions/legacy-trigger-repeat.js +53 -0
  273. package/dist/tools/definitions/legacy-trigger-repeat.js.map +1 -0
  274. package/dist/tools/definitions/link-tracking.d.ts +8 -0
  275. package/dist/tools/definitions/link-tracking.js +141 -38
  276. package/dist/tools/definitions/link-tracking.js.map +1 -1
  277. package/dist/tools/definitions/mailing-variant-content.d.ts +75 -0
  278. package/dist/tools/definitions/mailing-variant-content.js +73 -0
  279. package/dist/tools/definitions/mailing-variant-content.js.map +1 -0
  280. package/dist/tools/definitions/model-comparison.d.ts +2 -1
  281. package/dist/tools/definitions/model-comparison.js +4 -5
  282. package/dist/tools/definitions/model-comparison.js.map +1 -1
  283. package/dist/tools/definitions/money-currency.d.ts +5 -0
  284. package/dist/tools/definitions/money-currency.js +10 -0
  285. package/dist/tools/definitions/money-currency.js.map +1 -0
  286. package/dist/tools/definitions/operator-workflow.d.ts +5 -5
  287. package/dist/tools/definitions/operator-workflow.js +80 -27
  288. package/dist/tools/definitions/operator-workflow.js.map +1 -1
  289. package/dist/tools/definitions/platform-funnel-analytics.d.ts +42 -0
  290. package/dist/tools/definitions/platform-funnel-analytics.js +72 -0
  291. package/dist/tools/definitions/platform-funnel-analytics.js.map +1 -0
  292. package/dist/tools/definitions/platform-getcourse-wave-field-bindings.d.ts +42 -0
  293. package/dist/tools/definitions/platform-getcourse-wave-field-bindings.js +51 -0
  294. package/dist/tools/definitions/platform-getcourse-wave-field-bindings.js.map +1 -0
  295. package/dist/tools/definitions/platform-settings-limits.d.ts +5 -0
  296. package/dist/tools/definitions/platform-settings-limits.js +6 -0
  297. package/dist/tools/definitions/platform-settings-limits.js.map +1 -0
  298. package/dist/tools/definitions/platform-settings-shipped-form.d.ts +37 -0
  299. package/dist/tools/definitions/platform-settings-shipped-form.js +310 -0
  300. package/dist/tools/definitions/platform-settings-shipped-form.js.map +1 -0
  301. package/dist/tools/definitions/platform-settings-update.d.ts +300 -0
  302. package/dist/tools/definitions/platform-settings-update.js +134 -0
  303. package/dist/tools/definitions/platform-settings-update.js.map +1 -0
  304. package/dist/tools/definitions/{getcourse-wave.d.ts → platform-setup-wave.d.ts} +75 -6
  305. package/dist/tools/definitions/platform-setup-wave.js +1079 -0
  306. package/dist/tools/definitions/platform-setup-wave.js.map +1 -0
  307. package/dist/tools/definitions/platform-setup.d.ts +697 -224
  308. package/dist/tools/definitions/platform-setup.js +313 -752
  309. package/dist/tools/definitions/platform-setup.js.map +1 -1
  310. package/dist/tools/definitions/platform-widget-page-rules.schema.d.ts +10 -0
  311. package/dist/tools/definitions/platform-widget-page-rules.schema.js +7 -0
  312. package/dist/tools/definitions/platform-widget-page-rules.schema.js.map +1 -0
  313. package/dist/tools/definitions/prompt-authoring.constants.d.ts +2 -0
  314. package/dist/tools/definitions/prompt-authoring.constants.js +3 -0
  315. package/dist/tools/definitions/prompt-authoring.constants.js.map +1 -0
  316. package/dist/tools/definitions/prompt-batch-controls.d.ts +5 -0
  317. package/dist/tools/definitions/prompt-batch-controls.js +40 -0
  318. package/dist/tools/definitions/prompt-batch-controls.js.map +1 -0
  319. package/dist/tools/definitions/prompt-draft-authoring.d.ts +5 -0
  320. package/dist/tools/definitions/prompt-draft-authoring.js +24 -0
  321. package/dist/tools/definitions/prompt-draft-authoring.js.map +1 -0
  322. package/dist/tools/definitions/prompt-text-projection.d.ts +11 -0
  323. package/dist/tools/definitions/prompt-text-projection.js +62 -0
  324. package/dist/tools/definitions/prompt-text-projection.js.map +1 -0
  325. package/dist/tools/definitions/reviewer-paid.d.ts +19 -0
  326. package/dist/tools/definitions/reviewer-paid.js +115 -0
  327. package/dist/tools/definitions/reviewer-paid.js.map +1 -0
  328. package/dist/tools/definitions/routing-condition-projection.d.ts +31 -0
  329. package/dist/tools/definitions/routing-condition-projection.js +97 -0
  330. package/dist/tools/definitions/routing-condition-projection.js.map +1 -0
  331. package/dist/tools/definitions/schedule-selection-hints.d.ts +3 -0
  332. package/dist/tools/definitions/schedule-selection-hints.js +42 -0
  333. package/dist/tools/definitions/schedule-selection-hints.js.map +1 -0
  334. package/dist/tools/definitions/{scheduled-tasks.d.ts → scheduled-task-alias.d.ts} +12 -10
  335. package/dist/tools/definitions/scheduled-task-alias.js +207 -0
  336. package/dist/tools/definitions/scheduled-task-alias.js.map +1 -0
  337. package/dist/tools/definitions/session.js +3 -3
  338. package/dist/tools/definitions/session.js.map +1 -1
  339. package/dist/tools/definitions/setup-init-operation.schema.d.ts +2 -0
  340. package/dist/tools/definitions/setup-init-operation.schema.js +6 -0
  341. package/dist/tools/definitions/setup-init-operation.schema.js.map +1 -0
  342. package/dist/tools/definitions/shared-input.helpers.d.ts +51 -0
  343. package/dist/tools/definitions/shared-input.helpers.js +323 -0
  344. package/dist/tools/definitions/shared-input.helpers.js.map +1 -0
  345. package/dist/tools/definitions/shared.d.ts +401 -307
  346. package/dist/tools/definitions/shared.js +430 -652
  347. package/dist/tools/definitions/shared.js.map +1 -1
  348. package/dist/tools/definitions/shipped-output-names.d.ts +19 -0
  349. package/dist/tools/definitions/shipped-output-names.js +123 -0
  350. package/dist/tools/definitions/shipped-output-names.js.map +1 -0
  351. package/dist/tools/definitions/task-state.d.ts +4 -4
  352. package/dist/tools/definitions/task-state.js +2 -1
  353. package/dist/tools/definitions/task-state.js.map +1 -1
  354. package/dist/tools/definitions/telegram-personal-capacity.d.ts +4 -0
  355. package/dist/tools/definitions/telegram-personal-capacity.js +18 -0
  356. package/dist/tools/definitions/telegram-personal-capacity.js.map +1 -0
  357. package/dist/tools/definitions/telegram-personal-management.d.ts +34 -0
  358. package/dist/tools/definitions/telegram-personal-management.js +139 -0
  359. package/dist/tools/definitions/telegram-personal-management.js.map +1 -0
  360. package/dist/tools/definitions/telegram-personal-restrictions.d.ts +19 -0
  361. package/dist/tools/definitions/telegram-personal-restrictions.js +109 -0
  362. package/dist/tools/definitions/telegram-personal-restrictions.js.map +1 -0
  363. package/dist/tools/definitions/telegram-pool-policy.d.ts +8 -0
  364. package/dist/tools/definitions/telegram-pool-policy.js +56 -0
  365. package/dist/tools/definitions/telegram-pool-policy.js.map +1 -0
  366. package/dist/tools/definitions/touch-history-alias.d.ts +4 -0
  367. package/dist/tools/definitions/touch-history-alias.js +99 -0
  368. package/dist/tools/definitions/touch-history-alias.js.map +1 -0
  369. package/dist/tools/definitions/trigger-action-item.schema.d.ts +254 -0
  370. package/dist/tools/definitions/trigger-action-item.schema.js +121 -0
  371. package/dist/tools/definitions/trigger-action-item.schema.js.map +1 -0
  372. package/dist/tools/definitions/trigger-argument.schema.d.ts +14 -0
  373. package/dist/tools/definitions/trigger-argument.schema.js +23 -0
  374. package/dist/tools/definitions/trigger-argument.schema.js.map +1 -0
  375. package/dist/tools/definitions/trigger-claim-alias.d.ts +10 -0
  376. package/dist/tools/definitions/trigger-claim-alias.js +90 -0
  377. package/dist/tools/definitions/trigger-claim-alias.js.map +1 -0
  378. package/dist/tools/definitions/trigger-echo-projection.d.ts +1 -0
  379. package/dist/tools/definitions/trigger-echo-projection.js +41 -0
  380. package/dist/tools/definitions/trigger-echo-projection.js.map +1 -0
  381. package/dist/tools/definitions/trigger-upsert.tool.d.ts +41 -0
  382. package/dist/tools/definitions/trigger-upsert.tool.js +159 -0
  383. package/dist/tools/definitions/trigger-upsert.tool.js.map +1 -0
  384. package/dist/tools/definitions/v15-port-descriptions.d.ts +11 -0
  385. package/dist/tools/definitions/v15-port-descriptions.js +30 -0
  386. package/dist/tools/definitions/v15-port-descriptions.js.map +1 -0
  387. package/dist/tools/definitions/variables.d.ts +44 -0
  388. package/dist/tools/definitions/variables.js +310 -0
  389. package/dist/tools/definitions/variables.js.map +1 -0
  390. package/dist/tools/definitions/voice-action-input.d.ts +9 -0
  391. package/dist/tools/definitions/voice-action-input.js +141 -0
  392. package/dist/tools/definitions/voice-action-input.js.map +1 -0
  393. package/dist/tools/definitions/widget-customization-compat.d.ts +51 -0
  394. package/dist/tools/definitions/widget-customization-compat.js +23 -0
  395. package/dist/tools/definitions/widget-customization-compat.js.map +1 -0
  396. package/dist/tools/definitions.d.ts +1134 -617
  397. package/dist/tools/definitions.js +63 -27
  398. package/dist/tools/definitions.js.map +1 -1
  399. package/dist/tools/description-localization.js +3 -2
  400. package/dist/tools/description-localization.js.map +1 -1
  401. package/dist/tools/follow-up-request.d.ts +19 -0
  402. package/dist/tools/follow-up-request.js +81 -0
  403. package/dist/tools/follow-up-request.js.map +1 -0
  404. package/dist/tools/followup-revision.d.ts +4 -0
  405. package/dist/tools/followup-revision.js +29 -0
  406. package/dist/tools/followup-revision.js.map +1 -0
  407. package/dist/tools/incomplete-list.js +4 -0
  408. package/dist/tools/incomplete-list.js.map +1 -1
  409. package/dist/tools/inventory.js +47 -11
  410. package/dist/tools/inventory.js.map +1 -1
  411. package/dist/tools/operation-recovery.d.ts +4 -0
  412. package/dist/tools/operation-recovery.js +33 -0
  413. package/dist/tools/operation-recovery.js.map +1 -0
  414. package/dist/tools/registry-mapping-primary.cases.d.ts +2 -0
  415. package/dist/tools/registry-mapping-primary.cases.js +765 -0
  416. package/dist/tools/registry-mapping-primary.cases.js.map +1 -0
  417. package/dist/tools/registry-mapping-secondary.cases.d.ts +2 -0
  418. package/dist/tools/registry-mapping-secondary.cases.js +626 -0
  419. package/dist/tools/registry-mapping-secondary.cases.js.map +1 -0
  420. package/dist/tools/registry-mapping.cases.d.ts +8 -0
  421. package/dist/tools/registry-mapping.cases.js +170 -0
  422. package/dist/tools/registry-mapping.cases.js.map +1 -0
  423. package/dist/tools/registry-test-fixtures.d.ts +50 -0
  424. package/dist/tools/registry-test-fixtures.js +120 -0
  425. package/dist/tools/registry-test-fixtures.js.map +1 -0
  426. package/dist/tools/registry.d.ts +2 -0
  427. package/dist/tools/registry.js +84 -52
  428. package/dist/tools/registry.js.map +1 -1
  429. package/dist/tools/result.d.ts +1 -0
  430. package/dist/tools/result.js +90 -22
  431. package/dist/tools/result.js.map +1 -1
  432. package/dist/tools/toolsets.d.ts +16 -0
  433. package/dist/tools/toolsets.js +25 -1
  434. package/dist/tools/toolsets.js.map +1 -1
  435. package/dist/types/api-contract.gen.d.ts +131892 -22453
  436. package/dist/utils/credential-signatures.d.ts +3 -0
  437. package/dist/utils/credential-signatures.js +10 -0
  438. package/dist/utils/credential-signatures.js.map +1 -0
  439. package/dist/utils/data-source-column-name.d.ts +10 -0
  440. package/dist/utils/data-source-column-name.js +36 -0
  441. package/dist/utils/data-source-column-name.js.map +1 -0
  442. package/dist/utils/logger.d.ts +1 -0
  443. package/dist/utils/logger.js +32 -8
  444. package/dist/utils/logger.js.map +1 -1
  445. package/dist/utils/secret-read-boundary.d.ts +2 -0
  446. package/dist/utils/secret-read-boundary.js +88 -0
  447. package/dist/utils/secret-read-boundary.js.map +1 -0
  448. package/dist/utils/setup-secrets.d.ts +4 -0
  449. package/dist/utils/setup-secrets.js +40 -0
  450. package/dist/utils/setup-secrets.js.map +1 -0
  451. package/docs/agent-models.md +9 -0
  452. package/docs/agent-usage-guide.full.ru.md +1 -4
  453. package/docs/analytics-contract.md +67 -0
  454. package/docs/async-operation-lifecycle.md +10 -3
  455. package/docs/connect.ru.md +144 -4
  456. package/docs/contact-company-profile.md +17 -0
  457. package/docs/contact-recommendations.md +7 -0
  458. package/docs/crm-stage-pool.md +73 -0
  459. package/docs/customer-data.md +61 -0
  460. package/docs/dialogue-reprocess.md +37 -0
  461. package/docs/edit-versions.md +36 -0
  462. package/docs/failure-semantics.md +17 -9
  463. package/docs/help-navigation.md +15 -42
  464. package/docs/host-compatibility-matrix.md +72 -93
  465. package/docs/host-setup.md +33 -35
  466. package/docs/invariants/public-api-and-contracts.md +16 -0
  467. package/docs/legacy-action-settings.md +21 -0
  468. package/docs/main-transfer-dependencies.md +38 -0
  469. package/docs/mcp2-parity.md +50 -0
  470. package/docs/modules/analytics.md +79 -0
  471. package/docs/modules/besales-mcp.md +144 -0
  472. package/docs/modules/dialog-review-report.md +38 -0
  473. package/docs/modules/dialogue-followup-adapters.md +39 -0
  474. package/docs/modules/message-reactions.md +17 -0
  475. package/docs/modules/network-mode.md +284 -0
  476. package/docs/modules/prompt-batch-and-dialogue-controls.md +69 -0
  477. package/docs/pii-policy.md +21 -16
  478. package/docs/response-size-budget.md +197 -7
  479. package/docs/secret-read-boundary.md +102 -0
  480. package/docs/task-state.md +7 -2
  481. package/docs/telegram-personal-management.md +50 -0
  482. package/docs/telegram-personal-restrictions.md +87 -0
  483. package/docs/telegram-pool-policy.md +19 -0
  484. package/docs/tool-effects.md +15 -9
  485. package/docs/tool-surface.md +205 -4
  486. package/docs/voice-actions-and-inbox.md +95 -0
  487. package/docs/wazzup-instagram-comments.md +26 -0
  488. package/package.json +17 -10
  489. package/scripts/api-source-loader.spec.mjs +40 -0
  490. package/scripts/audit-bridge-controls.mjs +129 -0
  491. package/scripts/audit-revert-mutants.mjs +107 -0
  492. package/scripts/bridge-api-input.spec.mjs +98 -0
  493. package/scripts/bridge-controls-mutants.mjs +130 -0
  494. package/scripts/brx3-shipped-refusals.spec.mjs +149 -0
  495. package/scripts/brx4-ledger-payload.spec.mjs +127 -0
  496. package/scripts/build-onprem.mjs +108 -0
  497. package/scripts/connect-clients.sh +141 -0
  498. package/scripts/connect-scopes.mjs +166 -0
  499. package/scripts/connect-scopes.spec.mjs +83 -0
  500. package/scripts/emit-personal-link-carrier.mjs +31 -0
  501. package/scripts/emit-setup-init-schemas.mjs +24 -0
  502. package/scripts/emit-tool-routes.mjs +878 -0
  503. package/scripts/emit-tool-routes.spec.mjs +300 -0
  504. package/scripts/followup-registry.spec.mjs +107 -0
  505. package/scripts/generate-crm-rotation-contract.mjs +98 -0
  506. package/scripts/generate-followup-session-contract.mjs +16 -0
  507. package/scripts/getcourse-text-source.spec.mjs +110 -0
  508. package/scripts/icp-import-verification/mutate.cjs +70 -0
  509. package/scripts/import-secret-read-contract.mjs +53 -0
  510. package/scripts/install-claude-desktop.js +1 -1
  511. package/scripts/lag-decisions.mjs +37 -0
  512. package/scripts/lag-decisions.spec.mjs +87 -0
  513. package/scripts/lag-open-task-owners.mjs +46 -0
  514. package/scripts/lag-open-task-owners.spec.mjs +78 -0
  515. package/scripts/lag-payload.mjs +10 -0
  516. package/scripts/legacy-action-lag.spec.mjs +22 -0
  517. package/scripts/legacy-field-refusal.shipped.spec.mjs +99 -0
  518. package/scripts/mcpcompat-handler.mjs +34 -0
  519. package/scripts/mcpcompat-loader.mjs +36 -0
  520. package/scripts/mcpcompat-typescript.mjs +3 -0
  521. package/scripts/platform-settings-shipped-parity.spec.mjs +89 -0
  522. package/scripts/prbr-round1-recheck.spec.mjs +605 -0
  523. package/scripts/prbr-shipped-compatibility.spec.mjs +276 -0
  524. package/scripts/publish-mcp-registry.mjs +98 -0
  525. package/scripts/publish-mcp-registry.spec.mjs +68 -0
  526. package/scripts/record-scheduled-task-call.mjs +26 -0
  527. package/scripts/refusal-probe.mjs +17 -0
  528. package/scripts/refusal-probe.spec.mjs +29 -0
  529. package/scripts/registry-diff.mjs +502 -0
  530. package/scripts/registry-diff.spec.mjs +787 -0
  531. package/scripts/request-query.mjs +43 -0
  532. package/scripts/request-query.spec.mjs +82 -0
  533. package/scripts/route-lag.mjs +23 -0
  534. package/scripts/route-lag.spec.mjs +30 -0
  535. package/scripts/sample-args.mjs +174 -0
  536. package/scripts/sample-args.spec.mjs +160 -0
  537. package/scripts/shipped-definitions.mjs +197 -0
  538. package/scripts/shipped-definitions.spec.mjs +57 -0
  539. package/scripts/shipped-inputs.spec.mjs +136 -0
  540. package/scripts/shipped-recordings.spec.mjs +19 -0
  541. package/scripts/shipped-ref.d.mts +5 -0
  542. package/scripts/shipped-ref.mjs +20 -0
  543. package/scripts/shipped-ref.spec.mjs +59 -0
  544. package/scripts/shipped-registry.mjs +107 -0
  545. package/scripts/shipped-sample-candidates.mjs +69 -0
  546. package/scripts/shipped-sample-candidates.spec.mjs +117 -0
  547. package/scripts/shipped-sample.mjs +871 -0
  548. package/scripts/shipped-sample.spec.mjs +451 -0
  549. package/scripts/sync-agent-model-schemas.mjs +72 -0
  550. package/scripts/sync-api-contracts.mjs +85 -0
  551. package/scripts/sync-api-contracts.spec.mjs +144 -0
  552. package/scripts/sync-contract-ledger-schemas.mjs +161 -0
  553. package/scripts/sync-crm-stage-pool-schema.mjs +85 -0
  554. package/scripts/sync-prompt-draft-schema.mjs +92 -0
  555. package/scripts/sync-route-map.mjs +94 -0
  556. package/scripts/sync-schema-descriptions.mjs +25 -0
  557. package/scripts/sync-tool-inventory.mjs +27 -0
  558. package/scripts/sync-trigger-argument-schema.mjs +97 -0
  559. package/scripts/sync-trigger-argument-schema.spec.mjs +91 -0
  560. package/scripts/sync-trigger-event-schema.mjs +20 -0
  561. package/scripts/sync-trigger-repeat-mapping.mjs +12 -0
  562. package/scripts/sync-trigger-task-schema.mjs +45 -0
  563. package/scripts/sync-voice-actions-contract.mjs +67 -0
  564. package/scripts/sync-voice-actions-tools.mjs +97 -0
  565. package/scripts/sync-wave-id-schemas.mjs +55 -0
  566. package/scripts/telegram-personal-confirmation-mutants.mjs +74 -0
  567. package/scripts/tool-input-schemas.mjs +46 -0
  568. package/scripts/tool-input-schemas.spec.mjs +50 -0
  569. package/scripts/verify-followup-adapters.mjs +235 -0
  570. package/scripts/verify-secret-read-import.mjs +84 -0
  571. package/scripts/verify-secret-read-mutants.mjs +143 -0
  572. package/dist/tools/definitions/analytics.d.ts +0 -40
  573. package/dist/tools/definitions/analytics.js +0 -233
  574. package/dist/tools/definitions/analytics.js.map +0 -1
  575. package/dist/tools/definitions/broadcast-mailing-variants.d.ts +0 -41
  576. package/dist/tools/definitions/broadcast-mailing-variants.js +0 -194
  577. package/dist/tools/definitions/broadcast-mailing-variants.js.map +0 -1
  578. package/dist/tools/definitions/dialogue-audit.d.ts +0 -38
  579. package/dist/tools/definitions/dialogue-audit.js +0 -292
  580. package/dist/tools/definitions/dialogue-audit.js.map +0 -1
  581. package/dist/tools/definitions/getcourse-wave.js +0 -519
  582. package/dist/tools/definitions/getcourse-wave.js.map +0 -1
  583. package/dist/tools/definitions/operational-overview.d.ts +0 -3
  584. package/dist/tools/definitions/operational-overview.js +0 -23
  585. package/dist/tools/definitions/operational-overview.js.map +0 -1
  586. package/dist/tools/definitions/scheduled-tasks.js +0 -173
  587. package/dist/tools/definitions/scheduled-tasks.js.map +0 -1
  588. package/dist/tools/definitions/trigger-contact-claims.d.ts +0 -7
  589. package/dist/tools/definitions/trigger-contact-claims.js +0 -60
  590. package/dist/tools/definitions/trigger-contact-claims.js.map +0 -1
  591. package/dist/tools/registry-mapping-cases-core.d.ts +0 -38
  592. package/dist/tools/registry-mapping-cases-core.js +0 -963
  593. package/dist/tools/registry-mapping-cases-core.js.map +0 -1
  594. package/dist/tools/registry-mapping-cases-platform.d.ts +0 -2
  595. package/dist/tools/registry-mapping-cases-platform.js +0 -1052
  596. package/dist/tools/registry-mapping-cases-platform.js.map +0 -1
  597. package/dist/tools/trigger-action-config.d.ts +0 -49
  598. package/dist/tools/trigger-action-config.js +0 -171
  599. package/dist/tools/trigger-action-config.js.map +0 -1
  600. package/docs/evals/model-behavior-scorecard.md +0 -80
  601. package/docs/operation-coverage.md +0 -114
  602. package/scripts/mock-credentials.js +0 -77
  603. package/scripts/model-eval-server.js +0 -213
  604. package/scripts/run-model-eval.js +0 -447
@@ -0,0 +1,144 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { z } from 'zod';
4
+ import { toolDefinitions } from '../src/tools/definitions.ts';
5
+ import { syncSchemaDescriptions } from './sync-schema-descriptions.mjs';
6
+
7
+ const options = { io: 'input', unrepresentable: 'any' };
8
+
9
+ describe('генератор контрактов: описания полей', () => {
10
+ it('переносит новые и обновлённые описания любых полей, сохраняя ограничения и подписи без замены', () => {
11
+ const target = {
12
+ type: 'object',
13
+ required: ['another_field'],
14
+ properties: {
15
+ another_field: { type: 'integer', enum: [1, 2], description: 'старое описание' },
16
+ new_hint: { type: 'string', minLength: 4 },
17
+ published_hint: { type: 'string', description: 'подпись каталога' },
18
+ catalog_only: { type: 'boolean', description: 'только каталог' },
19
+ },
20
+ allOf: [{ if: { required: ['new_hint'] }, then: { required: ['published_hint'] } }],
21
+ };
22
+ const before = structuredClone(target);
23
+ const derived = z.toJSONSchema(
24
+ z.object({
25
+ another_field: z.number().int().describe('актуальное описание'),
26
+ new_hint: z.string().describe('новая подсказка'),
27
+ published_hint: z.string(),
28
+ executable_only: z.string().describe('не добавлять поле'),
29
+ }),
30
+ options,
31
+ );
32
+ const source = structuredClone(derived);
33
+
34
+ syncSchemaDescriptions(target, derived);
35
+
36
+ before.properties.another_field.description = 'актуальное описание';
37
+ before.properties.new_hint.description = 'новая подсказка';
38
+ expect(target).toEqual(before);
39
+ expect(derived).toEqual(source);
40
+ syncSchemaDescriptions(target, derived);
41
+ expect(target).toEqual(before);
42
+ });
43
+
44
+ it('обходит вложенные объекты, элементы массивов, словари и ветви схем', () => {
45
+ const derived = z.toJSONSchema(
46
+ z.object({
47
+ rows: z.array(z.object({
48
+ value: z.string().describe('значение строки'),
49
+ description: z.string().describe('подсказка поля с именем description'),
50
+ }).describe('строка')).describe('строки'),
51
+ dictionary: z.record(z.string(), z.string().describe('значение словаря')),
52
+ choice: z.union([
53
+ z.string().describe('текст'),
54
+ z.object({ count: z.number().describe('количество') }),
55
+ ]),
56
+ }),
57
+ options,
58
+ );
59
+ const target = structuredClone(derived);
60
+ const withoutDescriptions = (value) => {
61
+ if (!value || typeof value !== 'object') return;
62
+ if (typeof value.description === 'string') delete value.description;
63
+ Object.values(value).forEach(withoutDescriptions);
64
+ };
65
+ withoutDescriptions(target);
66
+ syncSchemaDescriptions(target, derived);
67
+ expect(target).toEqual(derived);
68
+
69
+ const conditional = { allOf: [{ if: {}, then: {}, else: {} }], oneOf: [{}], prefixItems: [{}] };
70
+ const annotations = {
71
+ allOf: [{
72
+ if: { description: 'условие' },
73
+ then: { description: 'да' },
74
+ else: { description: 'нет' },
75
+ }],
76
+ oneOf: [{ description: 'вариант' }],
77
+ prefixItems: [{ description: 'элемент' }],
78
+ };
79
+ syncSchemaDescriptions(conditional, annotations);
80
+ expect(conditional).toEqual(annotations);
81
+ });
82
+
83
+ it('не переписывает description внутри пользовательских default/const/enum/examples', () => {
84
+ const target = {
85
+ default: { description: 'данные' },
86
+ const: { description: 'данные' },
87
+ enum: [{ description: 'данные' }],
88
+ examples: [{ description: 'данные' }],
89
+ additionalProperties: false,
90
+ };
91
+ const before = structuredClone(target);
92
+ syncSchemaDescriptions(target, {
93
+ default: { description: 'не подпись' },
94
+ const: { description: 'не подпись' },
95
+ enum: [{ description: 'не подпись' }],
96
+ examples: [{ description: 'не подпись' }],
97
+ additionalProperties: { description: 'не менять boolean-схему' },
98
+ });
99
+ expect(target).toEqual(before);
100
+ expect(() => syncSchemaDescriptions(undefined, {})).not.toThrow();
101
+ expect(() => syncSchemaDescriptions({}, false)).not.toThrow();
102
+ });
103
+
104
+ it('S28: на текущем снимке переносит адаптивный горизонт и не меняет в каталоге ничего кроме описаний', () => {
105
+ const registry = JSON.parse(
106
+ readFileSync(new URL('../src/schemas/mcp-tools.json', import.meta.url), 'utf8'),
107
+ );
108
+ const snapshot = readFileSync(new URL('../src/types/api-contract.gen.ts', import.meta.url), 'utf8');
109
+ expect(snapshot).toContain('Если не передан, сервер подбирает его по доле вырезанных касаний');
110
+ const before = structuredClone(registry);
111
+ for (const definition of toolDefinitions) {
112
+ const tool = registry.tools.find((entry) => entry.name === definition.name);
113
+ expect(tool, definition.name).toBeDefined();
114
+ syncSchemaDescriptions(tool.inputSchema, z.toJSONSchema(definition.schema, options));
115
+ }
116
+ const horizon = registry.tools.find(
117
+ (entry) => entry.name === 'besales_followup_reactions',
118
+ ).inputSchema.properties.horizon_minutes;
119
+ const definition = toolDefinitions.find((entry) => entry.name === 'besales_followup_reactions');
120
+ expect(horizon.description).toBe(
121
+ z.toJSONSchema(definition.schema, options).properties.horizon_minutes.description,
122
+ );
123
+ expect(horizon.description).toContain('Если не передан, сервер подбирает горизонт');
124
+ expect(horizon.description).not.toMatch(/по умолчанию 90/iu);
125
+ const withoutDescriptions = (value) => {
126
+ if (Array.isArray(value)) return value.map(withoutDescriptions);
127
+ if (!value || typeof value !== 'object') return value;
128
+ return Object.fromEntries(
129
+ Object.entries(value)
130
+ .filter(([key, child]) => key !== 'description' || typeof child !== 'string')
131
+ .map(([key, child]) => [key, withoutDescriptions(child)]),
132
+ );
133
+ };
134
+ expect(withoutDescriptions(registry)).toEqual(withoutDescriptions(before));
135
+ const generated = structuredClone(registry);
136
+ for (const definition of toolDefinitions) {
137
+ syncSchemaDescriptions(
138
+ registry.tools.find((entry) => entry.name === definition.name).inputSchema,
139
+ z.toJSONSchema(definition.schema, options),
140
+ );
141
+ }
142
+ expect(registry).toEqual(generated);
143
+ });
144
+ });
@@ -0,0 +1,161 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { z } from 'zod';
3
+ import { syncSchemaDescriptions } from './sync-schema-descriptions.mjs';
4
+ const { v15DescriptionUpdates } = await import(process.env.BESALES_MCP_SCHEMA_SOURCE === '1'
5
+ ? '../src/tools/definitions/v15-port-descriptions.ts' : '../dist/tools/definitions/v15-port-descriptions.js');
6
+ const { toolDefinitions } = await import(process.env.BESALES_MCP_SCHEMA_SOURCE === '1'
7
+ ? '../src/tools/definitions.ts' : '../dist/tools/definitions.js');
8
+ const { MODEL_COMPARISON_MAX_MODELS } = await import(process.env.BESALES_MCP_SCHEMA_SOURCE === '1'
9
+ ? '../src/tools/definitions/model-comparison.ts' : '../dist/tools/definitions/model-comparison.js');
10
+
11
+ // Меняются только узлы этой поправки: описания остальных инструментов сохраняются.
12
+ const registryPath = new URL('../src/schemas/mcp-tools.json', import.meta.url);
13
+ const original = readFileSync(registryPath, 'utf8');
14
+ const registry = JSON.parse(original);
15
+ const selected = {
16
+ besales_model_comparison_run_start: ['models'],
17
+ besales_agent_list: ['query'],
18
+ besales_contact_search: ['phone', 'email', 'external_id'],
19
+ besales_trigger_upsert: ['allow_repeated_calls', 'run_once_per_contact'],
20
+ besales_trigger_claim_list: ['contact_id', 'chat_user_id'],
21
+ besales_broadcast_analytics_get: ['reason'],
22
+ besales_dialogue_audit_findings: ['agent_id'],
23
+ besales_dialogue_audit_import: ['findings.items.category', 'findings.items.severity', 'findings.items.expected_behavior'],
24
+ ...Object.fromEntries(['document','qa','table','website'].map((kind) => [`besales_knowledge_${kind}_list`, ['page']])),
25
+ };
26
+ const constraints = ['type','format','enum','const','minLength','maxLength','minimum','maximum','minItems','maxItems','default'];
27
+ function node(root, key, create = false) {
28
+ const parts = key.split('.');
29
+ let parent = root;
30
+ for (const part of parts.slice(0,-1)) {
31
+ if (part === 'items') parent = parent.items;
32
+ else parent = parent.properties[part];
33
+ }
34
+ parent.properties ??= {};
35
+ const last = parts.at(-1);
36
+ if (create) parent.properties[last] ??= {};
37
+ return { parent, last, value: parent.properties[last] };
38
+ }
39
+ for (const [name, keys] of Object.entries(selected)) {
40
+ const tool = registry.tools.find((entry) => entry.name === name);
41
+ const definition = toolDefinitions.find((entry) => entry.name === name);
42
+ if (!tool || !definition) throw new Error(`Нет инструмента ${name}`);
43
+ const derived = z.toJSONSchema(definition.schema, { io: 'input' });
44
+ for (const key of keys) {
45
+ const source = node(derived, key).value;
46
+ if (!source) throw new Error(`${name}.${key} отсутствует в zod`);
47
+ const destination = node(tool.inputSchema, key, true).value;
48
+ for (const field of constraints) {
49
+ delete destination[field];
50
+ if (source[field] !== undefined && !(['minimum','maximum'].includes(field) &&
51
+ Math.abs(source[field]) === Number.MAX_SAFE_INTEGER)) destination[field] = source[field];
52
+ }
53
+ }
54
+ if (name === 'besales_dialogue_audit_findings') {
55
+ // В v1.5 это уже был UUID: возвращаем прежний контракт, без нового pattern.
56
+ const agent = tool.inputSchema.properties.agent_id;
57
+ delete agent.pattern;
58
+ agent.description = node(derived, 'agent_id').value.description;
59
+ }
60
+ if (name === 'besales_trigger_claim_list') tool.inputSchema.required = [];
61
+ if (name.startsWith('besales_knowledge_') && name.endsWith('_list')) {
62
+ tool.description = tool.description.replace(/page\/limit применяются локально MCP-клиентом[^.]*\.?/gu, 'limit и cursor передаются серверу.');
63
+ delete tool.inputSchema.properties.limit.default;
64
+ tool.inputSchema.properties.page.description = 'Прежний page отвергается до запроса: продолжайте по cursor из предыдущего ответа.';
65
+ }
66
+ }
67
+ const search = registry.tools.find((entry) => entry.name === 'besales_contact_search');
68
+ const comparison = registry.tools.find((entry) => entry.name === 'besales_model_comparison_run_start');
69
+ comparison.description = comparison.description.replace(/1\.\.\d+/gu, `1..${MODEL_COMPARISON_MAX_MODELS}`);
70
+ comparison.inputSchema.properties.models.description = comparison.inputSchema.properties.models.description.replace(/1\.\.\d+/gu, `1..${MODEL_COMPARISON_MAX_MODELS}`);
71
+ search.inputSchema.properties.email.description = 'Один email или CSV почт через запятую; предел всей строки 8192.';
72
+ search.inputSchema.properties.phone.description = 'Один телефон или CSV телефонов через запятую, международный формат. Национальная запись не переписывается (8 не заменяется на +7); предел всей строки 8192.';
73
+ const claims = registry.tools.find((entry) => entry.name === 'besales_trigger_claim_list');
74
+ claims.inputSchema.properties.chat_user_id.description = 'Прежнее имя contact_id. Передайте одно имя или одинаковые значения; разные адреса отвергаются.';
75
+ const triggers = registry.tools.find((entry) => entry.name === 'besales_trigger_upsert');
76
+ triggers.inputSchema.properties.allow_repeated_calls.description = 'Прежний флаг повтора: переводится маппером переноса в allow_repeat_in_conversation. run_once_per_contact=true имеет приоритет; горизонт новой системы — переписка, не контакт навсегда.';
77
+ triggers.inputSchema.properties.run_once_per_contact.description = 'Прежняя однократность: true переводится в allow_repeat_in_conversation=false. После закрытия переписки право возвращается; повтор в CRM возможен. Не смешивайте с новым именем.';
78
+ // SATMCPB: обновляем только перенесённые поля; ручные allOf и остальной контракт сохраняются.
79
+ const portFields = {
80
+ besales_getcourse_wave_import: ['channels', 'funnel'],
81
+ besales_getcourse_wave_run_start: ['channels', 'funnel'],
82
+ besales_getcourse_wave_run_batch_start: ['segments.items.channels', 'segments.items.funnel'],
83
+ };
84
+ for (const name of new Set([...Object.keys(portFields), ...Object.keys(v15DescriptionUpdates), 'besales_broadcast_schedule_upsert'])) {
85
+ const tool = registry.tools.find((entry) => entry.name === name);
86
+ const definition = toolDefinitions.find((entry) => entry.name === name);
87
+ if (!tool || !definition) throw new Error('PORT_TOOL_MISSING:' + name);
88
+ const derived = z.toJSONSchema(definition.schema, { io: 'input', target: 'draft-7' });
89
+ syncSchemaDescriptions(tool.inputSchema, derived);
90
+ for (const field of portFields[name] ?? []) {
91
+ const source = node(derived, field).value;
92
+ if (!source) throw new Error('PORT_FIELD_MISSING:' + name + '.' + field);
93
+ const target = node(tool.inputSchema, field, true);
94
+ // Nullable оформляем как type:[T,null], чтобы опись видела границы значения.
95
+ const nonNull = source.anyOf?.find((branch) => branch.type !== 'null');
96
+ const nullable = source.anyOf?.length === 2 && source.anyOf.some((branch) => branch.type === 'null');
97
+ if (nullable && nonNull && ['string', 'integer'].includes(nonNull.type)) {
98
+ const { anyOf: _branches, ...metadata } = source;
99
+ target.parent.properties[target.last] = { ...nonNull, ...metadata, type: [nonNull.type, 'null'] };
100
+ } else target.parent.properties[target.last] = source;
101
+ }
102
+ // Снимаем прежние подсказки перед добавлением исправленных: повторный sync идемпотентен.
103
+ if (name === 'besales_broadcast_analytics_get' && !tool.description.includes(v15DescriptionUpdates[name].append)) {
104
+ tool.description = tool.description.replace('mode=range требует полный упорядоченный диапазон from/to. Параметры должны поддерживаться выбранным report; payment_candidates: page_size не больше 100. payment_view можно сочетать с payment_status/payment_eligibility: API отдаёт приоритет view.', '').replace('mode=range принимает открытый диапазон: только from, только to или обе границы; если заданы обе, to не раньше from. Параметры должны поддерживаться выбранным report; payment_candidates: page_size не больше 100. payment_view можно сочетать с payment_status/payment_eligibility: API отдаёт приоритет view.', '').trim();
105
+ }
106
+ if (name === 'besales_broadcast_schedule_runs') {
107
+ tool.description = tool.description.replace(/Снятые из-за переменных блоки: excludedBy\.blockPlaceholdersUnresolved, исход SKIPPED_UNRESOLVED_VARS и пауза 6 часов; имена переменных — в причине строк журнала\./u, 'Снятие БЛОКА планом из-за переменных: excludedBy.blockPlaceholdersUnresolved, исход SKIPPED_UNRESOLVED_VARS и пауза 6 часов (при отправке отдельному человеку пауза сутки); имена переменных — в причине строк журнала.');
108
+ }
109
+ const update = v15DescriptionUpdates[name];
110
+ if (update) {
111
+ for (const [from, to] of update.replace ?? []) tool.description = tool.description.replace(from, to);
112
+ if (!tool.description.includes(update.append)) tool.description += ' ' + update.append;
113
+ }
114
+ }
115
+ // Условная схема архивации тоже обязана объявлять boolean для const:true.
116
+ const archive = registry.tools.find((entry) => entry.name === 'besales_broadcast_mailing_variant_update');
117
+ archive.inputSchema.if.properties.archived = z.toJSONSchema(z.literal(true), { io: 'input' });
118
+ delete archive.inputSchema.if.properties.archived.$schema;
119
+ // Сохраняем остальные условия фасада. Потолок берётся из выделенного списка оплат.
120
+ const facade = registry.tools.find((entry) => entry.name === 'besales_broadcast_analytics_get');
121
+ delete facade.inputSchema.properties.mode.default;
122
+ const pageSize = registry.tools.find((entry) => entry.name === 'besales_broadcast_payment_candidates_list').inputSchema.properties.page_size;
123
+ const pageCap = {
124
+ if: { properties: { report: { const: 'payment_candidates' } }, required: ['report'] },
125
+ then: { properties: { page_size: { type: 'integer', minimum: pageSize.minimum, maximum: pageSize.maximum } } },
126
+ };
127
+ facade.inputSchema.allOf = (facade.inputSchema.allOf ?? []).filter((rule) => rule.if?.properties?.report?.const !== 'payment_candidates');
128
+ facade.inputSchema.allOf.push(pageCap);
129
+ facade.inputSchema.allOf = facade.inputSchema.allOf.filter((rule) => rule.if?.properties?.mode?.const !== 'range');
130
+ facade.inputSchema.allOf.push({
131
+ if: { properties: { report: { enum: ['payment_candidates', 'payment_candidates_summary'] }, mode: { const: 'range' } }, required: ['report', 'mode'] },
132
+ then: { anyOf: [{ required: ['from'] }, { required: ['to'] }] },
133
+ });
134
+ const findings = registry.tools.find((entry) => entry.name === 'besales_dialogue_audit_findings');
135
+ const agentScopeHint = 'agent_id необязателен: мост сначала читает разбор (besales_dialogue_audit_run_get) и сверяет agentId; при несовпадении — «разбор относится к другому агенту», без запроса находок. Без agent_id находки читаются сразу.';
136
+ findings.description = findings.description.replace('⛔ Фильтра по агенту у инструмента нет: прогон v2 принадлежит ОДНОМУ агенту, и фильтр невыразим. Чей это прогон — покажет besales_dialogue_audit_run_get.', agentScopeHint);
137
+ if (!findings.description.includes(agentScopeHint)) findings.description += ' ' + agentScopeHint;
138
+ // Владельцы и ссылки описи воспроизводятся вместе со схемами. ACTIVE-решения
139
+ // для новых точных ключей ратифицируются в API, а не выдумываются генератором.
140
+ const lagPath = new URL('../src/schemas/shipped-lag.json', import.meta.url);
141
+ const lagOriginal = readFileSync(lagPath, 'utf8');
142
+ const lag = JSON.parse(lagOriginal);
143
+ const channelDecisions = {
144
+ besales_getcourse_wave_import: '6.19.51:ratification-e91ef72931a8',
145
+ besales_getcourse_wave_run_batch_start: '6.19.51:ratification-dd43ed6fe094',
146
+ besales_getcourse_wave_run_start: '6.19.51:ratification-f32263f46446',
147
+ };
148
+ for (const [key, row] of Object.entries(lag.contractLag)) {
149
+ const id = channelDecisions[key.split('::')[0]];
150
+ if (id && key.includes('channels[]#enum')) {
151
+ row.owner = 'DELIBERATE';
152
+ row.severity = 'DELIBERATE';
153
+ row.reason = row.reason.replace(/decision:[^\s;,]+/gu, 'decision:' + id);
154
+ }
155
+ }
156
+ for (const [path, before, value] of [[registryPath, original, registry], [lagPath, lagOriginal, lag]]) {
157
+ const output = JSON.stringify(value, null, 2) + '\n';
158
+ if (process.argv.includes('--check')) {
159
+ if (before !== output) throw new Error(`${path.pathname}: выполните sync-contract-ledger-schemas.mjs`);
160
+ } else writeFileSync(path, output);
161
+ }
@@ -0,0 +1,85 @@
1
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import openapiTS from 'openapi-typescript';
5
+ import { z } from 'zod';
6
+ import {
7
+ triggerActionItemSchema,
8
+ followupSequenceConfigSchema,
9
+ } from '../dist/tools/definitions/platform-setup.js';
10
+ import {
11
+ crmMoveStageConfigSchema,
12
+ stagePoolFields,
13
+ } from '../dist/tools/definitions/crm-stage-pool.schema.js';
14
+ import { CRM_STAGE_ACTION_POOL_MAX_SIZE } from '../dist/shared/constants/crm-stage-pool.constants.js';
15
+
16
+ // Каталог ссылки берётся из принятого API. Отставание соседних полей этим выпуском не снимается.
17
+ const contractsDir = process.env.BESALES_API_CONTRACTS_DIR?.trim() || '../besales-api/contracts';
18
+ let apiPool;
19
+ await openapiTS(pathToFileURL(resolve(contractsDir, 'openapi-besales-api.yaml')), {
20
+ transform(schema) {
21
+ if (
22
+ schema.properties?.step_type?.enum?.includes('CRM_MOVE_STAGE') &&
23
+ schema.properties.assign_responsible_operator_ids
24
+ )
25
+ apiPool = schema.properties.assign_responsible_operator_ids;
26
+ },
27
+ });
28
+ if (
29
+ apiPool?.type !== 'array' ||
30
+ apiPool.items?.format !== 'uuid' ||
31
+ apiPool.uniqueItems !== true ||
32
+ apiPool.minItems !== 1 ||
33
+ apiPool.maxItems !== undefined
34
+ )
35
+ throw new Error('CRM_STAGE_POOL_CONTRACT_MISSING_OR_DRIFTED');
36
+ const options = { target: 'draft-7', io: 'input' };
37
+ const stage = z.toJSONSchema(crmMoveStageConfigSchema, options);
38
+ const action = z.toJSONSchema(triggerActionItemSchema, options);
39
+ const followup = z.toJSONSchema(followupSequenceConfigSchema, options);
40
+ delete stage.$schema;
41
+ for (const name of Object.keys(stagePoolFields)) {
42
+ const property = stage.properties[name];
43
+ const array = property.anyOf.find((branch) => branch.type === 'array');
44
+ array.uniqueItems = true;
45
+ if (name === 'assign_responsible_operator_ids') array.items = apiPool.items;
46
+ followup.properties[name] = JSON.parse(JSON.stringify(property));
47
+ array.maxItems = CRM_STAGE_ACTION_POOL_MAX_SIZE;
48
+ }
49
+ const extraArray = stage.properties.extra.properties.assignResponsibleOperatorIds.anyOf.find(
50
+ (branch) => branch.type === 'array',
51
+ );
52
+ extraArray.maxItems = CRM_STAGE_ACTION_POOL_MAX_SIZE;
53
+ extraArray.uniqueItems = true;
54
+
55
+ const target = new URL('../src/schemas/mcp-tools.json', import.meta.url);
56
+ const registry = JSON.parse(readFileSync(target, 'utf8'));
57
+ const trigger = registry.tools.find((tool) => tool.name === 'besales_trigger_upsert');
58
+ const chain = registry.tools.find((tool) => tool.name === 'besales_followup_sequence_upsert');
59
+ const read = registry.tools.find((tool) => tool.name === 'besales_followup_sequence_list');
60
+ if (
61
+ !trigger?.inputSchema?.properties?.actions?.items?.properties?.config ||
62
+ !chain?.inputSchema?.properties?.config ||
63
+ !read?.inputSchema?.properties
64
+ )
65
+ throw new Error('CRM_STAGE_POOL_TOOL_MISSING');
66
+ const item = trigger.inputSchema.properties.actions.items;
67
+ item.properties.type = action.properties.type;
68
+ for (const container of ['crmConfig', 'crmMoveStage', 'crmMoveStageConfig'])
69
+ item.properties[container] = stage;
70
+ for (const name of Object.keys(stagePoolFields)) {
71
+ item.properties.config.properties[name] = stage.properties[name];
72
+ chain.inputSchema.properties.config.properties[name] = followup.properties[name];
73
+ }
74
+ item.properties.config.properties.extra = stage.properties.extra;
75
+ read.description = read.description.replace(
76
+ 'Отдаёт РЕЗУЛЬТАТ трансляции (какие шаги реально исполняются), а не вход besales_followup_sequence_upsert: конфигурацию в форме v1.5 инструмент не возвращает.',
77
+ 'С sequence_id возвращает сохранённые type, trigger, config и configUnavailableReason для правки. Пул сохраняется в config без сортировки. При config=null требуется полное восстановление формы; latestVersion.steps не подставляют в config.',
78
+ );
79
+ const hint = stagePoolFields.assign_responsible_operator_ids.description;
80
+ for (const tool of [trigger, chain])
81
+ if (!tool.description.includes(hint)) tool.description += ` ${hint}`;
82
+ const serialized = `${JSON.stringify(registry, null, 2)}\n`;
83
+ writeFileSync(target, serialized);
84
+ mkdirSync(new URL('../dist/schemas/', import.meta.url), { recursive: true });
85
+ writeFileSync(new URL('../dist/schemas/mcp-tools.json', import.meta.url), serialized);
@@ -0,0 +1,92 @@
1
+ import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
2
+ import { z } from 'zod';
3
+
4
+ /** Меняются только входы выбора: остальные принятые определения сохраняют свои подписи. */
5
+ const target = new URL('../src/schemas/mcp-tools.json', import.meta.url);
6
+ const registry = JSON.parse(readFileSync(target, 'utf8'));
7
+ mkdirSync(new URL('../dist/schemas/', import.meta.url), { recursive: true });
8
+ writeFileSync(new URL('../dist/schemas/mcp-tools.json', import.meta.url), JSON.stringify(registry));
9
+ const { toolDefinitions } = await import('../dist/tools/definitions.js');
10
+ const names = ['besales_prompt_patch_start', 'besales_prompt_drafts_mine'];
11
+ for (const name of names) {
12
+ const definition = toolDefinitions.find((tool) => tool.name === name);
13
+ if (!definition) throw new Error('Missing prompt draft tool: ' + name);
14
+ const generated = z.toJSONSchema(definition.schema, {
15
+ target: 'draft-7',
16
+ io: 'input',
17
+ });
18
+ delete generated.$schema;
19
+ let contract = registry.tools.find((tool) => tool.name === name);
20
+ if (!contract) {
21
+ contract = {
22
+ name,
23
+ description:
24
+ 'Мои черновики по агенту: текущий ACTIVE отдельно от страницы истории; только metadata без текста.',
25
+ inputSchema: generated,
26
+ executionMode: 'proxy',
27
+ };
28
+ const position = toolDefinitions.findIndex((tool) => tool.name === name);
29
+ const previous = toolDefinitions[position - 1].name;
30
+ registry.tools.splice(
31
+ registry.tools.findIndex((tool) => tool.name === previous) + 1,
32
+ 0,
33
+ contract,
34
+ );
35
+ } else if (name === 'besales_prompt_patch_start') {
36
+ for (const field of ['mode', 'draft_id', 'expected_content_hash'])
37
+ contract.inputSchema.properties[field] = generated.properties[field];
38
+ contract.description =
39
+ 'Начать черновик. CREATED / CONTINUED обозначают успех; CHOICE_REQUIRED требует явного выбора автора через mode, draft_id и expected_content_hash. Чужие конфликты возвращаются числом conflictingDraftCount.';
40
+ } else {
41
+ contract.inputSchema = generated;
42
+ contract.description =
43
+ 'Мои черновики по агенту: текущий ACTIVE отдельно от страницы истории; только metadata без текста.';
44
+ }
45
+ }
46
+ const serialized = JSON.stringify(registry, null, 2) + '\n';
47
+ writeFileSync(target, serialized);
48
+ mkdirSync(new URL('../dist/schemas/', import.meta.url), { recursive: true });
49
+ writeFileSync(new URL('../dist/schemas/mcp-tools.json', import.meta.url), serialized);
50
+
51
+ const routeTarget = new URL('../src/schemas/mcp-v2-route-map.json', import.meta.url);
52
+ const routes = JSON.parse(readFileSync(routeTarget, 'utf8'));
53
+ const mine = toolDefinitions.find((tool) => tool.name === 'besales_prompt_drafts_mine');
54
+ const canonicalArgs = { agent_id: '00000000-0000-4000-8000-000000000002' };
55
+ const request = mine.createRequest(mine.schema.parse(canonicalArgs));
56
+ const entry = {
57
+ tool: mine.name,
58
+ canonicalArgs,
59
+ expected: {
60
+ method: request.method,
61
+ pathTemplate: '/agents/:agentId/prompt/drafts/mine',
62
+ path: request.path,
63
+ },
64
+ };
65
+ const index = routes.findIndex((row) => row.tool === mine.name);
66
+ if (index < 0) routes.push(entry);
67
+ else routes[index] = entry;
68
+ writeFileSync(routeTarget, JSON.stringify(routes, null, 2) + '\n');
69
+
70
+ const { toolInventoryCounts, renderToolInventoryMarkdown } =
71
+ await import('../dist/tools/inventory.js');
72
+ const activeNames = registry.tools.map((tool) => tool.name);
73
+ registry.summary.total_tools = activeNames.length;
74
+ registry.summary.tools_by_category = toolInventoryCounts(activeNames);
75
+ const completeRegistry = JSON.stringify(registry, null, 2) + '\n';
76
+ writeFileSync(target, completeRegistry);
77
+ writeFileSync(new URL('../dist/schemas/mcp-tools.json', import.meta.url), completeRegistry);
78
+ const readmeTarget = new URL('../README.md', import.meta.url);
79
+ const readme = readFileSync(readmeTarget, 'utf8');
80
+ const startMarker = '<!-- BEGIN GENERATED TOOL INVENTORY -->';
81
+ const endMarker = '<!-- END GENERATED TOOL INVENTORY -->';
82
+ const start = readme.indexOf(startMarker),
83
+ end = readme.indexOf(endMarker);
84
+ if (start < 0 || end < start) throw new Error('README inventory markers missing');
85
+ writeFileSync(
86
+ readmeTarget,
87
+ readme.slice(0, start + startMarker.length) +
88
+ '\n' +
89
+ renderToolInventoryMarkdown(activeNames) +
90
+ '\n' +
91
+ readme.slice(end),
92
+ );
@@ -0,0 +1,94 @@
1
+ // Пересобирает только карту и локальные доказательства маршрутов; API остаётся входом.
2
+ import { execFileSync } from 'node:child_process';
3
+ import { createHash } from 'node:crypto';
4
+ import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
5
+ import { resolve } from 'node:path';
6
+ import { sampleFor, resetSampleUid } from './sample-args.mjs';
7
+ const contracts = process.env.BESALES_API_CONTRACTS_DIR?.trim();
8
+ if (!contracts) throw new Error('BESALES_API_CONTRACTS_DIR обязателен: contracts/ выбранного API');
9
+ const apiFile = resolve(contracts, 'openapi-besales-api.yaml');
10
+ const apiText = readFileSync(apiFile, 'utf8');
11
+ if (/^(?:<<<<<<<|=======|>>>>>>>)/mu.test(apiText)) throw new Error('OPENAPI_MERGE_CONFLICT');
12
+ const { toolDefinitions } = await import('../dist/tools/definitions.js');
13
+ copyFileSync(new URL('../src/schemas/mcp-v2-route-map.json', import.meta.url), new URL('../dist/schemas/mcp-v2-route-map.json', import.meta.url));
14
+ const { mappingCases } = await import('../dist/tools/registry-mapping.cases.js');
15
+ const registry = JSON.parse(readFileSync(new URL('../src/schemas/mcp-tools.json', import.meta.url), 'utf8'));
16
+ const known = new Map(registry.tools.map((tool) => [tool.name, tool]));
17
+ const routeFile = new URL('../src/schemas/mcp-v2-route-map.json', import.meta.url);
18
+ const original = readFileSync(routeFile, 'utf8');
19
+ const rows = JSON.parse(original);
20
+ // Справочники не принимают фильтр периода: прежний образец mode=all стал недопустим.
21
+ for (const row of rows) {
22
+ if (['besales_broadcast_analytics_get@segments_catalog', 'besales_broadcast_analytics_get@funnel_products'].includes(row.tool)) delete row.canonicalArgs.mode;
23
+ }
24
+ const definitions = new Map(toolDefinitions.map((definition) => [definition.name, definition]));
25
+ const snapshot = readFileSync(new URL('../src/types/api-contract.gen.ts', import.meta.url), 'utf8');
26
+ const paths = [...snapshot.matchAll(/^ {4}"(\/[^"]*)":\s*\{\n([\s\S]*?)^ {4}\};$/gm)].map((block) => ({
27
+ path: block[1], methods: new Set([...block[2].matchAll(/^ {8}([a-z]+):[ \t]*(\S[^\n]*)/gm)].filter((match) => !/^never\b/u.test(match[2])).map((match) => match[1].toUpperCase())),
28
+ regex: new RegExp('^' + block[1].split('/').map((part) => part.startsWith('{') ? '[^/]+' : part.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&')).join('/') + '$'),
29
+ })).sort((a, b) => (a.path.match(/\{/gu)?.length ?? 0) - (b.path.match(/\{/gu)?.length ?? 0));
30
+ // Маршрут намеренно исключён из публичного OpenAPI, но зарегистрирован в текущем API.
31
+ const privateController = resolve(contracts, '../src/control/channel/crm-webhook-url-reveal.controller.ts');
32
+ const privateModule = resolve(contracts, '../src/control/channel/channel.module.ts');
33
+ const controllerSource = readFileSync(privateController, 'utf8');
34
+ const moduleSource = readFileSync(privateModule, 'utf8');
35
+ const controller = /@Controller\('([^']+)'\)/u.exec(controllerSource);
36
+ if (!controller || !/@Post\(\)/u.test(controllerSource) || !/@HiddenFromPublicDocs/u.test(controllerSource) || !/controllers:\s*\[[\s\S]*?CrmWebhookUrlRevealController/u.test(moduleSource)) throw new Error('PRIVATE_CRM_ROUTE_NOT_REGISTERED');
37
+ const privatePath = '/api/v2/' + controller[1];
38
+ paths.push({ path: privatePath, methods: new Set(['POST']), regex: new RegExp('^' + privatePath + '$'), private: true });
39
+ const initialRows = JSON.parse(execFileSync('git', ['show', 'HEAD:src/schemas/mcp-v2-route-map.json'], { encoding: 'utf8' }));
40
+ const initialByName = new Map(initialRows.map((row) => [row.tool, row]));
41
+ const errors = [];
42
+ const changes = [];
43
+ for (const definition of toolDefinitions) {
44
+ if (!definition.createRequest || rows.some((row) => row.tool.split('@')[0] === definition.name)) continue;
45
+ resetSampleUid();
46
+ const schema = known.get(definition.name).inputSchema;
47
+ const args = mappingCases.find((row) => row.name === definition.name)?.input ?? sampleFor(definition.name, schema, true);
48
+ if (definition.name === 'besales_feedback_document_access_update') args.expected_document_snapshot = 'a'.repeat(64);
49
+ rows.push({ tool: definition.name, canonicalArgs: args });
50
+ }
51
+ for (const row of rows) {
52
+ const definition = definitions.get(row.tool.split('@')[0]);
53
+ try {
54
+ const input = definition.schema.parse(row.canonicalArgs);
55
+ const request = definition.createRequest(input);
56
+ const url = new URL(request.path, 'https://api.test');
57
+ const method = request.method ?? 'POST';
58
+ const route = paths.find((candidate) => candidate.regex.test('/api/v2' + url.pathname) && candidate.methods.has(method));
59
+ if (!route) throw new Error(`API_ROUTE_MISSING:${method} ${url.pathname}`);
60
+ const query = {};
61
+ for (const key of new Set(url.searchParams.keys())) {
62
+ const values = url.searchParams.getAll(key);
63
+ query[key] = values.length === 1 ? values[0] : values;
64
+ }
65
+ const expected = { method, path: url.pathname, pathTemplate: route.path.slice('/api/v2'.length).replace(/\{([^}]+)\}/gu, ':$1') };
66
+ if (Object.keys(query).length) expected.query = query;
67
+ if (request.body instanceof FormData) {
68
+ const fields = {};
69
+ let file;
70
+ for (const [key, value] of request.body.entries()) {
71
+ if (typeof value === 'string') fields[key] = value;
72
+ else file = { fieldName: key, filename: value.name, contentType: value.type, content: await value.text() };
73
+ }
74
+ expected.multipart = { fields, file };
75
+ } else if (request.body !== undefined) expected.body = request.body;
76
+ const before = initialByName.get(row.tool)?.expected;
77
+ if (before && (before.method !== method || before.pathTemplate !== expected.pathTemplate)) changes.push({ tool: row.tool, before: before.method + ' ' + before.pathTemplate, after: method + ' ' + expected.pathTemplate });
78
+ if (row.tool.startsWith('besales_dialogue_audit_run_start@')) expected.body.idempotencyKey = '00000000-0000-4000-8000-000000000090';
79
+ row.expected = expected;
80
+ if (route.private) { delete row.backendTarget; row.contractVisibility = 'CUSTOMER'; }
81
+ else row.backendTarget = 'besales-api';
82
+ } catch (error) { errors.push({ tool: row.tool, error: String(error) }); }
83
+ }
84
+ const artifactDir = new URL('../.codex-artifacts-bridge-train2/', import.meta.url);
85
+ mkdirSync(artifactDir, { recursive: true });
86
+ const payload = { privateRoutes: [{ method: 'POST', path: privatePath, controller: privateController, sha256: createHash('sha256').update(controllerSource).digest('hex') }], source: 'working-tree', apiOpenApi: apiFile, apiSha256: createHash('sha256').update(apiText).digest('hex'), apiHead: execFileSync('git', ['-C', resolve(contracts, '..'), 'rev-parse', 'HEAD'], { encoding: 'utf8' }).trim(), totalTools: toolDefinitions.length, localTools: toolDefinitions.filter((tool) => !tool.createRequest).map((tool) => tool.name), checkedApiTools: new Set(rows.map((row) => row.tool.split('@')[0])).size, records: rows.length, changes, errors };
87
+ writeFileSync(new URL('route-audit.json', artifactDir), JSON.stringify(payload, null, 2) + '\n');
88
+ writeFileSync(new URL('mcp-tool-routes.json', artifactDir), JSON.stringify({ ...payload, tools: rows }, null, 2) + '\n');
89
+ if (errors.length) { console.error(JSON.stringify(errors, null, 2)); throw new Error(`API_ROUTE_AUDIT_FAILED:${errors.length}`); }
90
+ const output = JSON.stringify(rows, null, 2) + '\n';
91
+ if (process.argv.includes('--check')) {
92
+ if (original !== output) throw new Error('Карта разошлась с определениями: выполните sync-route-map.mjs');
93
+ } else writeFileSync(routeFile, output);
94
+ console.log(`API route audit: ${payload.checkedApiTools} API tools, ${rows.length} variants; missing 0`);
@@ -0,0 +1,25 @@
1
+ // Обновляем только описания совпадающих узлов JSON Schema. Ограничения каталога,
2
+ // в том числе ручные allOf для superRefine, не заменяются выводом Zod.
3
+ export function syncSchemaDescriptions(target, derived) {
4
+ if (!target || !derived || typeof target !== 'object' || typeof derived !== 'object') return;
5
+ if (typeof derived.description === 'string') target.description = derived.description;
6
+
7
+ for (const keyword of ['properties', 'patternProperties', '$defs', 'definitions', 'dependentSchemas']) {
8
+ for (const name of Object.keys(target[keyword] ?? {})) {
9
+ syncSchemaDescriptions(target[keyword][name], derived[keyword]?.[name]);
10
+ }
11
+ }
12
+ for (const keyword of [
13
+ 'items', 'additionalProperties', 'additionalItems', 'contains', 'propertyNames',
14
+ 'not', 'if', 'then', 'else', 'unevaluatedProperties', 'unevaluatedItems',
15
+ ]) {
16
+ if (!Array.isArray(target[keyword]) && !Array.isArray(derived[keyword])) {
17
+ syncSchemaDescriptions(target[keyword], derived[keyword]);
18
+ }
19
+ }
20
+ for (const keyword of ['items', 'prefixItems', 'allOf', 'anyOf', 'oneOf']) {
21
+ if (Array.isArray(target[keyword]) && Array.isArray(derived[keyword])) {
22
+ target[keyword].forEach((schema, index) => syncSchemaDescriptions(schema, derived[keyword][index]));
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,27 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import ts from 'typescript';
3
+
4
+ const source = readFileSync(new URL('../src/tools/inventory.ts', import.meta.url), 'utf8');
5
+ const compiled = ts.transpileModule(source, {
6
+ compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 },
7
+ }).outputText;
8
+ const { renderToolInventoryMarkdown, toolInventoryCounts } = await import(
9
+ 'data:text/javascript;base64,' + Buffer.from(compiled).toString('base64')
10
+ );
11
+ const schemaUrl = new URL('../src/schemas/mcp-tools.json', import.meta.url);
12
+ const schema = JSON.parse(readFileSync(schemaUrl, 'utf8'));
13
+ const names = schema.tools.filter((tool) => tool.status !== 'removed').map((tool) => tool.name);
14
+ schema.summary.total_tools = names.length;
15
+ schema.summary.tools_by_category = toolInventoryCounts(names);
16
+ writeFileSync(schemaUrl, JSON.stringify(schema, null, 2) + '\n');
17
+ const readmeUrl = new URL('../README.md', import.meta.url);
18
+ const readme = readFileSync(readmeUrl, 'utf8');
19
+ const begin = '<!-- BEGIN GENERATED TOOL INVENTORY -->';
20
+ const end = '<!-- END GENERATED TOOL INVENTORY -->';
21
+ const first = readme.indexOf(begin), last = readme.indexOf(end);
22
+ if (first < 0 || last < first) throw new Error('README inventory markers missing');
23
+ writeFileSync(
24
+ readmeUrl,
25
+ readme.slice(0, first + begin.length) + '\n\n' +
26
+ renderToolInventoryMarkdown(names) + '\n\n' + readme.slice(last),
27
+ );