@besales/mcp 0.48.0 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -164
- package/README.onprem.ru.md +35 -0
- package/bin/besales-mcp-http.js +9 -0
- package/bin/besales-onprem.mjs +19 -0
- package/dist/auth/connection-store.d.ts +3 -1
- package/dist/auth/connection-store.js +9 -3
- package/dist/auth/connection-store.js.map +1 -1
- package/dist/auth/oauth-client.d.ts +20 -27
- package/dist/auth/oauth-client.js +31 -23
- package/dist/auth/oauth-client.js.map +1 -1
- package/dist/auth/session-workspace.d.ts +1 -0
- package/dist/auth/session-workspace.js +10 -1
- package/dist/auth/session-workspace.js.map +1 -1
- package/dist/auth/token-storage.js +4 -1
- package/dist/auth/token-storage.js.map +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +80 -19
- package/dist/cli.js.map +1 -1
- package/dist/constants/crm-catalog.d.ts +2 -0
- package/dist/constants/crm-catalog.js +3 -0
- package/dist/constants/crm-catalog.js.map +1 -0
- package/dist/http/api-client.d.ts +52 -7
- package/dist/http/api-client.js +131 -66
- package/dist/http/api-client.js.map +1 -1
- package/dist/http/feedback-document-error.d.ts +26 -0
- package/dist/http/feedback-document-error.js +22 -0
- package/dist/http/feedback-document-error.js.map +1 -0
- package/dist/http-server.d.ts +15 -0
- package/dist/http-server.js +378 -0
- package/dist/http-server.js.map +1 -0
- package/dist/instructions/server-instructions.d.ts +1 -1
- package/dist/instructions/server-instructions.js +6 -3
- package/dist/instructions/server-instructions.js.map +1 -1
- package/dist/network/constants.d.ts +25 -0
- package/dist/network/constants.js +26 -0
- package/dist/network/constants.js.map +1 -0
- package/dist/network/failed-verifications.d.ts +10 -0
- package/dist/network/failed-verifications.js +37 -0
- package/dist/network/failed-verifications.js.map +1 -0
- package/dist/network/http-test-fixture.d.ts +3 -0
- package/dist/network/http-test-fixture.js +86 -0
- package/dist/network/http-test-fixture.js.map +1 -0
- package/dist/network/known-keys.d.ts +10 -0
- package/dist/network/known-keys.js +38 -0
- package/dist/network/known-keys.js.map +1 -0
- package/dist/network/memory-credentials.d.ts +11 -0
- package/dist/network/memory-credentials.js +24 -0
- package/dist/network/memory-credentials.js.map +1 -0
- package/dist/network/rate-limit.d.ts +23 -0
- package/dist/network/rate-limit.js +62 -0
- package/dist/network/rate-limit.js.map +1 -0
- package/dist/network/rejected-keys.d.ts +9 -0
- package/dist/network/rejected-keys.js +39 -0
- package/dist/network/rejected-keys.js.map +1 -0
- package/dist/network/request-work.d.ts +8 -0
- package/dist/network/request-work.js +20 -0
- package/dist/network/request-work.js.map +1 -0
- package/dist/network/successful-keys.d.ts +17 -0
- package/dist/network/successful-keys.js +47 -0
- package/dist/network/successful-keys.js.map +1 -0
- package/dist/resources/concepts/external-execution.md +3 -1
- package/dist/resources/concepts/feedback-sheets.md +21 -12
- package/dist/resources/concepts/icp.md +8 -1
- package/dist/resources/concepts/sandbox.md +15 -6
- package/dist/resources/concepts/triggers.md +8 -0
- package/dist/resources/concepts/workbook-classification.md +104 -50
- package/dist/resources/docs/agent-behavior.md +51 -382
- package/dist/resources/docs/campaigns.md +9 -16
- package/dist/resources/docs/crm-integration.md +39 -523
- package/dist/resources/docs/files-and-uploads.md +23 -286
- package/dist/resources/docs/follow-up.md +47 -12
- package/dist/resources/docs/knowledge-base.md +52 -521
- package/dist/resources/docs/pipeline-builder.md +26 -216
- package/dist/resources/docs/pipeline-settings-deep.md +27 -220
- package/dist/resources/docs/platforms.md +106 -519
- package/dist/resources/docs/prompt-anatomy.md +39 -285
- package/dist/resources/docs/routing.md +8 -16
- package/dist/resources/docs/trigger-actions.md +40 -24
- package/dist/resources/docs/variables.md +8 -12
- package/dist/resources/operator-edit.contract.d.ts +7 -0
- package/dist/resources/operator-edit.contract.js +8 -0
- package/dist/resources/operator-edit.contract.js.map +1 -0
- package/dist/resources/registry.js +20 -4
- package/dist/resources/registry.js.map +1 -1
- package/dist/resources/workflows/audit-dialogues.md +23 -12
- package/dist/resources/workflows/compare-models.md +6 -6
- package/dist/resources/workflows/connect-crm-from-scratch.md +15 -12
- package/dist/resources/workflows/connect-datasource-from-scratch.md +5 -4
- package/dist/resources/workflows/extract-from-document.md +8 -6
- package/dist/resources/workflows/operator-edit.md +15 -0
- package/dist/resources/workflows/platform-setup-from-scratch.md +59 -70
- package/dist/resources/workflows/production-readiness-check.md +25 -15
- package/dist/schemas/mcp-tools.json +9902 -4734
- package/dist/schemas/voice-actions-api.contract.json +248 -0
- package/dist/shared/constants/broadcast-reason.constants.d.ts +2 -0
- package/dist/shared/constants/broadcast-reason.constants.js +47 -0
- package/dist/shared/constants/broadcast-reason.constants.js.map +1 -0
- package/dist/shared/constants/crm-stage-pool.constants.d.ts +2 -0
- package/dist/shared/constants/crm-stage-pool.constants.js +3 -0
- package/dist/shared/constants/crm-stage-pool.constants.js.map +1 -0
- package/dist/shared/constants/followup-note.constants.d.ts +3 -0
- package/dist/shared/constants/followup-note.constants.js +4 -0
- package/dist/shared/constants/followup-note.constants.js.map +1 -0
- package/dist/shared/constants/followup-session.constants.d.ts +2 -0
- package/dist/shared/constants/followup-session.constants.js +3 -0
- package/dist/shared/constants/followup-session.constants.js.map +1 -0
- package/dist/shared/constants/funnel-analytics.constants.d.ts +2 -0
- package/dist/shared/constants/funnel-analytics.constants.js +3 -0
- package/dist/shared/constants/funnel-analytics.constants.js.map +1 -0
- package/dist/shared/constants/message-filter.constants.d.ts +7 -0
- package/dist/shared/constants/message-filter.constants.js +8 -0
- package/dist/shared/constants/message-filter.constants.js.map +1 -0
- package/dist/shared/utils/trigger-repeat-mapping.d.ts +72 -0
- package/dist/shared/utils/trigger-repeat-mapping.js +53 -0
- package/dist/shared/utils/trigger-repeat-mapping.js.map +1 -0
- package/dist/skills/besales-dialogue-audit/SKILL.md +31 -20
- package/dist/tasks/task-state-store.js +5 -0
- package/dist/tasks/task-state-store.js.map +1 -1
- package/dist/tools/annotations.js +4 -3
- package/dist/tools/annotations.js.map +1 -1
- package/dist/tools/definitions/agent-design.d.ts +78 -21
- package/dist/tools/definitions/agent-design.js +246 -90
- package/dist/tools/definitions/agent-design.js.map +1 -1
- package/dist/tools/definitions/agent-model-notice.d.ts +5 -0
- package/dist/tools/definitions/agent-model-notice.js +31 -0
- package/dist/tools/definitions/agent-model-notice.js.map +1 -0
- package/dist/tools/definitions/agent-models.d.ts +5 -0
- package/dist/tools/definitions/agent-models.js +26 -0
- package/dist/tools/definitions/agent-models.js.map +1 -0
- package/dist/tools/definitions/agent-settings.d.ts +85 -0
- package/dist/tools/definitions/agent-settings.js +187 -0
- package/dist/tools/definitions/agent-settings.js.map +1 -0
- package/dist/tools/definitions/ai-costs.d.ts +12 -0
- package/dist/tools/definitions/ai-costs.js +142 -0
- package/dist/tools/definitions/ai-costs.js.map +1 -0
- package/dist/tools/definitions/api-tool-request.d.ts +15 -0
- package/dist/tools/definitions/api-tool-request.js +2 -0
- package/dist/tools/definitions/api-tool-request.js.map +1 -0
- package/dist/tools/definitions/behavior-shipped-form.d.ts +182 -0
- package/dist/tools/definitions/behavior-shipped-form.js +185 -0
- package/dist/tools/definitions/behavior-shipped-form.js.map +1 -0
- package/dist/tools/definitions/broadcast-alerts.d.ts +6 -0
- package/dist/tools/definitions/broadcast-alerts.js +72 -0
- package/dist/tools/definitions/broadcast-alerts.js.map +1 -0
- package/dist/tools/definitions/broadcast-analytics.d.ts +102 -18
- package/dist/tools/definitions/broadcast-analytics.js +732 -431
- package/dist/tools/definitions/broadcast-analytics.js.map +1 -1
- package/dist/tools/definitions/broadcast-scheduler.d.ts +10 -13
- package/dist/tools/definitions/broadcast-scheduler.js +196 -154
- package/dist/tools/definitions/broadcast-scheduler.js.map +1 -1
- package/dist/tools/definitions/call-operator-task.schema.d.ts +11 -0
- package/dist/tools/definitions/call-operator-task.schema.js +30 -0
- package/dist/tools/definitions/call-operator-task.schema.js.map +1 -0
- package/dist/tools/definitions/contacts.d.ts +3 -0
- package/dist/tools/definitions/contacts.js +57 -31
- package/dist/tools/definitions/contacts.js.map +1 -1
- package/dist/tools/definitions/crm-platform.d.ts +28 -41
- package/dist/tools/definitions/crm-platform.js +235 -368
- package/dist/tools/definitions/crm-platform.js.map +1 -1
- package/dist/tools/definitions/crm-stage-pool.messages.d.ts +39 -0
- package/dist/tools/definitions/crm-stage-pool.messages.js +43 -0
- package/dist/tools/definitions/crm-stage-pool.messages.js.map +1 -0
- package/dist/tools/definitions/crm-stage-pool.schema.d.ts +64 -0
- package/dist/tools/definitions/crm-stage-pool.schema.js +109 -0
- package/dist/tools/definitions/crm-stage-pool.schema.js.map +1 -0
- package/dist/tools/definitions/custom-reports.d.ts +12 -0
- package/dist/tools/definitions/custom-reports.js +68 -0
- package/dist/tools/definitions/custom-reports.js.map +1 -0
- package/dist/tools/definitions/datasource.d.ts +2 -1
- package/dist/tools/definitions/datasource.js +28 -13
- package/dist/tools/definitions/datasource.js.map +1 -1
- package/dist/tools/definitions/dialog-review-findings-response.d.ts +14 -0
- package/dist/tools/definitions/dialog-review-findings-response.js +23 -0
- package/dist/tools/definitions/dialog-review-findings-response.js.map +1 -0
- package/dist/tools/definitions/dialog-review-safe-response.d.ts +5 -0
- package/dist/tools/definitions/dialog-review-safe-response.js +152 -0
- package/dist/tools/definitions/dialog-review-safe-response.js.map +1 -0
- package/dist/tools/definitions/dialog-review.d.ts +49 -0
- package/dist/tools/definitions/dialog-review.js +383 -0
- package/dist/tools/definitions/dialog-review.js.map +1 -0
- package/dist/tools/definitions/dialogue-analysis.d.ts +46 -0
- package/dist/tools/definitions/dialogue-analysis.js +170 -0
- package/dist/tools/definitions/dialogue-analysis.js.map +1 -0
- package/dist/tools/definitions/dialogue-audit-agent-scope.d.ts +7 -0
- package/dist/tools/definitions/dialogue-audit-agent-scope.js +41 -0
- package/dist/tools/definitions/dialogue-audit-agent-scope.js.map +1 -0
- package/dist/tools/definitions/dialogue-audit-alias.d.ts +67 -0
- package/dist/tools/definitions/dialogue-audit-alias.js +559 -0
- package/dist/tools/definitions/dialogue-audit-alias.js.map +1 -0
- package/dist/tools/definitions/dialogue-export.d.ts +7 -1
- package/dist/tools/definitions/dialogue-export.js +89 -32
- package/dist/tools/definitions/dialogue-export.js.map +1 -1
- package/dist/tools/definitions/dialogue-followup-state.d.ts +9 -0
- package/dist/tools/definitions/dialogue-followup-state.js +69 -0
- package/dist/tools/definitions/dialogue-followup-state.js.map +1 -0
- package/dist/tools/definitions/edit-version-transport.test-fixtures.d.ts +13 -0
- package/dist/tools/definitions/edit-version-transport.test-fixtures.js +292 -0
- package/dist/tools/definitions/edit-version-transport.test-fixtures.js.map +1 -0
- package/dist/tools/definitions/edit-version.d.ts +5 -0
- package/dist/tools/definitions/edit-version.js +20 -0
- package/dist/tools/definitions/edit-version.js.map +1 -0
- package/dist/tools/definitions/external-api-channels.js +17 -15
- package/dist/tools/definitions/external-api-channels.js.map +1 -1
- package/dist/tools/definitions/feedback-document-access.d.ts +16 -0
- package/dist/tools/definitions/feedback-document-access.js +63 -0
- package/dist/tools/definitions/feedback-document-access.js.map +1 -0
- package/dist/tools/definitions/fixtures/shipped-setup-status.d.ts +3 -0
- package/dist/tools/definitions/fixtures/shipped-setup-status.js +9 -0
- package/dist/tools/definitions/fixtures/shipped-setup-status.js.map +1 -0
- package/dist/tools/definitions/follow-up-config.d.ts +79 -0
- package/dist/tools/definitions/follow-up-config.js +258 -0
- package/dist/tools/definitions/follow-up-config.js.map +1 -0
- package/dist/tools/definitions/follow-up-funnel-test.d.ts +4 -3
- package/dist/tools/definitions/follow-up-funnel-test.js +65 -52
- package/dist/tools/definitions/follow-up-funnel-test.js.map +1 -1
- package/dist/tools/definitions/follow-up-promotion-instructions.d.ts +2 -0
- package/dist/tools/definitions/follow-up-promotion-instructions.js +7 -0
- package/dist/tools/definitions/follow-up-promotion-instructions.js.map +1 -0
- package/dist/tools/definitions/follow-up-setup.d.ts +4 -28
- package/dist/tools/definitions/follow-up-setup.js +20 -87
- package/dist/tools/definitions/follow-up-setup.js.map +1 -1
- package/dist/tools/definitions/follow-up.d.ts +20 -122
- package/dist/tools/definitions/follow-up.js +200 -357
- package/dist/tools/definitions/follow-up.js.map +1 -1
- package/dist/tools/definitions/followup-getcourse-compat.d.ts +29 -0
- package/dist/tools/definitions/followup-getcourse-compat.js +62 -0
- package/dist/tools/definitions/followup-getcourse-compat.js.map +1 -0
- package/dist/tools/definitions/followup-sequence-config.schema.d.ts +10 -0
- package/dist/tools/definitions/followup-sequence-config.schema.js +14 -0
- package/dist/tools/definitions/followup-sequence-config.schema.js.map +1 -0
- package/dist/tools/definitions/funnel-analytics.d.ts +18 -0
- package/dist/tools/definitions/funnel-analytics.js +150 -0
- package/dist/tools/definitions/funnel-analytics.js.map +1 -0
- package/dist/tools/definitions/getcourse-anchor-refresh.d.ts +5 -9
- package/dist/tools/definitions/getcourse-anchor-refresh.js +26 -31
- package/dist/tools/definitions/getcourse-anchor-refresh.js.map +1 -1
- package/dist/tools/definitions/getcourse-cold-outbound-settings.d.ts +46 -0
- package/dist/tools/definitions/getcourse-cold-outbound-settings.js +37 -0
- package/dist/tools/definitions/getcourse-cold-outbound-settings.js.map +1 -0
- package/dist/tools/definitions/getcourse-cold-welcome.d.ts +14 -29
- package/dist/tools/definitions/getcourse-cold-welcome.js +180 -254
- package/dist/tools/definitions/getcourse-cold-welcome.js.map +1 -1
- package/dist/tools/definitions/getcourse-wave-welcome.messages.d.ts +10 -0
- package/dist/tools/definitions/getcourse-wave-welcome.messages.js +17 -0
- package/dist/tools/definitions/getcourse-wave-welcome.messages.js.map +1 -0
- package/dist/tools/definitions/help.js.map +1 -1
- package/dist/tools/definitions/icp-import-source.d.ts +75 -0
- package/dist/tools/definitions/icp-import-source.js +88 -0
- package/dist/tools/definitions/icp-import-source.js.map +1 -0
- package/dist/tools/definitions/inbound-analytics.d.ts +13 -0
- package/dist/tools/definitions/inbound-analytics.js +55 -0
- package/dist/tools/definitions/inbound-analytics.js.map +1 -0
- package/dist/tools/definitions/instagram-comment.templates.d.ts +19 -0
- package/dist/tools/definitions/instagram-comment.templates.js +34 -0
- package/dist/tools/definitions/instagram-comment.templates.js.map +1 -0
- package/dist/tools/definitions/instagram-settings-compat.d.ts +33 -0
- package/dist/tools/definitions/instagram-settings-compat.js +7 -0
- package/dist/tools/definitions/instagram-settings-compat.js.map +1 -0
- package/dist/tools/definitions/knowledge-chunking.d.ts +42 -0
- package/dist/tools/definitions/knowledge-chunking.js +83 -0
- package/dist/tools/definitions/knowledge-chunking.js.map +1 -0
- package/dist/tools/definitions/knowledge-space-search-fields.d.ts +12 -0
- package/dist/tools/definitions/knowledge-space-search-fields.js +30 -0
- package/dist/tools/definitions/knowledge-space-search-fields.js.map +1 -0
- package/dist/tools/definitions/knowledge.d.ts +24 -14
- package/dist/tools/definitions/knowledge.js +342 -233
- package/dist/tools/definitions/knowledge.js.map +1 -1
- package/dist/tools/definitions/legacy-trigger-repeat.d.ts +17 -0
- package/dist/tools/definitions/legacy-trigger-repeat.js +53 -0
- package/dist/tools/definitions/legacy-trigger-repeat.js.map +1 -0
- package/dist/tools/definitions/link-tracking.d.ts +8 -0
- package/dist/tools/definitions/link-tracking.js +141 -38
- package/dist/tools/definitions/link-tracking.js.map +1 -1
- package/dist/tools/definitions/mailing-variant-content.d.ts +75 -0
- package/dist/tools/definitions/mailing-variant-content.js +73 -0
- package/dist/tools/definitions/mailing-variant-content.js.map +1 -0
- package/dist/tools/definitions/model-comparison.d.ts +1 -0
- package/dist/tools/definitions/model-comparison.js +4 -5
- package/dist/tools/definitions/model-comparison.js.map +1 -1
- package/dist/tools/definitions/money-currency.d.ts +5 -0
- package/dist/tools/definitions/money-currency.js +10 -0
- package/dist/tools/definitions/money-currency.js.map +1 -0
- package/dist/tools/definitions/operator-workflow.d.ts +5 -5
- package/dist/tools/definitions/operator-workflow.js +80 -27
- package/dist/tools/definitions/operator-workflow.js.map +1 -1
- package/dist/tools/definitions/platform-funnel-analytics.d.ts +42 -0
- package/dist/tools/definitions/platform-funnel-analytics.js +72 -0
- package/dist/tools/definitions/platform-funnel-analytics.js.map +1 -0
- package/dist/tools/definitions/platform-getcourse-wave-field-bindings.d.ts +42 -0
- package/dist/tools/definitions/platform-getcourse-wave-field-bindings.js +51 -0
- package/dist/tools/definitions/platform-getcourse-wave-field-bindings.js.map +1 -0
- package/dist/tools/definitions/platform-settings-limits.d.ts +5 -0
- package/dist/tools/definitions/platform-settings-limits.js +6 -0
- package/dist/tools/definitions/platform-settings-limits.js.map +1 -0
- package/dist/tools/definitions/platform-settings-shipped-form.d.ts +37 -0
- package/dist/tools/definitions/platform-settings-shipped-form.js +310 -0
- package/dist/tools/definitions/platform-settings-shipped-form.js.map +1 -0
- package/dist/tools/definitions/platform-settings-update.d.ts +300 -0
- package/dist/tools/definitions/platform-settings-update.js +134 -0
- package/dist/tools/definitions/platform-settings-update.js.map +1 -0
- package/dist/tools/definitions/{getcourse-wave.d.ts → platform-setup-wave.d.ts} +75 -6
- package/dist/tools/definitions/platform-setup-wave.js +1079 -0
- package/dist/tools/definitions/platform-setup-wave.js.map +1 -0
- package/dist/tools/definitions/platform-setup.d.ts +686 -224
- package/dist/tools/definitions/platform-setup.js +313 -752
- package/dist/tools/definitions/platform-setup.js.map +1 -1
- package/dist/tools/definitions/platform-widget-page-rules.schema.d.ts +10 -0
- package/dist/tools/definitions/platform-widget-page-rules.schema.js +7 -0
- package/dist/tools/definitions/platform-widget-page-rules.schema.js.map +1 -0
- package/dist/tools/definitions/prompt-authoring.constants.d.ts +2 -0
- package/dist/tools/definitions/prompt-authoring.constants.js +3 -0
- package/dist/tools/definitions/prompt-authoring.constants.js.map +1 -0
- package/dist/tools/definitions/prompt-batch-controls.d.ts +5 -0
- package/dist/tools/definitions/prompt-batch-controls.js +40 -0
- package/dist/tools/definitions/prompt-batch-controls.js.map +1 -0
- package/dist/tools/definitions/prompt-draft-authoring.d.ts +5 -0
- package/dist/tools/definitions/prompt-draft-authoring.js +24 -0
- package/dist/tools/definitions/prompt-draft-authoring.js.map +1 -0
- package/dist/tools/definitions/prompt-text-projection.d.ts +11 -0
- package/dist/tools/definitions/prompt-text-projection.js +62 -0
- package/dist/tools/definitions/prompt-text-projection.js.map +1 -0
- package/dist/tools/definitions/reviewer-paid.d.ts +19 -0
- package/dist/tools/definitions/reviewer-paid.js +115 -0
- package/dist/tools/definitions/reviewer-paid.js.map +1 -0
- package/dist/tools/definitions/routing-condition-projection.d.ts +31 -0
- package/dist/tools/definitions/routing-condition-projection.js +97 -0
- package/dist/tools/definitions/routing-condition-projection.js.map +1 -0
- package/dist/tools/definitions/schedule-selection-hints.d.ts +3 -0
- package/dist/tools/definitions/schedule-selection-hints.js +42 -0
- package/dist/tools/definitions/schedule-selection-hints.js.map +1 -0
- package/dist/tools/definitions/{scheduled-tasks.d.ts → scheduled-task-alias.d.ts} +12 -10
- package/dist/tools/definitions/scheduled-task-alias.js +207 -0
- package/dist/tools/definitions/scheduled-task-alias.js.map +1 -0
- package/dist/tools/definitions/session.js +3 -3
- package/dist/tools/definitions/session.js.map +1 -1
- package/dist/tools/definitions/setup-init-operation.schema.d.ts +2 -0
- package/dist/tools/definitions/setup-init-operation.schema.js +6 -0
- package/dist/tools/definitions/setup-init-operation.schema.js.map +1 -0
- package/dist/tools/definitions/shared-input.helpers.d.ts +51 -0
- package/dist/tools/definitions/shared-input.helpers.js +323 -0
- package/dist/tools/definitions/shared-input.helpers.js.map +1 -0
- package/dist/tools/definitions/shared.d.ts +396 -307
- package/dist/tools/definitions/shared.js +430 -652
- package/dist/tools/definitions/shared.js.map +1 -1
- package/dist/tools/definitions/shipped-output-names.d.ts +19 -0
- package/dist/tools/definitions/shipped-output-names.js +123 -0
- package/dist/tools/definitions/shipped-output-names.js.map +1 -0
- package/dist/tools/definitions/task-state.d.ts +5 -5
- package/dist/tools/definitions/task-state.js +2 -1
- package/dist/tools/definitions/task-state.js.map +1 -1
- package/dist/tools/definitions/telegram-personal-capacity.d.ts +4 -0
- package/dist/tools/definitions/telegram-personal-capacity.js +18 -0
- package/dist/tools/definitions/telegram-personal-capacity.js.map +1 -0
- package/dist/tools/definitions/telegram-pool-policy.d.ts +8 -0
- package/dist/tools/definitions/telegram-pool-policy.js +56 -0
- package/dist/tools/definitions/telegram-pool-policy.js.map +1 -0
- package/dist/tools/definitions/touch-history-alias.d.ts +4 -0
- package/dist/tools/definitions/touch-history-alias.js +99 -0
- package/dist/tools/definitions/touch-history-alias.js.map +1 -0
- package/dist/tools/definitions/trigger-action-item.schema.d.ts +254 -0
- package/dist/tools/definitions/trigger-action-item.schema.js +121 -0
- package/dist/tools/definitions/trigger-action-item.schema.js.map +1 -0
- package/dist/tools/definitions/trigger-argument.schema.d.ts +14 -0
- package/dist/tools/definitions/trigger-argument.schema.js +23 -0
- package/dist/tools/definitions/trigger-argument.schema.js.map +1 -0
- package/dist/tools/definitions/trigger-claim-alias.d.ts +10 -0
- package/dist/tools/definitions/trigger-claim-alias.js +90 -0
- package/dist/tools/definitions/trigger-claim-alias.js.map +1 -0
- package/dist/tools/definitions/trigger-echo-projection.d.ts +1 -0
- package/dist/tools/definitions/trigger-echo-projection.js +41 -0
- package/dist/tools/definitions/trigger-echo-projection.js.map +1 -0
- package/dist/tools/definitions/trigger-upsert.tool.d.ts +29 -0
- package/dist/tools/definitions/trigger-upsert.tool.js +122 -0
- package/dist/tools/definitions/trigger-upsert.tool.js.map +1 -0
- package/dist/tools/definitions/v15-port-descriptions.d.ts +11 -0
- package/dist/tools/definitions/v15-port-descriptions.js +30 -0
- package/dist/tools/definitions/v15-port-descriptions.js.map +1 -0
- package/dist/tools/definitions/variables.d.ts +44 -0
- package/dist/tools/definitions/variables.js +310 -0
- package/dist/tools/definitions/variables.js.map +1 -0
- package/dist/tools/definitions/voice-action-input.d.ts +9 -0
- package/dist/tools/definitions/voice-action-input.js +141 -0
- package/dist/tools/definitions/voice-action-input.js.map +1 -0
- package/dist/tools/definitions/widget-customization-compat.d.ts +51 -0
- package/dist/tools/definitions/widget-customization-compat.js +23 -0
- package/dist/tools/definitions/widget-customization-compat.js.map +1 -0
- package/dist/tools/definitions.d.ts +1089 -636
- package/dist/tools/definitions.js +57 -27
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/description-localization.js +3 -2
- package/dist/tools/description-localization.js.map +1 -1
- package/dist/tools/follow-up-request.d.ts +19 -0
- package/dist/tools/follow-up-request.js +81 -0
- package/dist/tools/follow-up-request.js.map +1 -0
- package/dist/tools/followup-revision.d.ts +4 -0
- package/dist/tools/followup-revision.js +29 -0
- package/dist/tools/followup-revision.js.map +1 -0
- package/dist/tools/incomplete-list.js +4 -0
- package/dist/tools/incomplete-list.js.map +1 -1
- package/dist/tools/inventory.js +47 -11
- package/dist/tools/inventory.js.map +1 -1
- package/dist/tools/operation-recovery.d.ts +4 -0
- package/dist/tools/operation-recovery.js +33 -0
- package/dist/tools/operation-recovery.js.map +1 -0
- package/dist/tools/registry-mapping-primary.cases.d.ts +2 -0
- package/dist/tools/registry-mapping-primary.cases.js +753 -0
- package/dist/tools/registry-mapping-primary.cases.js.map +1 -0
- package/dist/tools/registry-mapping-secondary.cases.d.ts +2 -0
- package/dist/tools/registry-mapping-secondary.cases.js +626 -0
- package/dist/tools/registry-mapping-secondary.cases.js.map +1 -0
- package/dist/tools/registry-mapping.cases.d.ts +8 -0
- package/dist/tools/registry-mapping.cases.js +13 -0
- package/dist/tools/registry-mapping.cases.js.map +1 -0
- package/dist/tools/registry-test-fixtures.d.ts +50 -0
- package/dist/tools/registry-test-fixtures.js +120 -0
- package/dist/tools/registry-test-fixtures.js.map +1 -0
- package/dist/tools/registry.d.ts +2 -0
- package/dist/tools/registry.js +82 -52
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/result.d.ts +1 -0
- package/dist/tools/result.js +90 -22
- package/dist/tools/result.js.map +1 -1
- package/dist/tools/toolsets.d.ts +16 -0
- package/dist/tools/toolsets.js +25 -1
- package/dist/tools/toolsets.js.map +1 -1
- package/dist/types/api-contract.gen.d.ts +105875 -22205
- package/dist/utils/credential-signatures.d.ts +3 -0
- package/dist/utils/credential-signatures.js +10 -0
- package/dist/utils/credential-signatures.js.map +1 -0
- package/dist/utils/data-source-column-name.d.ts +10 -0
- package/dist/utils/data-source-column-name.js +36 -0
- package/dist/utils/data-source-column-name.js.map +1 -0
- package/dist/utils/logger.d.ts +1 -0
- package/dist/utils/logger.js +32 -8
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/secret-read-boundary.d.ts +2 -0
- package/dist/utils/secret-read-boundary.js +88 -0
- package/dist/utils/secret-read-boundary.js.map +1 -0
- package/dist/utils/setup-secrets.d.ts +4 -0
- package/dist/utils/setup-secrets.js +40 -0
- package/dist/utils/setup-secrets.js.map +1 -0
- package/docs/agent-models.md +9 -0
- package/docs/agent-usage-guide.full.ru.md +1 -4
- package/docs/analytics-contract.md +67 -0
- package/docs/async-operation-lifecycle.md +10 -3
- package/docs/connect.ru.md +144 -4
- package/docs/contact-company-profile.md +17 -0
- package/docs/contact-recommendations.md +7 -0
- package/docs/crm-stage-pool.md +73 -0
- package/docs/customer-data.md +61 -0
- package/docs/edit-versions.md +36 -0
- package/docs/failure-semantics.md +17 -9
- package/docs/help-navigation.md +15 -42
- package/docs/host-compatibility-matrix.md +72 -93
- package/docs/host-setup.md +33 -35
- package/docs/invariants/public-api-and-contracts.md +16 -0
- package/docs/legacy-action-settings.md +21 -0
- package/docs/main-transfer-dependencies.md +38 -0
- package/docs/mcp2-parity.md +50 -0
- package/docs/modules/analytics.md +79 -0
- package/docs/modules/besales-mcp.md +137 -0
- package/docs/modules/dialog-review-report.md +38 -0
- package/docs/modules/dialogue-followup-adapters.md +39 -0
- package/docs/modules/message-reactions.md +17 -0
- package/docs/modules/network-mode.md +284 -0
- package/docs/modules/prompt-batch-and-dialogue-controls.md +69 -0
- package/docs/pii-policy.md +21 -16
- package/docs/response-size-budget.md +197 -7
- package/docs/secret-read-boundary.md +102 -0
- package/docs/task-state.md +7 -2
- package/docs/telegram-pool-policy.md +19 -0
- package/docs/tool-effects.md +15 -9
- package/docs/tool-surface.md +205 -4
- package/docs/voice-actions-and-inbox.md +95 -0
- package/docs/wazzup-instagram-comments.md +26 -0
- package/package.json +17 -10
- package/scripts/api-source-loader.spec.mjs +40 -0
- package/scripts/audit-bridge-controls.mjs +129 -0
- package/scripts/audit-revert-mutants.mjs +107 -0
- package/scripts/bridge-api-input.spec.mjs +98 -0
- package/scripts/bridge-controls-mutants.mjs +130 -0
- package/scripts/brx3-shipped-refusals.spec.mjs +149 -0
- package/scripts/brx4-ledger-payload.spec.mjs +127 -0
- package/scripts/build-onprem.mjs +108 -0
- package/scripts/connect-clients.sh +141 -0
- package/scripts/connect-scopes.mjs +166 -0
- package/scripts/connect-scopes.spec.mjs +83 -0
- package/scripts/emit-personal-link-carrier.mjs +31 -0
- package/scripts/emit-setup-init-schemas.mjs +24 -0
- package/scripts/emit-tool-routes.mjs +878 -0
- package/scripts/emit-tool-routes.spec.mjs +300 -0
- package/scripts/followup-registry.spec.mjs +107 -0
- package/scripts/generate-crm-rotation-contract.mjs +98 -0
- package/scripts/generate-followup-session-contract.mjs +16 -0
- package/scripts/icp-import-verification/mutate.cjs +70 -0
- package/scripts/import-secret-read-contract.mjs +53 -0
- package/scripts/install-claude-desktop.js +1 -1
- package/scripts/lag-decisions.mjs +37 -0
- package/scripts/lag-decisions.spec.mjs +87 -0
- package/scripts/lag-open-task-owners.mjs +46 -0
- package/scripts/lag-open-task-owners.spec.mjs +78 -0
- package/scripts/lag-payload.mjs +10 -0
- package/scripts/legacy-action-lag.spec.mjs +22 -0
- package/scripts/legacy-field-refusal.shipped.spec.mjs +99 -0
- package/scripts/mcpcompat-handler.mjs +34 -0
- package/scripts/mcpcompat-loader.mjs +36 -0
- package/scripts/mcpcompat-typescript.mjs +3 -0
- package/scripts/platform-settings-shipped-parity.spec.mjs +89 -0
- package/scripts/prbr-round1-recheck.spec.mjs +605 -0
- package/scripts/prbr-shipped-compatibility.spec.mjs +276 -0
- package/scripts/publish-mcp-registry.mjs +98 -0
- package/scripts/publish-mcp-registry.spec.mjs +68 -0
- package/scripts/record-scheduled-task-call.mjs +26 -0
- package/scripts/refusal-probe.mjs +17 -0
- package/scripts/refusal-probe.spec.mjs +29 -0
- package/scripts/registry-diff.mjs +502 -0
- package/scripts/registry-diff.spec.mjs +787 -0
- package/scripts/request-query.mjs +43 -0
- package/scripts/request-query.spec.mjs +82 -0
- package/scripts/route-lag.mjs +23 -0
- package/scripts/route-lag.spec.mjs +30 -0
- package/scripts/sample-args.mjs +174 -0
- package/scripts/sample-args.spec.mjs +160 -0
- package/scripts/shipped-definitions.mjs +197 -0
- package/scripts/shipped-definitions.spec.mjs +57 -0
- package/scripts/shipped-inputs.spec.mjs +136 -0
- package/scripts/shipped-recordings.spec.mjs +19 -0
- package/scripts/shipped-ref.d.mts +5 -0
- package/scripts/shipped-ref.mjs +20 -0
- package/scripts/shipped-ref.spec.mjs +59 -0
- package/scripts/shipped-registry.mjs +107 -0
- package/scripts/shipped-sample-candidates.mjs +69 -0
- package/scripts/shipped-sample-candidates.spec.mjs +117 -0
- package/scripts/shipped-sample.mjs +868 -0
- package/scripts/shipped-sample.spec.mjs +451 -0
- package/scripts/sync-agent-model-schemas.mjs +72 -0
- package/scripts/sync-api-contracts.mjs +85 -0
- package/scripts/sync-api-contracts.spec.mjs +144 -0
- package/scripts/sync-contract-ledger-schemas.mjs +161 -0
- package/scripts/sync-crm-stage-pool-schema.mjs +85 -0
- package/scripts/sync-prompt-draft-schema.mjs +92 -0
- package/scripts/sync-route-map.mjs +94 -0
- package/scripts/sync-schema-descriptions.mjs +25 -0
- package/scripts/sync-tool-inventory.mjs +27 -0
- package/scripts/sync-trigger-argument-schema.mjs +121 -0
- package/scripts/sync-trigger-repeat-mapping.mjs +12 -0
- package/scripts/sync-voice-actions-contract.mjs +67 -0
- package/scripts/sync-voice-actions-tools.mjs +97 -0
- package/scripts/sync-wave-id-schemas.mjs +55 -0
- package/scripts/tool-input-schemas.mjs +46 -0
- package/scripts/tool-input-schemas.spec.mjs +50 -0
- package/scripts/verify-followup-adapters.mjs +235 -0
- package/scripts/verify-secret-read-import.mjs +84 -0
- package/scripts/verify-secret-read-mutants.mjs +143 -0
- package/dist/tools/definitions/analytics.d.ts +0 -40
- package/dist/tools/definitions/analytics.js +0 -233
- package/dist/tools/definitions/analytics.js.map +0 -1
- package/dist/tools/definitions/broadcast-mailing-variants.d.ts +0 -41
- package/dist/tools/definitions/broadcast-mailing-variants.js +0 -194
- package/dist/tools/definitions/broadcast-mailing-variants.js.map +0 -1
- package/dist/tools/definitions/dialogue-audit.d.ts +0 -38
- package/dist/tools/definitions/dialogue-audit.js +0 -292
- package/dist/tools/definitions/dialogue-audit.js.map +0 -1
- package/dist/tools/definitions/getcourse-wave.js +0 -519
- package/dist/tools/definitions/getcourse-wave.js.map +0 -1
- package/dist/tools/definitions/operational-overview.d.ts +0 -3
- package/dist/tools/definitions/operational-overview.js +0 -23
- package/dist/tools/definitions/operational-overview.js.map +0 -1
- package/dist/tools/definitions/scheduled-tasks.js +0 -173
- package/dist/tools/definitions/scheduled-tasks.js.map +0 -1
- package/dist/tools/definitions/trigger-contact-claims.d.ts +0 -7
- package/dist/tools/definitions/trigger-contact-claims.js +0 -60
- package/dist/tools/definitions/trigger-contact-claims.js.map +0 -1
- package/dist/tools/registry-mapping-cases-core.d.ts +0 -38
- package/dist/tools/registry-mapping-cases-core.js +0 -963
- package/dist/tools/registry-mapping-cases-core.js.map +0 -1
- package/dist/tools/registry-mapping-cases-platform.d.ts +0 -2
- package/dist/tools/registry-mapping-cases-platform.js +0 -1052
- package/dist/tools/registry-mapping-cases-platform.js.map +0 -1
- package/dist/tools/trigger-action-config.d.ts +0 -49
- package/dist/tools/trigger-action-config.js +0 -171
- package/dist/tools/trigger-action-config.js.map +0 -1
- package/docs/evals/model-behavior-scorecard.md +0 -80
- package/docs/operation-coverage.md +0 -114
- package/scripts/mock-credentials.js +0 -77
- package/scripts/model-eval-server.js +0 -213
- package/scripts/run-model-eval.js +0 -447
|
@@ -0,0 +1,878 @@
|
|
|
1
|
+
// Выгружает в besales-api перечисление инструментов и адрес каждого — вход проверки полноты моста.
|
|
2
|
+
//
|
|
3
|
+
// ⭐ Перечисление ведётся от ОТГРУЖЕННОГО реестра по общей настройке ссылки, а не от ветки v2. Пока входом
|
|
4
|
+
// была ветка v2, проверка сравнивала v2 сам с собой: инструмент, отгруженный клиенту, но
|
|
5
|
+
// отсутствующий в v2, не видел ни один гвард.
|
|
6
|
+
//
|
|
7
|
+
// Адрес и тело выводятся ПРОГОНОМ `createRequest` на аргументах, выведенных из отгруженной схемы, —
|
|
8
|
+
// рукописный список разъехался бы с кодом ровно так же, как разъехались карты.
|
|
9
|
+
import { execFileSync } from 'node:child_process';
|
|
10
|
+
import { readFileSync, realpathSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { resolve } from 'node:path';
|
|
12
|
+
import { routeLagFindings } from './route-lag.mjs';
|
|
13
|
+
import { remainingLagSections } from './lag-payload.mjs';
|
|
14
|
+
|
|
15
|
+
import { extractConnectScopes } from './connect-scopes.mjs';
|
|
16
|
+
import { collectInputSchemas, namesWithoutSchema } from './tool-input-schemas.mjs';
|
|
17
|
+
import { SHIPPED_INPUT_PATHS, loadShippedRegistry } from './shipped-registry.mjs';
|
|
18
|
+
import { loadShippedDefinitions } from './shipped-definitions.mjs';
|
|
19
|
+
import {
|
|
20
|
+
buildShippedSample,
|
|
21
|
+
filterOf,
|
|
22
|
+
prepareKnownArgs,
|
|
23
|
+
resolveShippedVariant,
|
|
24
|
+
routeShape,
|
|
25
|
+
schemaLagExplains,
|
|
26
|
+
schemaPathsOf,
|
|
27
|
+
valuesAt,
|
|
28
|
+
variantExtensionFindings,
|
|
29
|
+
withGeneratedValues,
|
|
30
|
+
withValueAt,
|
|
31
|
+
} from './shipped-sample.mjs';
|
|
32
|
+
import { diffRegistries, lagKey, reconcileWithRegistry } from './registry-diff.mjs';
|
|
33
|
+
import { resetSampleUid, sampleFor } from './sample-args.mjs';
|
|
34
|
+
import { hasExactRefusalPath } from './refusal-probe.mjs';
|
|
35
|
+
import { SHIPPED_SAMPLE_FALLBACKS, shippedSampleCandidates } from './shipped-sample-candidates.mjs';
|
|
36
|
+
import { parseQuery, shippedQueryCarrierSample } from './request-query.mjs';
|
|
37
|
+
import { lagOpenTaskErrors, readLagPlans } from './lag-open-task-owners.mjs';
|
|
38
|
+
|
|
39
|
+
const CONTRACTS_DIR_ENV = 'BESALES_API_CONTRACTS_DIR';
|
|
40
|
+
const packageRoot = new URL('..', import.meta.url).pathname;
|
|
41
|
+
|
|
42
|
+
const contractsDir = process.env[CONTRACTS_DIR_ENV]?.trim();
|
|
43
|
+
if (!contractsDir) {
|
|
44
|
+
// Каталог назначения обязателен: скрипт живёт в общем репозитории пакета, а besales-api бывает
|
|
45
|
+
// разложен несколькими рабочими деревьями. Вычисленный «по соседству» путь молча писал бы в чужую
|
|
46
|
+
// ветку — правка уезжала бы туда, где её никто не ждёт.
|
|
47
|
+
console.error(
|
|
48
|
+
`Не задан ${CONTRACTS_DIR_ENV} — каталог contracts/ целевого besales-api. ` +
|
|
49
|
+
'Пример: BESALES_API_CONTRACTS_DIR=../besales-api/contracts yarn publish:mcp-registry',
|
|
50
|
+
);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const OUT = resolve(contractsDir, 'mcp-tool-routes.json');
|
|
54
|
+
// Диагностика не является подписанной выгрузкой: только файловый эталон и
|
|
55
|
+
// временное назначение. Штатный путь сохраняет все проверки происхождения.
|
|
56
|
+
const dryRun = process.argv.includes('--dry-run');
|
|
57
|
+
if (
|
|
58
|
+
dryRun &&
|
|
59
|
+
(!process.env.BESALES_MCP_SHIPPED_REGISTRY?.trim() ||
|
|
60
|
+
!realpathSync(contractsDir)
|
|
61
|
+
.split('/')
|
|
62
|
+
.some((part) => /^\.codex-artifacts-[A-Za-z0-9_-]+$/u.test(part)))
|
|
63
|
+
) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
'--dry-run требует файловый эталон и contracts/ внутри .codex-artifacts-*/',
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
// Рабочая область у сгенерированного набора одна и та же: она не участвует в различении веток.
|
|
69
|
+
const SAMPLE_WORKSPACE_ID = '00000000-0000-4000-8000-0000000000ff';
|
|
70
|
+
// Третий вход выгрузки на отгружаемой линии: исходник клиента, из которого извлекаются права
|
|
71
|
+
// подключения. Объявлен константой, потому что уезжает в выгрузку вместе с двумя из загрузчика —
|
|
72
|
+
// по этому списку besales-api считает СВЕЖЕСТЬ артефакта.
|
|
73
|
+
const SHIPPED_CLIENT_SOURCE = 'src/auth/oauth-client.ts';
|
|
74
|
+
|
|
75
|
+
const { toolDefinitions } = await import('../dist/tools/definitions.js');
|
|
76
|
+
const localRegistry = JSON.parse(
|
|
77
|
+
readFileSync(new URL('../src/schemas/mcp-tools.json', import.meta.url), 'utf8'),
|
|
78
|
+
);
|
|
79
|
+
const lagRegistry = JSON.parse(
|
|
80
|
+
readFileSync(new URL('../src/schemas/shipped-lag.json', import.meta.url), 'utf8'),
|
|
81
|
+
);
|
|
82
|
+
const metadataErrors = lagOpenTaskErrors(lagRegistry, readLagPlans());
|
|
83
|
+
if (metadataErrors.length > 0) {
|
|
84
|
+
throw new Error(`Некорректные владельцы/метаданные отставания:\n${metadataErrors.join('\n')}`);
|
|
85
|
+
}
|
|
86
|
+
// ⛔ Выгрузка подписывается коммитом HEAD, а инструменты берутся из рабочей сборки: при незакоммиченных правках подпись
|
|
87
|
+
// называла бы коммит, из которого выгрузка НЕ собрана. Поэтому незакоммиченное дерево — отказ выгрузки.
|
|
88
|
+
const uncommitted = execFileSync('git', ['-C', packageRoot, 'status', '--porcelain'], {
|
|
89
|
+
encoding: 'utf8',
|
|
90
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
91
|
+
}).trim();
|
|
92
|
+
if (uncommitted !== '' && !dryRun) {
|
|
93
|
+
console.error(
|
|
94
|
+
'Дерево моста не закоммичено: выгрузка подписывается коммитом HEAD, а инструменты берутся из рабочей сборки. ' +
|
|
95
|
+
`Закоммитьте правки и перевыпустите:\n${uncommitted}`,
|
|
96
|
+
);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
const shipped = loadShippedRegistry(packageRoot);
|
|
100
|
+
// Права подключения отгруженного клиента — из того же коммита эталона, что и реестр инструментов. Файловый вход
|
|
101
|
+
// эталона коммита для чтения исходника не даёт. Диагностика ниже сверяет файл с названным git-коммитом;
|
|
102
|
+
// штатная выгрузка по-прежнему принимает только обновлённый git-эталон.
|
|
103
|
+
if (shipped.provenance.source !== 'git' && !dryRun) {
|
|
104
|
+
console.error(
|
|
105
|
+
'Права подключения выгружаются только из git-эталона: файловый вход исходника клиента не содержит',
|
|
106
|
+
);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
if (dryRun) {
|
|
110
|
+
const committedRegistry = execFileSync(
|
|
111
|
+
'git',
|
|
112
|
+
[
|
|
113
|
+
'-C',
|
|
114
|
+
packageRoot,
|
|
115
|
+
'show',
|
|
116
|
+
`${shipped.provenance.commit}:src/schemas/mcp-tools.json`,
|
|
117
|
+
],
|
|
118
|
+
{ encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 },
|
|
119
|
+
);
|
|
120
|
+
if (
|
|
121
|
+
JSON.stringify(JSON.parse(committedRegistry).tools) !==
|
|
122
|
+
JSON.stringify(shipped.tools)
|
|
123
|
+
) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
'Файловый эталон не совпадает с названным коммитом отгруженной линии',
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
console.warn(
|
|
129
|
+
'ДИАГНОСТИКА: source=file, без fetch; результат не пригоден для коммита',
|
|
130
|
+
);
|
|
131
|
+
shipped.provenance.diagnosticOnly = true;
|
|
132
|
+
}
|
|
133
|
+
const connectScopes = {
|
|
134
|
+
source: SHIPPED_CLIENT_SOURCE,
|
|
135
|
+
commit: shipped.provenance.commit,
|
|
136
|
+
scopes: extractConnectScopes(
|
|
137
|
+
execFileSync(
|
|
138
|
+
'git',
|
|
139
|
+
['-C', packageRoot, 'show', `${shipped.provenance.commit}:${SHIPPED_CLIENT_SOURCE}`],
|
|
140
|
+
{
|
|
141
|
+
encoding: 'utf8',
|
|
142
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
143
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
144
|
+
},
|
|
145
|
+
),
|
|
146
|
+
),
|
|
147
|
+
};
|
|
148
|
+
// Права, которые запрашивает ЭТА ветка (v2), — тем же извлекателем и с коммита, на котором стоит генератор. Сервер
|
|
149
|
+
// обязан принять и их: клиент, выпущенный с этой ветки, иначе не подключится. Берётся закоммиченный текст, а не
|
|
150
|
+
// рабочий файл: коммит в выгрузке обязан называть ровно то, из чего извлечён набор.
|
|
151
|
+
const generatorV2Commit = execFileSync('git', ['-C', packageRoot, 'rev-parse', 'HEAD'], {
|
|
152
|
+
encoding: 'utf8',
|
|
153
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
154
|
+
}).trim();
|
|
155
|
+
const v2ConnectScopes = {
|
|
156
|
+
source: 'src/auth/oauth-client.ts',
|
|
157
|
+
commit: generatorV2Commit,
|
|
158
|
+
scopes: extractConnectScopes(
|
|
159
|
+
execFileSync(
|
|
160
|
+
'git',
|
|
161
|
+
['-C', packageRoot, 'show', `${generatorV2Commit}:src/auth/oauth-client.ts`],
|
|
162
|
+
{
|
|
163
|
+
encoding: 'utf8',
|
|
164
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
165
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
166
|
+
},
|
|
167
|
+
),
|
|
168
|
+
),
|
|
169
|
+
};
|
|
170
|
+
// Отгруженные определения ИСПОЛНЯЮТСЯ: образец отгруженного вызова обязан пройти фильтр отгруженного инструмента
|
|
171
|
+
// (см. `shipped-sample.mjs`). Сбой загрузки — отказ выгрузки целиком, а не причина отдельного случая.
|
|
172
|
+
const shippedDefinitions = await loadShippedDefinitions(packageRoot, shipped.provenance.commit);
|
|
173
|
+
const shippedDefinitionByName = new Map(
|
|
174
|
+
shippedDefinitions.toolDefinitions.map((definition) => [definition.name, definition]),
|
|
175
|
+
);
|
|
176
|
+
const shippedSchemas = new Map(shipped.tools.map((tool) => [tool.name, tool.inputSchema]));
|
|
177
|
+
const shippedNameBySuccessor = new Map(
|
|
178
|
+
Object.entries(lagRegistry.toolSuccessors ?? {}).map(([shippedName, v2Name]) => [
|
|
179
|
+
v2Name,
|
|
180
|
+
shippedName,
|
|
181
|
+
]),
|
|
182
|
+
);
|
|
183
|
+
const localSchemas = new Map(localRegistry.tools.map((tool) => [tool.name, tool.inputSchema]));
|
|
184
|
+
|
|
185
|
+
// Аргументы из карты маршрутов предпочтительнее сгенерированных: они проверены тестом и, в отличие
|
|
186
|
+
// от генерации, проходят там, где схема требует ровно одно из взаимоисключающих полей.
|
|
187
|
+
const routeMap = JSON.parse(
|
|
188
|
+
readFileSync(new URL('../src/schemas/mcp-v2-route-map.json', import.meta.url), 'utf8'),
|
|
189
|
+
);
|
|
190
|
+
const routeLagProblems = routeLagFindings(
|
|
191
|
+
routeMap,
|
|
192
|
+
lagRegistry.routeLag ?? {},
|
|
193
|
+
readFileSync(new URL('../src/types/api-contract.gen.ts', import.meta.url), 'utf8'),
|
|
194
|
+
);
|
|
195
|
+
if (routeLagProblems.length > 0) throw new Error(routeLagProblems.join('\n'));
|
|
196
|
+
// Из этих аргументов выводятся тело и строка запроса, которые besales-api прогоняет через настоящий
|
|
197
|
+
// вход маршрута.
|
|
198
|
+
//
|
|
199
|
+
// ⭐ Ветвящийся инструмент выгружается ПО ЗАПИСИ НА ВАРИАНТ (2026-08-11, кусок A задачи 6.6.6).
|
|
200
|
+
//
|
|
201
|
+
// Прежде выгружался ровно один вариант — тот, что оказался в фикстуре первым. Это молча оставляло
|
|
202
|
+
// без проверки вторые ветки семи инструментов, причём у части из них ветки ведут в РАЗНЫЕ адреса и
|
|
203
|
+
// методы (правка правила маршрутизации: PATCH против POST). Промежуточная попытка «выбирать самый
|
|
204
|
+
// богатый набор» была сделана и ОТКАЧЕНА: она не убирает зависимость от порядка, не видит разницы
|
|
205
|
+
// во вложенных полях и замеренно ослабила стража — у статистики шагов выбор переключился на вариант
|
|
206
|
+
// с моментом времени вместо календарной даты отгруженной схемы.
|
|
207
|
+
//
|
|
208
|
+
// Восьмую ветку — создание цепочки дожимов против её правки — нашла не рукопись, а выводимая
|
|
209
|
+
// проверка полноты в `v2-route-map.spec.ts`: она прогоняет конструктор с одним снятым или
|
|
210
|
+
// добавленным необязательным полем и требует, чтобы объявленных веток было не меньше числа
|
|
211
|
+
// различимых пар «метод + форма адреса».
|
|
212
|
+
// ⛔ Инструмент БЕЗ строки фикстуры (таких 26: ICP, песочница, промпт-операции, каталог моделей,
|
|
213
|
+
// оба инструмента аналитики) обязан остаться в выгрузке. Поэтому список вариантов у него — один
|
|
214
|
+
// БЕЗЫМЯННЫЙ элемент, а не пустота: наивный цикл «по вариантам фикстуры» выкинул бы их молча.
|
|
215
|
+
const variantsByTool = new Map();
|
|
216
|
+
for (const entry of routeMap) {
|
|
217
|
+
const [name, variant] = splitVariantKey(entry.tool);
|
|
218
|
+
if (!variantsByTool.has(name)) variantsByTool.set(name, []);
|
|
219
|
+
variantsByTool.get(name).push({ variant, args: entry.canonicalArgs });
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ⛔ Помощники ниже НЕ экспортируются намеренно. Модуль сразу пишет артефакт и умеет завершить
|
|
223
|
+
// процесс кодом 1, поэтому импортировать его ради одной функции нельзя — экспорт обещал бы
|
|
224
|
+
// переиспользование, которого нет.
|
|
225
|
+
|
|
226
|
+
/** Ключ пары для сообщений об ошибке: без варианта — голое имя. */
|
|
227
|
+
function variantKey(name, variant) {
|
|
228
|
+
return variant === undefined ? name : name + '@' + variant;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Разбор ключа фикстуры `инструмент@вариант`. Безвариантный ключ даёт `undefined`. */
|
|
232
|
+
function splitVariantKey(key) {
|
|
233
|
+
const at = key.indexOf('@');
|
|
234
|
+
return at === -1 ? [key, undefined] : [key.slice(0, at), key.slice(at + 1)];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Варианты инструмента в порядке строк фикстуры.
|
|
239
|
+
*
|
|
240
|
+
* ⛔ Порядок несущий: по нему считаются идентификаторы образцов, и «побайтово прежние записи» —
|
|
241
|
+
* обещание, у которого без фиксированного порядка нет носителя.
|
|
242
|
+
*/
|
|
243
|
+
function variantsOf(name, map) {
|
|
244
|
+
return map.get(name) ?? [{ variant: undefined, args: undefined }];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Аргументы, которыми проверяется совместимость с ОТГРУЖЕННЫМ клиентом.
|
|
249
|
+
*
|
|
250
|
+
* Голый образец по отгруженной схеме не годится: схема инструмента слабее доменных ограничений
|
|
251
|
+
* маршрута (только цифры, перечисление транспортов), и такой набор давал бы ложный отказ вместо
|
|
252
|
+
* находки. Проверенные `canonicalArgs` — наоборот, беднее отгруженного входа и не трогают поля,
|
|
253
|
+
* ради которых всё затевалось. Поэтому берётся образец отгруженной схемы, а поверх него кладутся
|
|
254
|
+
* проверенные значения: доменно-корректные значения побеждают, отгруженные поля добавляются.
|
|
255
|
+
*/
|
|
256
|
+
function mergeShippedArgs(sampled, known) {
|
|
257
|
+
if (Array.isArray(known)) {
|
|
258
|
+
if (!Array.isArray(sampled) || sampled.length === 0) return known;
|
|
259
|
+
return known.map((item) => mergeShippedArgs(sampled[0], item));
|
|
260
|
+
}
|
|
261
|
+
if (known === null || typeof known !== 'object') return known;
|
|
262
|
+
if (sampled === null || typeof sampled !== 'object' || Array.isArray(sampled)) return known;
|
|
263
|
+
const out = { ...sampled };
|
|
264
|
+
for (const [key, value] of Object.entries(known))
|
|
265
|
+
out[key] = mergeShippedArgs(sampled[key], value);
|
|
266
|
+
return out;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ⛔ Сверка с реестром отставания идёт ПОСЛЕ образцов: отказ ветки v2, живущий в коде инструмента, виден только
|
|
270
|
+
// исполнением образца, и сверяется он вместе с расхождениями схем — по объединению (строки `…#refused`).
|
|
271
|
+
const diff = diffRegistries(shipped.tools, localRegistry.tools, lagRegistry.toolSuccessors);
|
|
272
|
+
|
|
273
|
+
const tools = [];
|
|
274
|
+
const failed = [];
|
|
275
|
+
/** Наблюдённые отказы v2 на законных отгруженных вызовах: `инструмент → путь → тип поля у отгруженного`. */
|
|
276
|
+
const observedRefusals = new Map();
|
|
277
|
+
/** Находки образцов, при которых выгрузка не пишется. */
|
|
278
|
+
const sampleFindings = [];
|
|
279
|
+
const usedShippedSampleFallbacks = new Set();
|
|
280
|
+
for (const definition of toolDefinitions) {
|
|
281
|
+
if (typeof definition.createRequest !== 'function') {
|
|
282
|
+
tools.push({ name: definition.name, kind: 'local' });
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
for (const knownVariant of variantsOf(definition.name, variantsByTool)) {
|
|
286
|
+
emitVariant(definition, knownVariant);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Ужесточения, которых нет в JSON Schema: голый null и доменные пределы из текста описания.
|
|
292
|
+
* Каждая проба сначала подтверждает законную соседнюю форму, затем отказ именно по этому пути.
|
|
293
|
+
* Если фильтр перестал отказывать, выгрузка падает и строка реестра должна быть снята.
|
|
294
|
+
*/
|
|
295
|
+
const stricterInputProbes = [
|
|
296
|
+
...['document', 'qa', 'table', 'website'].map((kind) => [
|
|
297
|
+
`besales_knowledge_${kind}_list`,
|
|
298
|
+
'page',
|
|
299
|
+
{ knowledge_space_id: '00000000-0000-4000-8000-000000000002' },
|
|
300
|
+
{ knowledge_space_id: '00000000-0000-4000-8000-000000000002', page: 2 },
|
|
301
|
+
'integer',
|
|
302
|
+
true,
|
|
303
|
+
]),
|
|
304
|
+
[
|
|
305
|
+
'besales_platform_settings_update',
|
|
306
|
+
'widget_marketing.web_widget_customization',
|
|
307
|
+
{ widget_marketing: { web_widget_customization: {} } },
|
|
308
|
+
{ widget_marketing: { web_widget_customization: null } },
|
|
309
|
+
'null',
|
|
310
|
+
],
|
|
311
|
+
[
|
|
312
|
+
'besales_platform_settings_update',
|
|
313
|
+
'widget_marketing.web_widget_marketing_field_mappings',
|
|
314
|
+
{ widget_marketing: { web_widget_marketing_field_mappings: {} } },
|
|
315
|
+
{ widget_marketing: { web_widget_marketing_field_mappings: null } },
|
|
316
|
+
'null',
|
|
317
|
+
],
|
|
318
|
+
[
|
|
319
|
+
'besales_platform_settings_update',
|
|
320
|
+
'widget_marketing.web_widget_entry_url_variable_mapping',
|
|
321
|
+
{ widget_marketing: { web_widget_entry_url_variable_mapping: {} } },
|
|
322
|
+
{ widget_marketing: { web_widget_entry_url_variable_mapping: null } },
|
|
323
|
+
'null',
|
|
324
|
+
],
|
|
325
|
+
[
|
|
326
|
+
'besales_behavior_update',
|
|
327
|
+
'message_filters[].source',
|
|
328
|
+
{
|
|
329
|
+
message_filters: [{ id: 'x', source: 'а', target: 'б', enabled: true, order: 1 }],
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
message_filters: [
|
|
333
|
+
{
|
|
334
|
+
id: 'x',
|
|
335
|
+
source: '\uFDD0',
|
|
336
|
+
target: 'б',
|
|
337
|
+
enabled: true,
|
|
338
|
+
order: 1,
|
|
339
|
+
},
|
|
340
|
+
],
|
|
341
|
+
},
|
|
342
|
+
'string',
|
|
343
|
+
],
|
|
344
|
+
[
|
|
345
|
+
'besales_behavior_update',
|
|
346
|
+
'message_filters[].source',
|
|
347
|
+
{
|
|
348
|
+
message_filters: [{ id: 'x', source: 'а', target: 'б', enabled: true, order: 1 }],
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
message_filters: [{ id: 'x', source: '', target: 'б', enabled: true, order: 1 }],
|
|
352
|
+
},
|
|
353
|
+
'string',
|
|
354
|
+
],
|
|
355
|
+
[
|
|
356
|
+
'besales_behavior_update',
|
|
357
|
+
'message_filters[].target',
|
|
358
|
+
{
|
|
359
|
+
message_filters: [{ id: 'x', source: 'а', target: 'б', enabled: true, order: 1 }],
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
message_filters: [
|
|
363
|
+
{
|
|
364
|
+
id: 'x',
|
|
365
|
+
source: 'а',
|
|
366
|
+
target: '\uFDD1',
|
|
367
|
+
enabled: true,
|
|
368
|
+
order: 1,
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
},
|
|
372
|
+
'string',
|
|
373
|
+
],
|
|
374
|
+
[
|
|
375
|
+
'besales_behavior_update',
|
|
376
|
+
'error_handling.ai_error_target_stage_id',
|
|
377
|
+
{ error_handling: { ai_error_target_stage_id: 0 } },
|
|
378
|
+
{ error_handling: { ai_error_target_stage_id: -1 } },
|
|
379
|
+
'integer',
|
|
380
|
+
],
|
|
381
|
+
];
|
|
382
|
+
for (const [
|
|
383
|
+
name,
|
|
384
|
+
path,
|
|
385
|
+
good,
|
|
386
|
+
bad,
|
|
387
|
+
shippedType,
|
|
388
|
+
nonnegativeInteger = false,
|
|
389
|
+
] of stricterInputProbes) {
|
|
390
|
+
const definition = toolDefinitions.find((item) => item.name === name);
|
|
391
|
+
const shippedDefinition = shippedDefinitionByName.get(name);
|
|
392
|
+
const schema = shippedSchemas.get(name);
|
|
393
|
+
const shippedPath =
|
|
394
|
+
schema === undefined ? undefined : schemaPathsOf(schema, `отгруженный ${name}`).get(path);
|
|
395
|
+
if (definition === undefined || shippedDefinition === undefined || shippedPath === undefined) {
|
|
396
|
+
sampleFindings.push(`${name}::${path}: нет определения или поля отгруженного реестра`);
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
const declaredTypes = Array.isArray(shippedPath.type) ? shippedPath.type : [shippedPath.type];
|
|
400
|
+
const declaredAllows =
|
|
401
|
+
declaredTypes.includes(shippedType) &&
|
|
402
|
+
(shippedType !== 'string' ||
|
|
403
|
+
shippedPath.maxLength === undefined ||
|
|
404
|
+
shippedPath.maxLength >= 51) &&
|
|
405
|
+
(shippedType !== 'integer' ||
|
|
406
|
+
nonnegativeInteger ||
|
|
407
|
+
shippedPath.minimum === undefined ||
|
|
408
|
+
shippedPath.minimum < 0);
|
|
409
|
+
if (!declaredAllows) {
|
|
410
|
+
sampleFindings.push(`${name}::${path}: отгруженный реестр уже ограничивает пробное значение`);
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
const accept = filterOf(definition, SAMPLE_WORKSPACE_ID);
|
|
414
|
+
const base = { platform_id: '00000000-0000-4000-8000-000000000002' };
|
|
415
|
+
const baseline = accept({ ...base, ...good });
|
|
416
|
+
const rejected = accept({ ...base, ...bad });
|
|
417
|
+
const shippedAccepted = filterOf(shippedDefinition, SAMPLE_WORKSPACE_ID)({ ...base, ...bad });
|
|
418
|
+
const hasPath = hasExactRefusalPath(rejected, path);
|
|
419
|
+
if (!baseline.ok || !hasPath || !shippedAccepted.ok) {
|
|
420
|
+
sampleFindings.push(
|
|
421
|
+
`${name}::${path}: проба не подтвердила приём отгруженной линией и адресный отказ v2`,
|
|
422
|
+
);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
if (!observedRefusals.has(name)) observedRefusals.set(name, new Map());
|
|
426
|
+
observedRefusals.get(name).set(path, shippedType);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Одна запись артефакта: пара «инструмент × вариант».
|
|
431
|
+
*
|
|
432
|
+
* ⛔ Поле `variant` у безвариантного инструмента физически НЕ сериализуется. Только так 180 записей
|
|
433
|
+
* из 187 остаются побайтово прежними, и правка одного ветвящегося инструмента не краснит сравнение
|
|
434
|
+
* у всех остальных.
|
|
435
|
+
*/
|
|
436
|
+
function emitVariant(definition, knownVariant) {
|
|
437
|
+
resetSampleUid();
|
|
438
|
+
const knownArgsForVariant = knownVariant.args;
|
|
439
|
+
// Часть инструментов отвергает отдельные ветки входа ДО HTTP (взаимоисключающие поля,
|
|
440
|
+
// неподдержанные в v2 параметры). Поэтому перебираем наборы аргументов целиком — вместе с
|
|
441
|
+
// прогоном конструктора: максимальный набор у таких инструментов заведомо упирается в отказ,
|
|
442
|
+
// а обязательный минимум проходит. Первым идёт набор, выведенный из ОТГРУЖЕННОЙ схемы: тело
|
|
443
|
+
// выгрузки должно отражать вызов клиента, а не удобную для нас форму.
|
|
444
|
+
const shippedSchema = shippedSchemas.get(
|
|
445
|
+
shippedNameBySuccessor.get(definition.name) ?? definition.name,
|
|
446
|
+
);
|
|
447
|
+
const localSchema = localSchemas.get(definition.name);
|
|
448
|
+
let request = null;
|
|
449
|
+
let bodySource = null;
|
|
450
|
+
// Проверенные аргументы карты идут ПЕРВЫМИ: сгенерированный по JSON-схеме набор проходит саму
|
|
451
|
+
// схему, но не доменные ограничения принимающей стороны (только цифры, перечисление транспортов),
|
|
452
|
+
// и выведенное из него тело давало бы ложный отказ вместо находки.
|
|
453
|
+
const candidates = [
|
|
454
|
+
...(knownArgsForVariant === undefined
|
|
455
|
+
? []
|
|
456
|
+
: [{ args: knownArgsForVariant, source: 'canonicalArgs' }]),
|
|
457
|
+
...(shippedSchema
|
|
458
|
+
? [
|
|
459
|
+
{
|
|
460
|
+
args: sampleFor(definition.name, shippedSchema, false),
|
|
461
|
+
source: 'generated',
|
|
462
|
+
},
|
|
463
|
+
]
|
|
464
|
+
: []),
|
|
465
|
+
{
|
|
466
|
+
args: sampleFor(definition.name, localSchema, false),
|
|
467
|
+
source: 'generated',
|
|
468
|
+
},
|
|
469
|
+
...(shippedSchema
|
|
470
|
+
? [
|
|
471
|
+
{
|
|
472
|
+
args: sampleFor(definition.name, shippedSchema, true),
|
|
473
|
+
source: 'generated',
|
|
474
|
+
},
|
|
475
|
+
]
|
|
476
|
+
: []),
|
|
477
|
+
{
|
|
478
|
+
args: sampleFor(definition.name, localSchema, true),
|
|
479
|
+
source: 'generated',
|
|
480
|
+
},
|
|
481
|
+
];
|
|
482
|
+
for (const candidate of candidates) {
|
|
483
|
+
try {
|
|
484
|
+
let input = definition.schema.parse(candidate.args);
|
|
485
|
+
if (definition.defaultWorkspaceId && input.workspace_id === undefined) {
|
|
486
|
+
input = definition.schema.parse({
|
|
487
|
+
...input,
|
|
488
|
+
workspace_id: SAMPLE_WORKSPACE_ID,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
request = definition.createRequest(input);
|
|
492
|
+
bodySource = candidate.source;
|
|
493
|
+
break;
|
|
494
|
+
} catch {
|
|
495
|
+
request = null;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
if (request === null) {
|
|
499
|
+
// Ни один сгенерированный набор не дошёл до запроса — это дефект схемы инструмента,
|
|
500
|
+
// а не повод промолчать и выгрузить неполный список.
|
|
501
|
+
failed.push(variantKey(definition.name, knownVariant.variant));
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
// Второе тело — ЗАКОННЫЙ вызов отгруженного клиента (он прошёл отгруженный фильтр) и ответ ветки v2 на него. Именно
|
|
505
|
+
// оно отвечает на вопрос задачи: примет ли v2-DTO то, что шлёт клиент, стоящий у людей сейчас.
|
|
506
|
+
// ⛔ Пропажу отгруженного образца нельзя выражать ОТСУТСТВИЕМ поля: «у инструмента нет отгруженного двойника» и
|
|
507
|
+
// «образец невозможен» выглядели бы одинаково. Невозможность выгружается причиной из закрытого перечня.
|
|
508
|
+
const shippedSample =
|
|
509
|
+
shippedSchema !== undefined
|
|
510
|
+
? shippedSampleFor(definition, knownVariant, shippedSchema, localSchema, request)
|
|
511
|
+
: undefined;
|
|
512
|
+
const shippedRequest = shippedSample?.request;
|
|
513
|
+
const shippedBody = shippedRequest?.body;
|
|
514
|
+
const sampleQuery = parseQuery(request.path);
|
|
515
|
+
// GET без параметров тоже является собранным отгруженным вызовом. Пустой объект сохраняет
|
|
516
|
+
// его фактическую форму и даёт серверному сторожу прогнать именно пустую строку запроса через DTO.
|
|
517
|
+
// Иначе v2 с limit/cursor выглядел как инструмент вообще без отгруженного образца.
|
|
518
|
+
const shippedCarrier = shippedQueryCarrierSample(shippedSample);
|
|
519
|
+
|
|
520
|
+
// Строка запроса выгружается ВСЕГДА, когда она есть: у инструмента без отгруженного двойника
|
|
521
|
+
// (новый в v2) её иначе не было бы вовсе — а это ровно тот класс, где карту писала одна рука и
|
|
522
|
+
// страж нужнее всего. Отсутствие поля означает «запроса нет», а не «вывести не удалось».
|
|
523
|
+
tools.push({
|
|
524
|
+
name: definition.name,
|
|
525
|
+
...(knownVariant.variant === undefined ? {} : { variant: knownVariant.variant }),
|
|
526
|
+
kind: 'api',
|
|
527
|
+
method: request.method ?? 'POST',
|
|
528
|
+
samplePath: request.path.split('?')[0],
|
|
529
|
+
...(sampleQuery === undefined ? {} : { sampleQuery }),
|
|
530
|
+
...(request.body === undefined ? {} : { sampleBody: request.body, bodySource }),
|
|
531
|
+
...(shippedBody === undefined ? {} : { shippedSampleBody: shippedBody }),
|
|
532
|
+
...shippedCarrier,
|
|
533
|
+
...(shippedSample?.omitted.length ? { shippedSampleOmitted: shippedSample.omitted } : {}),
|
|
534
|
+
...(shippedSample?.alternatives.length
|
|
535
|
+
? {
|
|
536
|
+
shippedSampleAlternatives: shippedSample.alternatives.map(alternativeRecord),
|
|
537
|
+
}
|
|
538
|
+
: {}),
|
|
539
|
+
...(shippedSample?.impossible === undefined
|
|
540
|
+
? {}
|
|
541
|
+
: {
|
|
542
|
+
shippedRequestFailed: true,
|
|
543
|
+
shippedSampleImpossible: shippedSample.impossible,
|
|
544
|
+
}),
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/** Запись альтернативы: путь, ради которого она собрана, адрес и тело или строка запроса. */
|
|
549
|
+
function alternativeRecord(alternative) {
|
|
550
|
+
const query = parseQuery(alternative.request.path);
|
|
551
|
+
return {
|
|
552
|
+
forPath: alternative.forPath,
|
|
553
|
+
method: alternative.request.method ?? 'POST',
|
|
554
|
+
samplePath: alternative.request.path.split('?')[0],
|
|
555
|
+
...(query === undefined ? {} : { query }),
|
|
556
|
+
...(alternative.request.body === undefined ? {} : { body: alternative.request.body }),
|
|
557
|
+
...(alternative.omitted.length > 0 ? { omitted: alternative.omitted } : {}),
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/** Один и тот же маршрут: метод и адрес без строки запроса, идентификаторы в адресе не различаются. */
|
|
562
|
+
function sameRoute(left, right) {
|
|
563
|
+
return routeShape(left) === routeShape(right);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Образец отгруженного вызова варианта (см. `shipped-sample.mjs`): шаг 0 — проверенные аргументы без полей, которых
|
|
568
|
+
* у отгруженного нет; затем перебор. Не нашёлся законный набор, а проверенное значение нарушает объявленное
|
|
569
|
+
* ограничение отгруженной схемы, — повтор со значением генератора на этих путях; повтор годится, только если ведёт в
|
|
570
|
+
* ТОТ ЖЕ маршрут: иначе проверенное значение и задавало вариант, и такой формы у отгруженного клиента нет.
|
|
571
|
+
*/
|
|
572
|
+
function shippedSampleFor(definition, knownVariant, shippedSchema, localSchema, mainRequest) {
|
|
573
|
+
const shippedName = shippedNameBySuccessor.get(definition.name) ?? definition.name;
|
|
574
|
+
const shippedDefinition = shippedDefinitionByName.get(shippedName);
|
|
575
|
+
const key = variantKey(definition.name, knownVariant.variant);
|
|
576
|
+
if (shippedDefinition === undefined || typeof shippedDefinition.createRequest !== 'function') {
|
|
577
|
+
return {
|
|
578
|
+
omitted: [],
|
|
579
|
+
alternatives: [],
|
|
580
|
+
impossible: { reason: 'SHIPPED_DEFINITION_UNAVAILABLE', paths: [] },
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
const schemaLag = diff.contractLag.filter((row) => row.tool === shippedName);
|
|
584
|
+
const shippedPaths = schemaPathsOf(shippedSchema, `отгруженный ${shippedName}`);
|
|
585
|
+
const v2Paths = schemaPathsOf(localSchema, `v2 ${definition.name}`);
|
|
586
|
+
const generated = sampleFor(definition.name, shippedSchema, false);
|
|
587
|
+
// У инструментов без строки карты нет canonicalArgs. Пустая база оставляет генератору
|
|
588
|
+
// отгруженной схемы возможность собрать обязательные поля и проверить такой случай.
|
|
589
|
+
const known = prepareKnownArgs(knownVariant.args ?? {}, shippedPaths, {
|
|
590
|
+
acceptV2: filterOf(definition, SAMPLE_WORKSPACE_ID),
|
|
591
|
+
mainRouteShape: routeShape(mainRequest),
|
|
592
|
+
});
|
|
593
|
+
const build = (knownArgs, sampled = generated) =>
|
|
594
|
+
buildShippedSample({
|
|
595
|
+
full: mergeShippedArgs(sampled, knownArgs),
|
|
596
|
+
known: knownArgs,
|
|
597
|
+
acceptShipped: filterOf(shippedDefinition, SAMPLE_WORKSPACE_ID),
|
|
598
|
+
acceptV2: filterOf(definition, SAMPLE_WORKSPACE_ID),
|
|
599
|
+
explains: (path, args) => schemaLagExplains(path, args, schemaLag, v2Paths),
|
|
600
|
+
shippedConstraints: shippedPaths,
|
|
601
|
+
goodValues: (path) =>
|
|
602
|
+
goodValuesOf(definition.name, knownVariant.variant, path, valuesAt(generated, path)[0]),
|
|
603
|
+
mainRouteShape: routeShape(mainRequest),
|
|
604
|
+
});
|
|
605
|
+
// У соседа десять поимённых запасных образцов для взаимоисключающих полей. Новый
|
|
606
|
+
// перебор обычно собирает их сам; оставляем запасной минимум и проверку протухания.
|
|
607
|
+
const fallback = SHIPPED_SAMPLE_FALLBACKS[key];
|
|
608
|
+
const candidates =
|
|
609
|
+
fallback === undefined
|
|
610
|
+
? undefined
|
|
611
|
+
: shippedSampleCandidates(
|
|
612
|
+
key,
|
|
613
|
+
generated,
|
|
614
|
+
sampleFor(definition.name, shippedSchema, true),
|
|
615
|
+
knownVariant.args,
|
|
616
|
+
);
|
|
617
|
+
if (candidates !== undefined) {
|
|
618
|
+
usedShippedSampleFallbacks.add(key);
|
|
619
|
+
const fullShipped = filterOf(shippedDefinition, SAMPLE_WORKSPACE_ID)(candidates[0]);
|
|
620
|
+
const fullV2 = filterOf(definition, SAMPLE_WORKSPACE_ID)(candidates[0]);
|
|
621
|
+
if (fullShipped.ok && fullV2.ok && sameRoute(fullV2.request, mainRequest)) {
|
|
622
|
+
throw new Error(
|
|
623
|
+
`${key}: строка запасного образца протухла — полный отгруженный набор собирается`,
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
let outcome = build(known);
|
|
628
|
+
if (
|
|
629
|
+
outcome.impossible?.reason === 'SHIPPED_COMBINATION_LIMIT' ||
|
|
630
|
+
outcome.impossible?.reason === 'SHIPPED_REJECTS_EVERY_SET'
|
|
631
|
+
) {
|
|
632
|
+
// Проверенное значение варианта могло быть переименовано (например, enum источника
|
|
633
|
+
// аудио), хотя поле и маршрут остались прежними. Берём только адресные отказы самого
|
|
634
|
+
// отгруженного фильтра и его же значение схемы; повтор должен пройти оба фильтра и
|
|
635
|
+
// сохранить маршрут, иначе это действительно вариант только v2.
|
|
636
|
+
const rejected = filterOf(shippedDefinition, SAMPLE_WORKSPACE_ID)(known);
|
|
637
|
+
const replaceable = (rejected.refusals ?? [])
|
|
638
|
+
.map((refusal) => refusal.path)
|
|
639
|
+
.filter(
|
|
640
|
+
(path) =>
|
|
641
|
+
path !== null && valuesAt(generated, path).length > 0 && valuesAt(known, path).length > 0,
|
|
642
|
+
);
|
|
643
|
+
if (replaceable.length > 0) {
|
|
644
|
+
const retry = build(withGeneratedValues(known, generated, replaceable));
|
|
645
|
+
if (retry.request !== undefined && sameRoute(retry.request, mainRequest)) outcome = retry;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
if (outcome.impossible?.reason === 'SHIPPED_REJECTS_EVERY_SET' && candidates !== undefined) {
|
|
649
|
+
outcome = build(
|
|
650
|
+
prepareKnownArgs(candidates[1], shippedPaths),
|
|
651
|
+
sampleFor(definition.name, shippedSchema, true),
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
outcome = resolveShippedVariant({
|
|
655
|
+
outcome,
|
|
656
|
+
known,
|
|
657
|
+
generated,
|
|
658
|
+
schemaLag,
|
|
659
|
+
shippedConstraints: shippedPaths,
|
|
660
|
+
build,
|
|
661
|
+
mainRouteShape: routeShape(mainRequest),
|
|
662
|
+
});
|
|
663
|
+
if (outcome.request !== undefined && !sameRoute(outcome.request, mainRequest)) {
|
|
664
|
+
sampleFindings.push(
|
|
665
|
+
`${key}: образец отгруженного вызова ведёт в ${outcome.request.method ?? 'POST'} ${outcome.request.path.split('?')[0]}, ` +
|
|
666
|
+
`а вариант — в ${mainRequest.method ?? 'POST'} ${mainRequest.path.split('?')[0]}: сверка шла бы не тем входом`,
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
for (const refusal of outcome.refused) {
|
|
670
|
+
if (!observedRefusals.has(shippedName)) observedRefusals.set(shippedName, new Map());
|
|
671
|
+
observedRefusals
|
|
672
|
+
.get(shippedName)
|
|
673
|
+
.set(refusal.path, shippedPaths.get(refusal.path)?.type ?? 'any');
|
|
674
|
+
}
|
|
675
|
+
for (const message of outcome.pathless) {
|
|
676
|
+
sampleFindings.push(
|
|
677
|
+
`${key}: ветка v2 отвергла законный отгруженный вызов без пути — перенеси отказ в схему с путём (${message})`,
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
if (outcome.absentKnown.length > 0) {
|
|
681
|
+
sampleFindings.push(
|
|
682
|
+
`${key}: ветка v2 требует ${outcome.absentKnown.join(', ')}, а отгруженный клиент законно шлёт вызов без них`,
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
return outcome;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/** Годные значения пути: аргументы другого варианта или значение схемы, принятое его отгруженным фильтром. */
|
|
689
|
+
function goodValuesOf(name, variant, path, generatedValue) {
|
|
690
|
+
const values = new Map();
|
|
691
|
+
const shippedName = shippedNameBySuccessor.get(name) ?? name;
|
|
692
|
+
const definition = shippedDefinitionByName.get(shippedName);
|
|
693
|
+
const schema = shippedSchemas.get(shippedName);
|
|
694
|
+
if (definition === undefined || schema === undefined) return [];
|
|
695
|
+
const accept = filterOf(definition, SAMPLE_WORKSPACE_ID);
|
|
696
|
+
const paths = schemaPathsOf(schema, `отгруженный ${shippedName}`);
|
|
697
|
+
for (const other of variantsByTool.get(name) ?? []) {
|
|
698
|
+
if (other.variant === variant || other.args === undefined) continue;
|
|
699
|
+
const candidate = prepareKnownArgs(other.args, paths);
|
|
700
|
+
// Значение «заведомо годное» лишь тогда, когда другой вариант отгруженный фильтр
|
|
701
|
+
// действительно ПРИНЯЛ. Совпадение с JSON-схемой не доказывает refine Zod.
|
|
702
|
+
if (!accept(candidate).ok) continue;
|
|
703
|
+
for (const value of valuesAt(candidate, path)) values.set(JSON.stringify(value), value);
|
|
704
|
+
// В карте другого варианта поле могло отсутствовать: manager_id у meta запрещён, а
|
|
705
|
+
// summary/cohorts принимают число из отгруженной схемы. Проверяем это ИСПОЛНЯЕМЫМ
|
|
706
|
+
// отгруженным фильтром, прежде чем считать значение годным для альтернативы.
|
|
707
|
+
if (generatedValue !== undefined && valuesAt(candidate, path).length === 0) {
|
|
708
|
+
const enriched = withValueAt(candidate, path, generatedValue);
|
|
709
|
+
if (accept(enriched).ok) values.set(JSON.stringify(generatedValue), generatedValue);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
return [...values.values()];
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
const staleShippedSampleFallbacks = Object.keys(SHIPPED_SAMPLE_FALLBACKS).filter(
|
|
716
|
+
(key) => !usedShippedSampleFallbacks.has(key),
|
|
717
|
+
);
|
|
718
|
+
if (staleShippedSampleFallbacks.length > 0) {
|
|
719
|
+
throw new Error(
|
|
720
|
+
`Запасной образец больше не имеет отгруженного маршрута: ${staleShippedSampleFallbacks.join(', ')}`,
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
if (failed.length > 0) {
|
|
725
|
+
console.error(`Не удалось вывести маршрут для: ${failed.join(', ')}`);
|
|
726
|
+
process.exit(1);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Наблюдённый отказ ветки v2 на законном отгруженном вызове — такое же расхождение контракта, как найденное
|
|
730
|
+
// сравнением схем, только живущее в коде инструмента: строка `инструмент::путь#refused`. Сверка — по объединению.
|
|
731
|
+
const refusalLag = [...observedRefusals].flatMap(([tool, paths]) =>
|
|
732
|
+
[...paths].map(([path, shippedType]) => ({
|
|
733
|
+
tool,
|
|
734
|
+
path: `${path}#refused`,
|
|
735
|
+
kind: 'REFUSED',
|
|
736
|
+
shipped: shippedType,
|
|
737
|
+
v2: 'refused',
|
|
738
|
+
})),
|
|
739
|
+
);
|
|
740
|
+
const foundLag = [...diff.contractLag, ...refusalLag].sort((a, b) =>
|
|
741
|
+
a.tool === b.tool ? a.path.localeCompare(b.path) : a.tool.localeCompare(b.tool),
|
|
742
|
+
);
|
|
743
|
+
const reconciliation = reconcileWithRegistry({ ...diff, contractLag: foundLag }, lagRegistry);
|
|
744
|
+
const problems = [];
|
|
745
|
+
problems.push(...variantExtensionFindings({
|
|
746
|
+
tools,
|
|
747
|
+
extensions: lagRegistry.contractExtensions ?? {},
|
|
748
|
+
shippedSchemas,
|
|
749
|
+
localSchemas,
|
|
750
|
+
variantsByTool,
|
|
751
|
+
}));
|
|
752
|
+
if (sampleFindings.length > 0) {
|
|
753
|
+
problems.push(`Образцы отгруженных вызовов:\n ${sampleFindings.join('\n ')}`);
|
|
754
|
+
}
|
|
755
|
+
if (reconciliation.undeclaredMissing.length > 0) {
|
|
756
|
+
problems.push(
|
|
757
|
+
`Отгруженные инструменты, которых нет в ветке v2 и нет в реестре отставания:\n ${reconciliation.undeclaredMissing.join('\n ')}`,
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
if (reconciliation.undeclaredLag.length > 0) {
|
|
761
|
+
problems.push(
|
|
762
|
+
`Расхождения контракта, не объявленные в реестре отставания:\n ${reconciliation.undeclaredLag.join('\n ')}`,
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
if (reconciliation.incomplete.length > 0) {
|
|
766
|
+
problems.push(
|
|
767
|
+
`Строки реестра без причины, владельца или тяжести из словаря:\n ${reconciliation.incomplete.join('\n ')}`,
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
if (reconciliation.staleMissing.length > 0 || reconciliation.staleLag.length > 0) {
|
|
771
|
+
problems.push(
|
|
772
|
+
'Протухшие строки реестра отставания (расхождения больше нет — строку надо снять):\n ' +
|
|
773
|
+
[...reconciliation.staleMissing, ...reconciliation.staleLag].join('\n '),
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
if (problems.length > 0) {
|
|
777
|
+
console.error(problems.join('\n\n'));
|
|
778
|
+
process.exit(1);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Fail-closed: записей ровно столько, сколько пар «инструмент × ветка» задаёт фикстура.
|
|
782
|
+
//
|
|
783
|
+
// ⛔ Ожидаемое число считается ПО САМОЙ ФИКСТУРЕ (`variantsByTool`), а не повторным вызовом
|
|
784
|
+
// `variantsOf` — иначе проверка была бы тавтологией цикла выгрузки. Ловит именно тот класс, который
|
|
785
|
+
// назвал Гейт A: подмена «безфикстурный инструмент даёт один безымянный вариант» на «даёт пустой
|
|
786
|
+
// список» молча выкинула бы из артефакта 26 инструментов (ICP, песочница, промпт-операции, каталог
|
|
787
|
+
// моделей, оба инструмента аналитики), и ни один тест на стороне API этого не увидел бы — их там
|
|
788
|
+
// нет и сравнивать не с чем.
|
|
789
|
+
const expectedRecordCount = toolDefinitions.reduce(
|
|
790
|
+
(sum, definition) =>
|
|
791
|
+
sum +
|
|
792
|
+
(typeof definition.createRequest !== 'function'
|
|
793
|
+
? 1
|
|
794
|
+
: Math.max(1, variantsByTool.get(definition.name)?.length ?? 0)),
|
|
795
|
+
0,
|
|
796
|
+
);
|
|
797
|
+
if (tools.length !== expectedRecordCount) {
|
|
798
|
+
console.error(
|
|
799
|
+
`Записей в выгрузке ${tools.length}, а пар «инструмент × ветка» ${expectedRecordCount}: ` +
|
|
800
|
+
'вариант потерян на выгрузке.',
|
|
801
|
+
);
|
|
802
|
+
process.exit(1);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Схемы входа обоих реестров — для сверки аргументов, которые называет навигация рабочей области (см. модуль схем).
|
|
806
|
+
// Выгружаемый инструмент без схемы ветки v2 — отказ сразу, для всех инструментов, а не красный сторож позже на сервере.
|
|
807
|
+
const shippedInputSchemas = collectInputSchemas(shipped.tools, 'отгруженный реестр');
|
|
808
|
+
const v2InputSchemas = collectInputSchemas(localRegistry.tools, 'ветка v2');
|
|
809
|
+
const withoutV2Schema = namesWithoutSchema(
|
|
810
|
+
tools.map((tool) => tool.name),
|
|
811
|
+
v2InputSchemas,
|
|
812
|
+
);
|
|
813
|
+
if (withoutV2Schema.length > 0) {
|
|
814
|
+
console.error(
|
|
815
|
+
`Нет схемы входа ветки v2 у выгружаемых инструментов: ${withoutV2Schema.join(', ')}`,
|
|
816
|
+
);
|
|
817
|
+
process.exit(1);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Отставание уезжает ОТДЕЛЬНЫМИ ключами, а не третьим видом записи внутри `tools`: `tools` —
|
|
821
|
+
// реестр реально существующих в v2 инструментов, и расширение его множества ослабило бы проверку
|
|
822
|
+
// «каждая запись серверной карты существует в пакете».
|
|
823
|
+
const payload = {
|
|
824
|
+
$comment:
|
|
825
|
+
'СГЕНЕРИРОВАНО besales-mcp (yarn publish:mcp-registry). Руками не править: правка потеряется при следующей выгрузке. ' +
|
|
826
|
+
'Запись = пара «инструмент × ветка»: у ветвящегося инструмента (вход решает метод или форму адреса) записей столько, сколько веток, и они различаются полем variant; ' +
|
|
827
|
+
'у неветвящегося поле variant отсутствует, а запись одна. Поэтому число записей БОЛЬШЕ числа инструментов. ' +
|
|
828
|
+
'samplePath — конкретный путь прогона, сопоставляется с шаблонами Nest посегментно. ' +
|
|
829
|
+
'shippedInputSchemas и v2InputSchemas — схемы входа всех инструментов отгруженного реестра и ветки v2 по имени (сверка аргументов навигации рабочей области).',
|
|
830
|
+
shippedRegistry: shipped.provenance,
|
|
831
|
+
// ⛔ Не справка, а ВХОД чужой проверки: besales-api по этому списку решает, менялось ли на
|
|
832
|
+
// отгружаемой линии то, из чего собрана выгрузка. Список берётся у самих чтений (загрузчик +
|
|
833
|
+
// исходник клиента), а не пишется здесь третьей копией.
|
|
834
|
+
// Замыкание импортов отгруженных определений — тоже вход: выгрузка ИСПОЛНЯЕТ отгруженный фильтр.
|
|
835
|
+
shippedInputPaths: [
|
|
836
|
+
...new Set([...SHIPPED_INPUT_PATHS, SHIPPED_CLIENT_SOURCE, ...shippedDefinitions.inputPaths]),
|
|
837
|
+
].sort(),
|
|
838
|
+
generatorV2Commit,
|
|
839
|
+
connectScopes,
|
|
840
|
+
v2ConnectScopes,
|
|
841
|
+
tools,
|
|
842
|
+
shippedOnly: diff.missingTools.map((name) => ({
|
|
843
|
+
name,
|
|
844
|
+
...lagRegistry.missingTools[name],
|
|
845
|
+
})),
|
|
846
|
+
contractLag: foundLag.map((entry) => ({
|
|
847
|
+
...entry,
|
|
848
|
+
...lagRegistry.contractLag[lagKey(entry)],
|
|
849
|
+
})),
|
|
850
|
+
// ⛔ Связь «прежнее имя → имя в v2» уезжает в выгрузку, потому что без неё besales-api не
|
|
851
|
+
// отличает переименованный инструмент от пропавшего: у переименованного отгруженное имя
|
|
852
|
+
// ИСЧЕЗАЕТ с поверхности, и клиент, зовущий его сегодня, получит «инструмент не найден».
|
|
853
|
+
// Эта пара — единственное, чем такой разрыв виден отдельно от расхождений полей.
|
|
854
|
+
toolSuccessors: lagRegistry.toolSuccessors ?? {},
|
|
855
|
+
// Все разделы долга доезжают до независимого потребителя API.
|
|
856
|
+
...remainingLagSections(lagRegistry),
|
|
857
|
+
shippedInputSchemas,
|
|
858
|
+
v2InputSchemas,
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
writeFileSync(OUT, `${JSON.stringify(payload, null, 2)}\n`);
|
|
862
|
+
// ⛔ Записи и инструменты — РАЗНЫЕ величины с тех пор, как ветвящийся инструмент даёт запись на
|
|
863
|
+
// ветку. Прежняя строка называла записи инструментами и разошлась бы с реальностью ровно там, где
|
|
864
|
+
// человек сверяет её глазами с числом инструментов реестра.
|
|
865
|
+
const apiRecords = tools.filter((t) => t.kind === 'api');
|
|
866
|
+
const distinctToolCount = new Set(tools.map((t) => t.name)).size;
|
|
867
|
+
const branchingToolCount = new Set(
|
|
868
|
+
apiRecords.filter((t) => t.variant !== undefined).map((t) => t.name),
|
|
869
|
+
).size;
|
|
870
|
+
console.log(
|
|
871
|
+
`Выгружено записей: ${tools.length} (api: ${apiRecords.length}) у ${distinctToolCount} инструментов, ` +
|
|
872
|
+
`из них ветвящихся: ${branchingToolCount}; ` +
|
|
873
|
+
`эталон ${shipped.provenance.source}:${shipped.provenance.ref ?? shipped.provenance.path}@${String(shipped.provenance.commit).slice(0, 7)} ` +
|
|
874
|
+
`(${shipped.provenance.toolCount} инструментов); отгружено-без-v2: ${diff.missingTools.length}; расхождений контракта: ${foundLag.length} ` +
|
|
875
|
+
`(из них отказов в коде инструмента: ${refusalLag.length}); образцов с альтернативами: ${tools.filter((t) => t.shippedSampleAlternatives).length}, ` +
|
|
876
|
+
`невозможных: ${tools.filter((t) => t.shippedSampleImpossible).length}; ` +
|
|
877
|
+
`схем входа: отгружено ${Object.keys(shippedInputSchemas).length}, ветка v2 ${Object.keys(v2InputSchemas).length}`,
|
|
878
|
+
);
|