@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,197 @@
1
+ // Загрузчик ОТГРУЖЕННЫХ определений инструментов: исходник эталона извлекается из git в кэш внутри моста,
2
+ // переводится в JavaScript без проверки типов и импортируется.
3
+ //
4
+ // ⭐ Зачем. Образец отгруженного вызова обязан пройти ФИЛЬТР отгруженного инструмента (схему zod и конструктор
5
+ // запроса), а не только его JSON-схему: полный набор полей часто не является вызовом, который клиент вообще может
6
+ // послать (взаимоисключающие поля), и сверка «примет ли v2 то, что шлёт клиент» на таком наборе отвечает не на тот
7
+ // вопрос. Рукописный список взаимоисключений был бы второй копией правил и не видел бы случаев, где v2 строже.
8
+ //
9
+ // ⛔ Кэш лежит ВНУТРИ `node_modules` моста: голые импорты (`zod`) из извлечённого исходника разрешаются поиском вверх
10
+ // по каталогам, и снаружи они не нашлись бы. Версии этих зависимостей сверяются с отгруженным `package.json`: фильтр,
11
+ // исполненный на чужой версии библиотеки, отвечал бы не так, как у клиента.
12
+ import { execFileSync } from 'node:child_process';
13
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
14
+ import { dirname, join, posix, relative } from 'node:path';
15
+ import { pathToFileURL } from 'node:url';
16
+
17
+ import ts from 'typescript';
18
+
19
+ /** Вход определений инструментов на отгружаемой линии. */
20
+ export const SHIPPED_DEFINITIONS_ENTRY = 'src/tools/definitions.ts';
21
+ const CACHE_SUBDIR = 'node_modules/.cache/besales-shipped-src';
22
+ const COMPLETE_MARKER = '.complete.json';
23
+ /** Версия способа перевода: кэш, собранный другим способом, пересобирается, а не исполняется. */
24
+ const LOADER_VERSION = 1;
25
+
26
+ /**
27
+ * Относительные импорты исходника (`./x.js` → `./x.ts`). Типовые импорты тоже входят: замыкание — вход СВЕЖЕСТИ
28
+ * выгрузки, и чувствительность к лишнему файлу безопаснее слепоты к нужному.
29
+ */
30
+ function relativeImports(sourceText) {
31
+ return ts
32
+ .preProcessFile(sourceText, true, true)
33
+ .importedFiles.map((file) => file.fileName)
34
+ .filter((specifier) => specifier.startsWith('./') || specifier.startsWith('../'));
35
+ }
36
+
37
+ /** Голые импорты ИСПОЛНЯЕМОГО кода (после перевода типовые импорты исчезают). */
38
+ function bareImports(javascriptText) {
39
+ return ts
40
+ .preProcessFile(javascriptText, true, true)
41
+ .importedFiles.map((file) => file.fileName)
42
+ .filter((specifier) => !specifier.startsWith('.') && !specifier.startsWith('node:'));
43
+ }
44
+
45
+ /** Имя пакета из спецификатора: `zod/v4` → `zod`, `@scope/pkg/sub` → `@scope/pkg`. */
46
+ export function packageNameOf(specifier) {
47
+ const parts = specifier.split('/');
48
+ return specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
49
+ }
50
+
51
+ /**
52
+ * Замыкание относительных импортов от входа — пути от корня репозитория, по порядку.
53
+ *
54
+ * ⛔ Неразрешимый импорт роняет загрузку: пропущенный файл — это исполненный код, изменение которого не запустило бы
55
+ * срок несвежести выгрузки.
56
+ *
57
+ * @param {(repoPath: string) => string | undefined} readSource текст файла по пути от корня или `undefined`
58
+ */
59
+ export function importClosure(entry, readSource) {
60
+ const seen = new Set();
61
+ const queue = [entry];
62
+ while (queue.length > 0) {
63
+ const current = queue.shift();
64
+ if (seen.has(current)) continue;
65
+ const text = readSource(current);
66
+ if (text === undefined) throw new Error(`отгруженный исходник: нет файла ${current}`);
67
+ seen.add(current);
68
+ if (!current.endsWith('.ts')) continue;
69
+ for (const specifier of relativeImports(text)) {
70
+ const target = posix.normalize(posix.join(posix.dirname(current), specifier));
71
+ const candidates = target.endsWith('.js')
72
+ ? [target.replace(/\.js$/u, '.ts'), target]
73
+ : target.endsWith('.json')
74
+ ? [target]
75
+ : [`${target}.ts`, `${target}/index.ts`];
76
+ const resolved = candidates.find((candidate) => readSource(candidate) !== undefined);
77
+ if (resolved === undefined) {
78
+ throw new Error(`отгруженный исходник: импорт ${specifier} из ${current} не разрешается`);
79
+ }
80
+ queue.push(resolved);
81
+ }
82
+ }
83
+ return [...seen].sort();
84
+ }
85
+
86
+ /**
87
+ * Версии голых зависимостей исполняемого кода обязаны совпадать у отгруженного и у этой ветки: кэш исполняется на
88
+ * `node_modules` ветки. Расхождение — отказ, а не предупреждение.
89
+ */
90
+ export function dependencyMismatches(bareSpecifiers, shippedPackage, localPackage) {
91
+ const specOf = (pkg, name) => pkg.dependencies?.[name] ?? pkg.devDependencies?.[name];
92
+ const mismatches = [];
93
+ for (const name of [...new Set(bareSpecifiers.map(packageNameOf))].sort()) {
94
+ const shipped = specOf(shippedPackage, name);
95
+ const local = specOf(localPackage, name);
96
+ if (shipped !== local) mismatches.push(`${name}: отгружено ${shipped ?? 'нет'}, ветка ${local ?? 'нет'}`);
97
+ }
98
+ return mismatches;
99
+ }
100
+
101
+ function listFiles(root, directory, out = []) {
102
+ for (const entry of readdirSync(join(root, directory), { withFileTypes: true })) {
103
+ const path = posix.join(directory, entry.name);
104
+ if (entry.isDirectory()) listFiles(root, path, out);
105
+ else out.push(path);
106
+ }
107
+ return out;
108
+ }
109
+
110
+ /** Извлечение и перевод исходника коммита в кэш; повторный вызов с тем же коммитом берёт готовый кэш. */
111
+ function materialize(packageRoot, commit) {
112
+ const cacheDir = join(packageRoot, CACHE_SUBDIR, commit);
113
+ const marker = join(cacheDir, COMPLETE_MARKER);
114
+ if (existsSync(marker)) {
115
+ const cached = JSON.parse(readFileSync(marker, 'utf8'));
116
+ if (cached.loaderVersion === LOADER_VERSION) return { cacheDir, meta: cached };
117
+ }
118
+ rmSync(cacheDir, { recursive: true, force: true });
119
+ mkdirSync(cacheDir, { recursive: true });
120
+ const archive = execFileSync('git', ['-C', packageRoot, 'archive', '--format=tar', commit, 'src', 'package.json'], {
121
+ maxBuffer: 256 * 1024 * 1024,
122
+ stdio: ['ignore', 'pipe', 'pipe'],
123
+ });
124
+ execFileSync('tar', ['-x', '-C', cacheDir], { input: archive, stdio: ['pipe', 'ignore', 'pipe'] });
125
+ const readSource = (repoPath) => {
126
+ const absolute = join(cacheDir, repoPath);
127
+ return existsSync(absolute) ? readFileSync(absolute, 'utf8') : undefined;
128
+ };
129
+ const closure = importClosure(SHIPPED_DEFINITIONS_ENTRY, readSource);
130
+ const bare = [];
131
+ for (const repoPath of listFiles(cacheDir, 'src')) {
132
+ if (!repoPath.endsWith('.ts') || repoPath.endsWith('.d.ts') || repoPath.endsWith('.spec.ts')) continue;
133
+ const output = ts.transpileModule(readSource(repoPath), {
134
+ compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 },
135
+ fileName: repoPath,
136
+ }).outputText;
137
+ writeFileSync(join(cacheDir, repoPath.replace(/\.ts$/u, '.js')), output);
138
+ if (closure.includes(repoPath)) bare.push(...bareImports(output));
139
+ }
140
+ const meta = { loaderVersion: LOADER_VERSION, commit, closure, bareImports: [...new Set(bare)].sort() };
141
+ mkdirSync(dirname(marker), { recursive: true });
142
+ writeFileSync(marker, `${JSON.stringify(meta, null, 2)}\n`);
143
+ return { cacheDir, meta };
144
+ }
145
+
146
+ /**
147
+ * Отгруженные определения инструментов коммита эталона.
148
+ *
149
+ * @returns {Promise<{ toolDefinitions: ReadonlyArray<any>, inputPaths: string[] }>} `inputPaths` — замыкание импортов
150
+ * входа определений: по ним сервер считает свежесть выгрузки.
151
+ */
152
+ export async function loadShippedDefinitions(packageRoot, commit) {
153
+ const { cacheDir, meta } = materialize(packageRoot, commit);
154
+ const mismatches = dependencyMismatches(
155
+ meta.bareImports,
156
+ JSON.parse(readFileSync(join(cacheDir, 'package.json'), 'utf8')),
157
+ JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')),
158
+ );
159
+ if (mismatches.length > 0) {
160
+ throw new Error(
161
+ `Отгруженный фильтр нельзя исполнить на зависимостях ветки — версии разошлись:\n ${mismatches.join('\n ')}`,
162
+ );
163
+ }
164
+ const entry = join(cacheDir, SHIPPED_DEFINITIONS_ENTRY.replace(/\.ts$/u, '.js'));
165
+ const module = await import(pathToFileURL(entry).href);
166
+ if (!Array.isArray(module.toolDefinitions)) {
167
+ throw new Error(`Отгруженный ${relative(packageRoot, entry)} не экспортирует toolDefinitions`);
168
+ }
169
+ return { toolDefinitions: module.toolDefinitions, inputPaths: meta.closure };
170
+ }
171
+
172
+ /**
173
+ * Исполняемый модуль ОТГРУЖЕННОГО пакета по пути от корня (`src/tools/result.ts`) — тот же кэш и та же сверка версий
174
+ * голых зависимостей, что у определений. Нужен проверкам, которым важно поведение УСТАНОВЛЕННОГО у клиентов моста, а
175
+ * не ветки: например, как отгруженный клиент показывает модели отказ сервера.
176
+ *
177
+ * @returns {Promise<Record<string, unknown>>} пространство имён модуля
178
+ */
179
+ export async function loadShippedModule(packageRoot, commit, repoPath) {
180
+ const { cacheDir } = materialize(packageRoot, commit);
181
+ const readSource = (path) => {
182
+ const absolute = join(cacheDir, path);
183
+ return existsSync(absolute) ? readFileSync(absolute, 'utf8') : undefined;
184
+ };
185
+ const bare = importClosure(repoPath, readSource)
186
+ .filter((path) => path.endsWith('.ts'))
187
+ .flatMap((path) => bareImports(readFileSync(join(cacheDir, path.replace(/\.ts$/u, '.js')), 'utf8')));
188
+ const mismatches = dependencyMismatches(
189
+ bare,
190
+ JSON.parse(readFileSync(join(cacheDir, 'package.json'), 'utf8')),
191
+ JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8')),
192
+ );
193
+ if (mismatches.length > 0) {
194
+ throw new Error(`Отгруженный модуль нельзя исполнить на зависимостях ветки:\n ${mismatches.join('\n ')}`);
195
+ }
196
+ return import(pathToFileURL(join(cacheDir, repoPath.replace(/\.ts$/u, '.js'))).href);
197
+ }
@@ -0,0 +1,57 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { dependencyMismatches, importClosure, packageNameOf } from './shipped-definitions.mjs';
4
+
5
+ /**
6
+ * Загрузчик отгруженных определений: замыкание импортов — вход СВЕЖЕСТИ выгрузки, версии зависимостей — условие
7
+ * честного исполнения отгруженного фильтра.
8
+ */
9
+ describe('замыкание импортов отгруженных определений', () => {
10
+ const files = new Map([
11
+ ['src/tools/definitions.ts', "import { a } from './definitions/a.js';\nimport type { T } from '../types.js';"],
12
+ ['src/tools/definitions/a.ts', "import { b } from './b.js';\nimport data from '../../schemas/data.json';"],
13
+ ['src/tools/definitions/b.ts', "import { z } from 'zod';\nexport const b = z.string();"],
14
+ ['src/types.ts', 'export type T = string;'],
15
+ ['src/schemas/data.json', '{}'],
16
+ ['src/unrelated.ts', 'export const x = 1;'],
17
+ ]);
18
+ const read = (path) => files.get(path);
19
+
20
+ it('обходит относительные импорты (и типовые, и данные), голые и чужие файлы в него не входят', () => {
21
+ expect(importClosure('src/tools/definitions.ts', read)).toEqual([
22
+ 'src/schemas/data.json',
23
+ 'src/tools/definitions.ts',
24
+ 'src/tools/definitions/a.ts',
25
+ 'src/tools/definitions/b.ts',
26
+ 'src/types.ts',
27
+ ]);
28
+ });
29
+
30
+ it('⛔ неразрешимый импорт — отказ: пропущенный файл был бы исполненным кодом без срока свежести', () => {
31
+ const broken = new Map(files);
32
+ broken.set('src/tools/definitions/b.ts', "import { gone } from './gone.js';");
33
+
34
+ expect(() => importClosure('src/tools/definitions.ts', (path) => broken.get(path))).toThrow(
35
+ 'импорт ./gone.js из src/tools/definitions/b.ts не разрешается',
36
+ );
37
+ });
38
+ });
39
+
40
+ describe('версии зависимостей', () => {
41
+ it('имя пакета из спецификатора', () => {
42
+ expect(packageNameOf('zod/v4')).toBe('zod');
43
+ expect(packageNameOf('@modelcontextprotocol/sdk/types.js')).toBe('@modelcontextprotocol/sdk');
44
+ });
45
+
46
+ it('расхождение версии исполняемой зависимости — отказ с обеими версиями', () => {
47
+ expect(
48
+ dependencyMismatches(['zod', 'zod/v4'], { dependencies: { zod: '^4.4.3' } }, { dependencies: { zod: '^4.4.3' } }),
49
+ ).toEqual([]);
50
+ expect(
51
+ dependencyMismatches(['zod'], { dependencies: { zod: '^4.4.3' } }, { devDependencies: { zod: '^4.5.0' } }),
52
+ ).toEqual(['zod: отгружено ^4.4.3, ветка ^4.5.0']);
53
+ expect(dependencyMismatches(['left-pad'], { dependencies: { 'left-pad': '1.0.0' } }, {})).toEqual([
54
+ 'left-pad: отгружено 1.0.0, ветка нет',
55
+ ]);
56
+ });
57
+ });
@@ -0,0 +1,136 @@
1
+ import { readFileSync, readdirSync } from 'node:fs';
2
+
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ import { SHIPPED_INPUT_PATHS } from './shipped-registry.mjs';
6
+
7
+ /**
8
+ * Список входов выгрузки на отгружаемой линии обязан совпадать с ФАКТИЧЕСКИМИ чтениями.
9
+ *
10
+ * ⛔ Зачем сторож. Список уезжает в выгрузку и там становится входом чужой проверки: besales-api
11
+ * по нему решает, менялось ли на отгружаемой линии то, из чего собран артефакт. Добавленное
12
+ * чтение, не попавшее в список, не даст ни ошибки, ни красного теста — оно просто перестанет
13
+ * запускать срок несвежести, и проверка продолжит отвечать «свежо» на устаревшей выгрузке. То
14
+ * есть промах тут стоит ровно той слепоты, ради которой проверка и заводилась.
15
+ *
16
+ * ⛔ Разбор fail-closed. Чтение с НЕИЗВЕСТНЫМ якорем роняет тест, а не пропускается: якорь — это
17
+ * ответ на вопрос «с какой стороны читаем», и молчаливый пропуск незнакомого якоря вернул бы ту
18
+ * же дыру под другим именем.
19
+ */
20
+
21
+ /** Откуда читаем. Отгружаемая линия — входы выгрузки; ветка v2 — её собственное состояние. */
22
+ const SHIPPED_ANCHORS = new Set(['ref', 'shipped.provenance.commit']);
23
+ const V2_ANCHORS = new Set(['generatorV2Commit']);
24
+
25
+ const SOURCES = ['scripts/shipped-registry.mjs', 'scripts/emit-tool-routes.mjs'];
26
+
27
+ /** `const NAME = 'значение';` — чтобы разрешить `${NAME}` в шаблоне чтения. */
28
+ function declaredConstants(source) {
29
+ const constants = new Map();
30
+ for (const match of source.matchAll(/const\s+([A-Za-z0-9_]+)\s*=\s*'([^']+)'/gu)) {
31
+ constants.set(match[1], match[2]);
32
+ }
33
+ return constants;
34
+ }
35
+
36
+ /**
37
+ * Все чтения вида `git show <якорь>:<путь>` в исходнике.
38
+ *
39
+ * ⛔ Привязка к `'show'` обязательна: без неё в разбор попадали бы ЛЮБЫЕ шаблоны с двоеточием
40
+ * после подстановки — например текст ошибки «Не удалось обновить ${ref}: …», — и список «входов»
41
+ * заполнялся бы кусками сообщений. Обратная сторона привязки закрыта счётом ниже: чтение,
42
+ * записанное иначе, парсер не увидит, поэтому число разобранных чтений сверяется с числом
43
+ * вызовов `show` в тех же файлах.
44
+ */
45
+ function readsOf(source) {
46
+ const constants = declaredConstants(source);
47
+ const reads = [];
48
+ for (const match of source.matchAll(/'show',\s*`\$\{([A-Za-z0-9_.]+)\}:([^`]+)`/gu)) {
49
+ const [, anchor, rawTarget] = match;
50
+ const named = /^\$\{([A-Za-z0-9_]+)\}$/u.exec(rawTarget);
51
+ const target = named === null ? rawTarget : constants.get(named[1]);
52
+ expect(target, `путь чтения ${rawTarget} не разрешается в строку`).toBeDefined();
53
+ reads.push({ anchor, target });
54
+ }
55
+ return reads;
56
+ }
57
+
58
+ describe('входы выгрузки на отгружаемой линии', () => {
59
+ const reads = SOURCES.flatMap((path) => readsOf(readFileSync(path, 'utf8')));
60
+
61
+ it('разбор нашёл сами чтения — иначе проверка ниже пуста по построению', () => {
62
+ expect(reads.length).toBeGreaterThanOrEqual(3);
63
+ });
64
+
65
+ it('⛔ разобраны ВСЕ чтения: счёт совпадает с числом вызовов show в этих же файлах', () => {
66
+ // Половина, закрывающая слепое пятно разбора: чтение, записанное в другой форме, парсер
67
+ // пропустил бы молча, и список входов остался бы неполным при зелёном тесте.
68
+ const showCalls = SOURCES.map((path) => readFileSync(path, 'utf8'))
69
+ .join('\n')
70
+ .match(/'show'/gu);
71
+
72
+ expect(reads.length).toBe(showCalls?.length ?? 0);
73
+ });
74
+
75
+ it('каждое чтение якорится известной стороной', () => {
76
+ const unknown = reads
77
+ .filter((read) => !SHIPPED_ANCHORS.has(read.anchor) && !V2_ANCHORS.has(read.anchor))
78
+ .map((read) => `${read.anchor}:${read.target}`);
79
+
80
+ expect(unknown).toEqual([]);
81
+ });
82
+
83
+ it('⛔ читают отгружаемую линию ТОЛЬКО через show: иных способов чтения нет', () => {
84
+ // ⛔ Счёт вызовов `show` закрывает лишь иначе записанный show. Чтение, сделанное ДРУГОЙ
85
+ // командой (`cat-file blob`, `archive`, чтение чекаута файлом), парсер не увидит вовсе, и
86
+ // новый вход перестанет запускать срок несвежести при зелёном тесте.
87
+ const sources = SOURCES.map((path) => readFileSync(path, 'utf8')).join('\n');
88
+ const forbidden = ['cat-file', 'archive', 'worktree', 'checkout'].filter((verb) =>
89
+ sources.includes(`'${verb}'`),
90
+ );
91
+
92
+ expect(forbidden).toEqual([]);
93
+ });
94
+
95
+ it('⛔ исходник отгружаемой линии целиком читает РОВНО один модуль — загрузчик определений, и его чтения объявлены', () => {
96
+ // Загрузчик извлекает исходник эталона командой archive, а объявляет прочитанное замыканием импортов входа
97
+ // определений — выгрузка кладёт его в список входов (тест ниже). Второй модуль с таким чтением остался бы без
98
+ // объявления и не запускал бы срок несвежести.
99
+ const readers = readdirSync('scripts')
100
+ .filter((name) => name.endsWith('.mjs') && !name.endsWith('.spec.mjs'))
101
+ .filter((name) => readFileSync(`scripts/${name}`, 'utf8').includes("'archive'"));
102
+
103
+ expect(readers).toEqual(['shipped-definitions.mjs']);
104
+ });
105
+
106
+ it('⛔ поле выгрузки строится ИЗ ЭТИХ констант, а не из своего списка', () => {
107
+ // Иначе список в артефакте и список здесь разъезжаются молча: сторож зелен, а besales-api
108
+ // следит за другими путями, чем читает эмиттер.
109
+ const emitter = readFileSync('scripts/emit-tool-routes.mjs', 'utf8');
110
+
111
+ // Третья часть списка — замыкание импортов отгруженных определений: выгрузка ИСПОЛНЯЕТ отгруженный фильтр, и его
112
+ // исходник — такой же вход, как реестр. Замыкание считает загрузчик по коммиту эталона (`shipped-definitions.mjs`).
113
+ expect(emitter.replace(/\s+/gu, ' ')).toContain(
114
+ 'shippedInputPaths: [ ...new Set([...SHIPPED_INPUT_PATHS, SHIPPED_CLIENT_SOURCE, ...shippedDefinitions.inputPaths]), ].sort()',
115
+ );
116
+ });
117
+
118
+ it('⛔ объявленный список равен фактическим чтениям отгружаемой линии', () => {
119
+ // Вторая, несущая половина: список не просто НЕПУСТ, он совпадает с тем, что читается.
120
+ // Проверка «список непуст» была бы зелена и на списке из одного файла при трёх чтениях.
121
+ const actual = [
122
+ ...new Set(reads.filter((read) => SHIPPED_ANCHORS.has(read.anchor)).map((read) => read.target)),
123
+ ].sort();
124
+
125
+ expect(actual).toEqual([...SHIPPED_INPUT_PATHS, 'src/auth/oauth-client.ts'].sort());
126
+ });
127
+
128
+ it('чтение состояния ветки v2 в список входов отгружаемой линии не попадает', () => {
129
+ // Разные предметы: исходник клиента ветки v2 читается с ЕЁ коммита и свежести выгрузки не
130
+ // касается. Смешав их, мы запускали бы срок на собственных правках моста.
131
+ const v2Reads = reads.filter((read) => V2_ANCHORS.has(read.anchor));
132
+
133
+ expect(v2Reads.length).toBeGreaterThan(0);
134
+ expect(SHIPPED_INPUT_PATHS).not.toContain('src/auth/oauth-client.ts');
135
+ });
136
+ });
@@ -0,0 +1,19 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { readFileSync } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { expect, it } from 'vitest';
5
+ import { loadShippedDefinitions } from './shipped-definitions.mjs';
6
+ import { shippedRef } from './shipped-ref.mjs';
7
+
8
+ it('записанный плановый вызов принадлежит истории отгруженной линии и воспроизводит прежний запрос', async () => {
9
+ const root = fileURLToPath(new URL('..', import.meta.url));
10
+ const fixture = JSON.parse(readFileSync(new URL(
11
+ '../src/tools/definitions/__fixtures__/scheduled-task-shipped-call.json', import.meta.url,
12
+ ), 'utf8'));
13
+ expect(fixture.source.commit).toMatch(/^[a-f0-9]{40}$/u);
14
+ execFileSync('git', ['-C', root, 'merge-base', '--is-ancestor', fixture.source.commit, shippedRef()]);
15
+ const { toolDefinitions } = await loadShippedDefinitions(root, fixture.source.commit);
16
+ const tool = toolDefinitions.find((entry) => entry.name === 'besales_scheduled_task_update');
17
+ expect(tool).toBeDefined();
18
+ expect(tool.createRequest(tool.schema.parse(fixture.input))).toEqual(fixture.shippedRequest);
19
+ }, 60000);
@@ -0,0 +1,5 @@
1
+ export const SHIPPED_REF_ENV: 'BESALES_MCP_SHIPPED_REF';
2
+ export const DEFAULT_SHIPPED_REF: 'origin/v1-line';
3
+ export function shippedRef(env?: Record<string, string | undefined>): string;
4
+ export function shippedRemoteRef(ref?: string): string;
5
+ export function parseShippedRef(ref?: string): { remote: string; branch: string };
@@ -0,0 +1,20 @@
1
+ /** Единая настройка ссылки на отгруженную клиентам линию пакета. */
2
+ export const SHIPPED_REF_ENV = 'BESALES_MCP_SHIPPED_REF';
3
+ export const DEFAULT_SHIPPED_REF = 'origin/v1-line';
4
+
5
+ export function shippedRef(env = process.env) {
6
+ return env[SHIPPED_REF_ENV]?.trim() || DEFAULT_SHIPPED_REF;
7
+ }
8
+
9
+ /** Полное имя локальной ссылки на удалённую ветку для show-ref. */
10
+ export function shippedRemoteRef(ref = shippedRef()) {
11
+ return `refs/remotes/${ref}`;
12
+ }
13
+
14
+ /** Первый слеш отделяет удалённый репозиторий; остальные принадлежат имени ветки. */
15
+ export function parseShippedRef(ref = shippedRef()) {
16
+ const slash = ref.indexOf('/');
17
+ return slash < 0
18
+ ? { remote: 'origin', branch: ref }
19
+ : { remote: ref.slice(0, slash), branch: ref.slice(slash + 1) };
20
+ }
@@ -0,0 +1,59 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { readFileSync } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ import {
6
+ DEFAULT_SHIPPED_REF,
7
+ SHIPPED_REF_ENV,
8
+ parseShippedRef,
9
+ shippedRef,
10
+ shippedRemoteRef,
11
+ } from './shipped-ref.mjs';
12
+ import { SHIPPED_REGISTRY_REF_ENV } from './shipped-registry.mjs';
13
+
14
+ const root = fileURLToPath(new URL('..', import.meta.url));
15
+ const HISTORICAL_REF_EXCEPTIONS = {
16
+ 'src/schemas/shipped-lag.json': 'Проза прежних решений о долге; основания не переписываются.',
17
+ 'src/tools/definitions/__fixtures__/scheduled-task-shipped-call.json':
18
+ 'Историческое имя ссылки при записи вызова; проверяется коммит и исполненный запрос.',
19
+ 'src/tools/definitions/__fixtures__/setup-init-shipped.json':
20
+ 'Исторический источник снимка схем; проверяется коммит и содержимое Git.',
21
+ 'scripts/shipped-ref.spec.mjs': 'Сам сторож обязан называть запрещённый литерал.',
22
+ };
23
+
24
+ describe('единая ссылка на отгруженную линию', () => {
25
+ it('сохраняет имя настройки; отсутствие, пустота и пробелы дают сохранённую ветку', () => {
26
+ expect(SHIPPED_REF_ENV).toBe('BESALES_MCP_SHIPPED_REF');
27
+ expect(SHIPPED_REGISTRY_REF_ENV).toBe(SHIPPED_REF_ENV);
28
+ expect(DEFAULT_SHIPPED_REF).toBe('origin/v1-line');
29
+ for (const value of [undefined, '', ' \t\n']) {
30
+ expect(shippedRef({ [SHIPPED_REF_ENV]: value })).toBe('origin/v1-line');
31
+ }
32
+ expect(shippedRef({ [SHIPPED_REF_ENV]: ' backup/release/v1 ' })).toBe('backup/release/v1');
33
+ });
34
+
35
+ it('без аргумента читает окружение; полное имя и разбор используют ту же настройку', () => {
36
+ vi.stubEnv(SHIPPED_REF_ENV, ' backup/release/v1 ');
37
+ try {
38
+ expect(shippedRef()).toBe('backup/release/v1');
39
+ expect(shippedRemoteRef()).toBe('refs/remotes/backup/release/v1');
40
+ expect(parseShippedRef()).toEqual({ remote: 'backup', branch: 'release/v1' });
41
+ } finally {
42
+ vi.unstubAllEnvs();
43
+ }
44
+ expect(shippedRemoteRef('upstream/v1')).toBe('refs/remotes/upstream/v1');
45
+ expect(parseShippedRef('v1-line')).toEqual({ remote: 'origin', branch: 'v1-line' });
46
+ });
47
+
48
+ it('отслеживаемые исходники не зашивают origin/main вне объявленных исторических исключений', () => {
49
+ const files = execFileSync('git', ['-C', root, 'ls-files', '-z', '--', 'scripts/', 'src/'], {
50
+ encoding: 'utf8',
51
+ }).split('\0').filter(Boolean);
52
+ expect(files.length).toBeGreaterThan(0);
53
+ const violations = files.filter((path) =>
54
+ !Object.hasOwn(HISTORICAL_REF_EXCEPTIONS, path) &&
55
+ readFileSync(new URL(`../${path}`, import.meta.url), 'utf8').includes('origin/main'),
56
+ );
57
+ expect(violations, 'Зашитая ссылка на отгруженную линию').toEqual([]);
58
+ });
59
+ });
@@ -0,0 +1,107 @@
1
+ // Отгруженный реестр инструментов — ЭТАЛОН, с которым сверяется ветка v2.
2
+ //
3
+ // Берётся из этого же репозитория (ссылка задаётся общей настройкой отгруженной линии): отгружаемая клиентам
4
+ // линия и ветка v2 — два состояния одного репозитория, поэтому никакой зависимости от чужой рабочей
5
+ // копии на диске нет, достаточно доступа к ремоуту.
6
+ //
7
+ // Fail-closed: без эталона выгрузка не пишется вовсе. Иначе проверка полноты моста снова сравнивала
8
+ // бы v2 сам с собой — ровно та слепота, ради которой этот модуль и появился.
9
+ import { execFileSync } from 'node:child_process';
10
+ import { SHIPPED_REF_ENV, parseShippedRef, shippedRef } from './shipped-ref.mjs';
11
+ import { readFileSync } from 'node:fs';
12
+
13
+ const REGISTRY_PATH = 'src/schemas/mcp-tools.json';
14
+ const PACKAGE_PATH = 'package.json';
15
+
16
+ /**
17
+ * Что выгрузка ЧИТАЕТ с отгружаемой линии — объявлено списком и уезжает в артефакт.
18
+ *
19
+ * ⛔ Список нужен не здесь, а на стороне besales-api: там по нему считается СВЕЖЕСТЬ выгрузки —
20
+ * «менялось ли с тех пор то, из чего она собрана». Своя копия списка на той стороне разошлась бы
21
+ * с этим модулем молча: эмиттер начал бы читать из отгружаемой линии четвёртый файл, а проверка
22
+ * продолжала бы следить за тремя — и правка, ради которой перевыпуск и нужен, срока бы не
23
+ * запускала. Поэтому список объявлен РЯДОМ с чтениями и едет вместе с выгрузкой.
24
+ *
25
+ * Тест `shipped-inputs.spec.mjs` сверяет его с фактическими чтениями обоих скриптов.
26
+ */
27
+ export const SHIPPED_INPUT_PATHS = Object.freeze([REGISTRY_PATH, PACKAGE_PATH]);
28
+
29
+ /** Офлайн-выход: путь к реестру. Обязан идти вместе с коммитом, иначе вход непроверяем. */
30
+ export const SHIPPED_REGISTRY_PATH_ENV = 'BESALES_MCP_SHIPPED_REGISTRY';
31
+ export const SHIPPED_REGISTRY_COMMIT_ENV = 'BESALES_MCP_SHIPPED_COMMIT';
32
+ /** Ссылка на отгружаемую ветку — на случай, если линия отгрузки когда-нибудь переедет. */
33
+ export const SHIPPED_REGISTRY_REF_ENV = SHIPPED_REF_ENV;
34
+
35
+ function git(repoRoot, args) {
36
+ return execFileSync('git', ['-C', repoRoot, ...args], {
37
+ encoding: 'utf8',
38
+ maxBuffer: 64 * 1024 * 1024,
39
+ stdio: ['ignore', 'pipe', 'pipe'],
40
+ });
41
+ }
42
+
43
+ /**
44
+ * @param {string} repoRoot корень репозитория пакета
45
+ * @param {{ env?: Record<string, string | undefined> }} [options]
46
+ * @returns {{ tools: Array<{ name: string, inputSchema?: unknown }>, provenance: Record<string, unknown> }}
47
+ */
48
+ export function loadShippedRegistry(repoRoot, options = {}) {
49
+ const env = options.env ?? process.env;
50
+ // ⚠️ Файловый вход — ТОЛЬКО для локальной диагностики без сети. Выгрузка, сделанная через него,
51
+ // в коммит попадать не должна: besales-api утверждает происхождение эталона отдельным тестом
52
+ // (`source: 'git'`, `ref: shippedRef()`, `fetched: true`), и такой артефакт покраснеет — именно
53
+ // затем, чтобы проверка полноты моста никогда не сравнивала ветку v2 саму с собой.
54
+ const explicitPath = env[SHIPPED_REGISTRY_PATH_ENV]?.trim();
55
+ if (explicitPath) {
56
+ const commit = env[SHIPPED_REGISTRY_COMMIT_ENV]?.trim();
57
+ if (!commit) {
58
+ throw new Error(
59
+ `${SHIPPED_REGISTRY_PATH_ENV} задан без ${SHIPPED_REGISTRY_COMMIT_ENV}: офлайн-вход обязан ` +
60
+ 'назвать, какое состояние отгруженной линии он выдаёт за эталон.',
61
+ );
62
+ }
63
+ const tools = JSON.parse(readFileSync(explicitPath, 'utf8')).tools;
64
+ return {
65
+ tools,
66
+ provenance: {
67
+ source: 'file',
68
+ path: explicitPath,
69
+ commit,
70
+ version: null,
71
+ toolCount: tools.length,
72
+ },
73
+ };
74
+ }
75
+
76
+ const ref = shippedRef(env);
77
+ const { remote, branch } = parseShippedRef(ref);
78
+ // Сбой fetch РОНЯЕТ генерацию. Уцелевшая локальная ссылка — не эталон, а его снимок неизвестной
79
+ // давности: продолжив на ней, выгрузка объявила бы сверку состоявшейся, хотя сверялась со старым
80
+ // состоянием отгружаемой линии. Выход из fail-closed один и он ниже, в тексте ошибки.
81
+ try {
82
+ git(repoRoot, ['fetch', '--no-tags', '--quiet', remote, branch]);
83
+ } catch {
84
+ throw new Error(
85
+ `Не удалось обновить ${ref}: эталон нельзя считать актуальным, выгрузка остановлена. ` +
86
+ `Офлайн-выход: ${SHIPPED_REGISTRY_PATH_ENV}=<файл> ${SHIPPED_REGISTRY_COMMIT_ENV}=<sha>.`,
87
+ );
88
+ }
89
+
90
+ let commit;
91
+ try {
92
+ commit = git(repoRoot, ['rev-parse', ref]).trim();
93
+ } catch {
94
+ throw new Error(
95
+ `Отгруженный реестр недостижим: ссылка ${ref} не разрешается. ` +
96
+ `Дай доступ к ремоуту либо укажи реестр явно: ${SHIPPED_REGISTRY_PATH_ENV}=<файл> ` +
97
+ `${SHIPPED_REGISTRY_COMMIT_ENV}=<sha>.`,
98
+ );
99
+ }
100
+
101
+ const tools = JSON.parse(git(repoRoot, ['show', `${ref}:${REGISTRY_PATH}`])).tools;
102
+ const version = JSON.parse(git(repoRoot, ['show', `${ref}:${PACKAGE_PATH}`])).version;
103
+ return {
104
+ tools,
105
+ provenance: { source: 'git', ref, commit, version, toolCount: tools.length, fetched: true },
106
+ };
107
+ }