@besales/mcp 0.47.1 → 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 -4
- 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 +12061 -6753
- 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 -427
- package/dist/tools/definitions/broadcast-analytics.js.map +1 -1
- package/dist/tools/definitions/broadcast-scheduler.d.ts +19 -13
- package/dist/tools/definitions/broadcast-scheduler.js +217 -128
- 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 -39
- package/dist/tools/definitions/crm-platform.js +235 -344
- 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 -354
- 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 +17 -29
- package/dist/tools/definitions/getcourse-cold-welcome.js +182 -242
- 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 +701 -222
- 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 +414 -284
- package/dist/tools/definitions/shared.js +436 -619
- 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 +1105 -621
- 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 +105862 -22115
- 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 -927
- 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
|
@@ -1,128 +1,94 @@
|
|
|
1
|
+
// «Первое сообщение» GetCourse (холодное приветствие): предпросмотр, запуск, пакет сегментов, ход пакета,
|
|
2
|
+
// возобновление и отмена. Схемы — с отгруженной линии (`getcourse-cold-welcome.ts`): клиент,
|
|
3
|
+
// зовущий инструменты сегодня, не получает отказа ни на одном поле, которое принимал. Отличия v2 — в теле
|
|
4
|
+
// запроса (канал называется channelId, подтверждение отправки людям уходит на сервер), в текстах для модели и
|
|
5
|
+
// в одном добавленном поле: `product_code` у предпросмотра — прогноз предохранителя обязан судить тот же
|
|
6
|
+
// продукт, что запуск.
|
|
1
7
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
8
|
+
import { guardModeEnum } from './getcourse-cold-outbound-settings.js';
|
|
9
|
+
import { compactObject, defineTool, getcourseTransportEnum, uuidSchema, withInstructions, } from './shared.js';
|
|
3
10
|
const MESSAGE_MAX_LENGTH = 4000;
|
|
4
11
|
const LABEL_MAX_LENGTH = 200;
|
|
5
12
|
const MAX_CONTACTS = 5000;
|
|
6
|
-
/** Потолок сегментов в пакете — паритет с
|
|
13
|
+
/** Потолок сегментов в пакете — паритет с сервером и с пакетом волны. */
|
|
7
14
|
const MAX_BATCH_SEGMENTS = 10;
|
|
15
|
+
const continuationSchema = z
|
|
16
|
+
.literal(true)
|
|
17
|
+
.describe('Только по явной просьбе человека продолжить обращение по файлу contacts. Сначала preview с теми же текстом, сегментом, продуктом и каналами, затем подтверждённый start. Не выбирать автоматически по alreadyWelcomed.')
|
|
18
|
+
.optional();
|
|
19
|
+
const continuationHasContacts = (input) => input.continuation === undefined || input.contacts !== undefined;
|
|
20
|
+
const continuationHasText = (input) => input.continuation === undefined ||
|
|
21
|
+
input.message !== undefined ||
|
|
22
|
+
input.mailing_variant_id !== undefined;
|
|
23
|
+
const CONTINUATION_AUDIENCE = 'continuation разрешён только по файлу contacts, без created_after';
|
|
24
|
+
const CONTINUATION_TEXT = 'continuation: передай message или mailing_variant_id с выбранным текстом и сегментом';
|
|
25
|
+
function continuationPreviewHints(response) {
|
|
26
|
+
const data = response;
|
|
27
|
+
const total = data?.totalContacts;
|
|
28
|
+
const narrowed = data?.narrowedOutByTransports ?? data?.narrowedOutByChannels;
|
|
29
|
+
return [
|
|
30
|
+
'ПРОДОЛЖЕНИЕ: totalContacts — аудитория прогноза. alreadyWelcomed — справка о прежнем первом сообщении, НЕ вычитается из охвата. Охват = totalContacts − narrowedOutByTransports (прежнее имя narrowedOutByChannels); channelsUnknown не вычитается. В текущем v2 channelsUnknown=0: отправка школу не переспрашивает.',
|
|
31
|
+
...(typeof total === 'number' &&
|
|
32
|
+
Number.isSafeInteger(total) &&
|
|
33
|
+
typeof narrowed === 'number' &&
|
|
34
|
+
Number.isSafeInteger(narrowed) &&
|
|
35
|
+
narrowed >= 0 &&
|
|
36
|
+
total >= narrowed
|
|
37
|
+
? [
|
|
38
|
+
`Охват прогноза: ${total - narrowed}. Это прогноз, окончательная доставка видна в статусе задачи.`,
|
|
39
|
+
]
|
|
40
|
+
: []),
|
|
41
|
+
'В продолжении touchClaimed может быть больше нуля; blockedBy.alreadyGreeted=0. alreadySentSegment запрещает повтор того же текста тому же сегменту; тот же шаблон другому сегменту разрешается лишь спустя больше трёх суток. Прежние приветствия права не освобождают.',
|
|
42
|
+
'Разговор блокирует отправку, только если прежде была наша реплика: человек ответил после неё либо наша реплика моложе трёх суток. Ровно трое суток временной гейт отпускает. Без нашей реплики одно сообщение человека этот гейт не включает.',
|
|
43
|
+
'Продолжение выбирай только по явной просьбе человека. Сначала preview с теми же continuation, файлом, текстом, сегментом, продуктом и каналами; после подтверждения start с explicit_confirmation=true. При 400 исправь названные в ошибке текст, сегмент или список; не повторяй отправку автоматически.',
|
|
44
|
+
];
|
|
45
|
+
}
|
|
8
46
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* Оба ИДЕНТИФИКАТОРА — ЧИСЛА в строковом виде, и проверяется именно форма: паритет с сестринской
|
|
13
|
-
* `besales_getcourse_wave_run_start`. Непустоты мало — «AB-123» доезжал до штампа уже ПОСЛЕ
|
|
14
|
-
* доставки сообщения, а «user@mail.ru» молча выпадал в отбракованные строки.
|
|
47
|
+
* Режим набора каналов, снятый прежней системой: принимается ради старых клиентов и на поведение не
|
|
48
|
+
* влияет. Список `channels` значит «слать сюда», судьбу КАЖДОГО канала решает сервер по фактам о человеке.
|
|
15
49
|
*/
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
50
|
+
export const coldWelcomeChannelsModeEnum = z.enum(['RESTRICT', 'ADD']);
|
|
51
|
+
/**
|
|
52
|
+
* Идентификаторы строки — ЧИСЛА в строковом виде, и проверяется именно форма: «AB-123» доезжал бы до штампа
|
|
53
|
+
* уже ПОСЛЕ доставки сообщения.
|
|
54
|
+
*/
|
|
55
|
+
const numericIdSchema = (field) => z.string().trim().regex(/^\d+$/, `${field} обязан быть числовым идентификатором GetCourse`);
|
|
20
56
|
const contactSchema = z
|
|
21
57
|
.object({
|
|
22
58
|
contact_id: numericIdSchema('contact_id'),
|
|
23
59
|
deal_id: numericIdSchema('deal_id').optional(),
|
|
24
60
|
/**
|
|
25
|
-
* Момент входа
|
|
26
|
-
*
|
|
27
|
-
* ⚠️⚠️ Заполняй его, когда предсписок собран ПРАВИЛОМ (события LeakEngine, выгрузка по
|
|
28
|
-
* сегменту): у каждой строки там свой момент, и он ФАКТ О ЧЕЛОВЕКЕ. Пока поле не принималось,
|
|
29
|
-
* все холодные строки уезжали без возраста и выпадали из любого непустого фильтра свежести.
|
|
30
|
-
*
|
|
31
|
-
* ⚠️⚠️ Дату запуска сюда подставлять НЕЛЬЗЯ. Разброс возраста в таких когортах — от часа до
|
|
32
|
-
* 294 дней при медиане 6,3 дня: общий момент схлопнул бы месяцы когорт в одну корзину, а
|
|
33
|
-
* разрез при этом выглядел бы наполненным. Не знаешь момента строки — не передавай ключ.
|
|
34
|
-
*
|
|
35
|
-
* `{ offset: true }` — зона обязательна (…Z либо ±ЧЧ:ММ), паритет с сестринской
|
|
36
|
-
* `besales_getcourse_wave_run_start`: без зоны момент читался бы по зоне процесса, и возраст
|
|
37
|
-
* разошёлся бы на часы между средами.
|
|
61
|
+
* Момент входа человека в когорту — на нём считается свежесть в «Аналитике рассылок». Дату запуска
|
|
62
|
+
* подставлять НЕЛЬЗЯ: общий момент схлопнул бы месяцы когорт в одну корзину. Зона обязательна.
|
|
38
63
|
*/
|
|
39
64
|
segment_entered_at: z.string().datetime({ offset: true }).optional(),
|
|
40
65
|
/**
|
|
41
|
-
*
|
|
42
|
-
* `
|
|
43
|
-
*
|
|
44
|
-
* ⚠️⚠️ Заполняй, когда файл собран из НЕСКОЛЬКИХ воронок: одна метка на запуск заставляла
|
|
45
|
-
* писать в поле воронки когорту («reg-no-show|дбо»), и ось «Воронка» переставала отвечать
|
|
46
|
-
* на свой вопрос — по f11 фильтр показывал НОЛЬ отправок за 30 дней при 3267 регистрациях
|
|
47
|
-
* и 1496 реально написанных людях (замер 02.09.2026). Когорта и продукт при этом уже лежат
|
|
48
|
-
* в своих полях `segment` и `product_code` — дублировать их в воронке нечем.
|
|
49
|
-
*
|
|
50
|
-
* Не передан — берётся воронка запуска (`funnel`), поведение прежнее.
|
|
66
|
+
* Момент РЕГИСТРАЦИИ, по которой человек попал в сегмент, — граница потока у предохранителя: заявки и
|
|
67
|
+
* оплаты раньше неё не держат. Подставлять `segment_entered_at` или «созрел с» НЕЛЬЗЯ. Зона обязательна.
|
|
51
68
|
*/
|
|
69
|
+
registered_at: z.string().datetime({ offset: true }).optional(),
|
|
70
|
+
/** Воронка ЭТОГО человека (файл из нескольких воронок); не передана — воронка запуска. */
|
|
52
71
|
funnel: z.string().min(1).max(LABEL_MAX_LENGTH).optional(),
|
|
53
72
|
})
|
|
54
73
|
.strict();
|
|
55
|
-
const toContacts = (contacts) => contacts?.map((contact) => ({
|
|
56
|
-
|
|
74
|
+
const toContacts = (contacts) => contacts?.map((contact) => compactObject({
|
|
75
|
+
getcourseUserId: contact.contact_id,
|
|
57
76
|
dealId: contact.deal_id,
|
|
58
77
|
segmentEnteredAt: contact.segment_entered_at,
|
|
78
|
+
registeredAt: contact.registered_at,
|
|
59
79
|
funnel: contact.funnel,
|
|
60
80
|
}));
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
* Строка ИМПОРТА — шире отправочной: кроме идентификаторов несёт данные самого контакта.
|
|
72
|
-
*
|
|
73
|
-
* Ключи остаются snake_case и уезжают на бэкенд КАК ЕСТЬ: там их читает разбор по алиасам колонок
|
|
74
|
-
* экспорта GetCourse (`contact_id`, `gc_deal_id`, `first_name`, …), тот же, что и для файла.
|
|
75
|
-
* Переименование в camelCase завело бы вторую копию правил разбора — а разбор решает, какой
|
|
76
|
-
* транспорт у контакта и попадёт ли он в базу вообще.
|
|
77
|
-
*/
|
|
78
|
-
const importContactSchema = z
|
|
79
|
-
.object({
|
|
80
|
-
contact_id: numericIdSchema('contact_id'),
|
|
81
|
-
deal_id: emptyAsAbsent(numericIdSchema('deal_id')),
|
|
82
|
-
dialog_id: emptyAsAbsent(numericIdSchema('dialog_id')),
|
|
83
|
-
transport: emptyAsAbsent(z.string().trim().max(50)),
|
|
84
|
-
email: emptyAsAbsent(z.string().trim().email('email невалиден').max(320)),
|
|
85
|
-
phone: emptyAsAbsent(z.string().trim().max(64)),
|
|
86
|
-
first_name: emptyAsAbsent(z.string().trim().max(200)),
|
|
87
|
-
last_name: emptyAsAbsent(z.string().trim().max(200)),
|
|
88
|
-
})
|
|
89
|
-
.strict();
|
|
90
|
-
/**
|
|
91
|
-
* Рассылка «Первое сообщение» (холодное приветствие GetCourse): МЫ пишем первыми тем, кому НАШЕГО
|
|
92
|
-
* исходящего ещё не было.
|
|
93
|
-
*
|
|
94
|
-
* ⚠️⚠️ Именно «нашего исходящего не было», а не «диалога нет»: человек, который написал школе и
|
|
95
|
-
* остался без ответа, — законный адресат (замер 01.09.2026: 4216 таких карточек из 8428 с диалогом,
|
|
96
|
-
* и их частые реплики «я буду», «ок», «+» это подтверждения участия в эфире). Исключать их из
|
|
97
|
-
* когорты НЕ надо. Отправка НЕОБРАТИМА и не идемпотентна на стороне GetCourse — повтор создал
|
|
98
|
-
* бы второе сообщение живому человеку, поэтому старт требует explicit_confirmation и всегда
|
|
99
|
-
* предваряется preview.
|
|
100
|
-
*/
|
|
81
|
+
const dealFieldsSchema = z.record(z.string().regex(/^\d+$/, 'Ключ deal_fields обязан быть числовым fieldId GetCourse'), z.union([z.string(), z.number(), z.boolean(), z.null()]));
|
|
82
|
+
/** Ровно одна аудитория. */
|
|
83
|
+
const ONE_AUDIENCE = 'Ровно одна аудитория: created_after (по дате) ЛИБО contacts (по файлу)';
|
|
84
|
+
/** Ровно один источник текста — у запуска и пакета. */
|
|
85
|
+
const ONE_TEXT_SOURCE = 'Ровно один источник текста: message (разовый) ЛИБО mailing_variant_id (сохранённая рассылка)';
|
|
86
|
+
const CHANNELS_MODE_DEPRECATED = '⚠️ channels_mode УСТАРЕЛ и на поведение НЕ влияет. Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у человека; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels, а мессенджеры перечисли явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется.';
|
|
87
|
+
/** Предохранитель — общий текст запуска, пакета и предпросмотра. */
|
|
88
|
+
const GUARD_INSTRUCTION = 'ПРЕДОХРАНИТЕЛИ. Перед отправкой каждый человек проверяется по фактам школы: идёт ли у него вебинарная серия, есть ли действующая заявка (с ним работает менеджер), оплачен ли продукт запуска. Заявка держит только отправку своего продукта. Заявки и оплаты судятся только после регистрации, по которой человек попал в сегмент: передавай её моментом contacts[].registered_at (не segment_entered_at и не «созрел с»: у reg-no-show и postweb они на дни позже, и заявка или оплата во время серии выпала бы из правила); без него судится вся история человека. Режимы правил (выключено / предупреждать / блокировать) настраиваются у канала — besales_platform_settings_update, getcourse_settings.guard_*: там решение видно всей команде. Исходы в итоге: SKIPPED_ACTIVE_SERIES, SKIPPED_ACTIVE_DEAL, SKIPPED_GUARD_UNAVAILABLE.';
|
|
89
|
+
const GUARD_SERIES_IS_DEFERRAL = '⚠️ Блокировка по серии — это ОТСРОЧКА, а не потеря: серия кончится, и человек станет доступен следующему запуску. Не пытайся обойти правило, чтобы «добрать объём».';
|
|
90
|
+
const GUARD_PAID_NEEDS_PRODUCT = '⚠️ Правило оплаты сверяет продукт запуска с оплаченными. Не задан product_code (и у рассылки нет продукта по умолчанию), а у человека есть оплата — отправка пропускается с SKIPPED_GUARD_UNAVAILABLE («сверять не с чем»): чинится запуском с продуктом.';
|
|
101
91
|
export const getcourseColdWelcomeTools = [
|
|
102
|
-
defineTool({
|
|
103
|
-
name: 'besales_contact_touch_history',
|
|
104
|
-
sideEffect: 'none',
|
|
105
|
-
requiredFields: ['getcourse_user_id'],
|
|
106
|
-
defaultWorkspaceId: true,
|
|
107
|
-
schema: z
|
|
108
|
-
.object({
|
|
109
|
-
workspace_id: uuidSchema.optional(),
|
|
110
|
-
getcourse_user_id: z.number().int().positive(),
|
|
111
|
-
})
|
|
112
|
-
.strict(),
|
|
113
|
-
createRequest: (input) => ({
|
|
114
|
-
method: 'GET',
|
|
115
|
-
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/touch-history/${input.getcourse_user_id}`,
|
|
116
|
-
}),
|
|
117
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
118
|
-
'⚠️⚠️ touches и sends отвечают на РАЗНЫЕ вопросы, складывать их нельзя. touches — журнал касаний: это ПРАВО, взятое ДО отправки, поэтому строка есть и у попытки, которая никуда не ушла (status UNKNOWN или зависший CLAIMED). sends — реестр получателей, он пишется ПОСЛЕ доставки и best-effort: его отсутствие неотправки НЕ доказывает (замер: 10 198 приветствий против 9 802 строк).',
|
|
119
|
-
'На вопрос «писали ли мы этому человеку» отвечает НАЛИЧИЕ строки в touches со статусом не RELEASED (RELEASED — доказанная неотправка, касание свободно) либо непустой firstWelcomeAt.',
|
|
120
|
-
'touchKey — служебное имя права, не показывай его пользователю как есть. Четыре рода: ярлык сегмента, text:<отпечаток шаблона> (правило «тот же текст не дважды»), registration:<заказ> (приветствие регистранта), legacy:welcome (право, восстановленное за период до появления журнала). Человеку называй mailingName и дату.',
|
|
121
|
-
'mailingName пуст у строк до 09.09.2026 — колонки тогда не было; это не потеря данных.',
|
|
122
|
-
'Ключ — человек ШКОЛЫ, поэтому история включает касания со ВСЕХ площадок воркспейса. Это и есть право: две площадки одной школы — один живой человек.',
|
|
123
|
-
'truncated=true — строк больше, чем поместилось; для разбора этого обычно достаточно, полная выгрузка сюда не помещается намеренно.',
|
|
124
|
-
]),
|
|
125
|
-
}),
|
|
126
92
|
defineTool({
|
|
127
93
|
name: 'besales_getcourse_cold_welcome_preview',
|
|
128
94
|
sideEffect: 'none',
|
|
@@ -134,47 +100,76 @@ export const getcourseColdWelcomeTools = [
|
|
|
134
100
|
platform_id: uuidSchema,
|
|
135
101
|
created_after: z.string().datetime({ offset: true }).optional(),
|
|
136
102
|
contacts: z.array(contactSchema).min(1).max(MAX_CONTACTS).optional(),
|
|
103
|
+
continuation: continuationSchema,
|
|
137
104
|
mailing_variant_id: uuidSchema.optional(),
|
|
138
105
|
/**
|
|
139
|
-
* ⚠️⚠️ ИДЕНТИЧНОСТЬ КАСАНИЯ:
|
|
140
|
-
*
|
|
141
|
-
* отпечатком шаблона. Без них прогноз молчит там, где старт ответит DUPLICATE.
|
|
106
|
+
* ⚠️⚠️ ИДЕНТИЧНОСТЬ КАСАНИЯ: сегмент и текст запуска — ими считается прогноз правил («этим сегментом
|
|
107
|
+
* уже слали», «тот же текст не дважды»). Передавай ровно те, с которыми пойдёт старт.
|
|
142
108
|
*/
|
|
143
109
|
segment: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
144
110
|
message: z.string().max(MESSAGE_MAX_LENGTH).optional(),
|
|
111
|
+
/**
|
|
112
|
+
* ⚠️⚠️ Продукт запуска — тот же, что пойдёт в старт: им предохранитель сверяет оплату и живую заявку.
|
|
113
|
+
* Без него прогноз судил бы «продукт неизвестен» и показал бы охват, которого у запуска с продуктом не будет.
|
|
114
|
+
*/
|
|
115
|
+
product_code: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
145
116
|
channels: z.array(getcourseTransportEnum).optional(),
|
|
146
117
|
channels_mode: coldWelcomeChannelsModeEnum.optional(),
|
|
147
118
|
})
|
|
148
119
|
.strict()
|
|
149
120
|
.refine((input) => (input.created_after !== undefined) !== (input.contacts !== undefined), {
|
|
150
|
-
message:
|
|
151
|
-
})
|
|
121
|
+
message: ONE_AUDIENCE,
|
|
122
|
+
})
|
|
123
|
+
.refine(continuationHasContacts, { message: CONTINUATION_AUDIENCE })
|
|
124
|
+
.refine(continuationHasText, { message: CONTINUATION_TEXT })
|
|
125
|
+
.refine((input) => input.continuation !== true ||
|
|
126
|
+
input.message === undefined ||
|
|
127
|
+
input.mailing_variant_id === undefined, { message: ONE_TEXT_SOURCE }),
|
|
152
128
|
createRequest: (input) => ({
|
|
153
129
|
method: 'POST',
|
|
154
130
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/preview`,
|
|
155
131
|
body: compactObject({
|
|
156
|
-
|
|
132
|
+
channelId: input.platform_id,
|
|
157
133
|
createdAfter: input.created_after,
|
|
158
134
|
contacts: toContacts(input.contacts),
|
|
135
|
+
continuation: input.continuation,
|
|
159
136
|
mailingVariantId: input.mailing_variant_id,
|
|
160
137
|
segment: input.segment,
|
|
161
138
|
message: input.message,
|
|
162
|
-
|
|
163
|
-
|
|
139
|
+
productCode: input.product_code,
|
|
140
|
+
transports: input.channels,
|
|
141
|
+
transportsMode: input.channels_mode,
|
|
164
142
|
}),
|
|
165
143
|
}),
|
|
166
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
144
|
+
enhanceResponse: (response, input) => withInstructions(response, [
|
|
145
|
+
...(input.continuation === true ? continuationPreviewHints(response) : []),
|
|
146
|
+
input.continuation === true
|
|
147
|
+
? 'Ничего не отправляет и ничего не пишет. Для продолжения нужен ровно один источник текста: message либо mailing_variant_id с выбранным непустым текстом и сегментом. Отсутствие или пробельный текст, вариант без выбранного текста или сегмента — ошибка: исправь текст/сегмент до запуска.'
|
|
148
|
+
: 'Ничего не отправляет и ничего не пишет. В предпросмотре message может переопределять текст mailing_variant_id; настройки рассылки при этом сохраняются. У запуска выбери ровно один источник текста.',
|
|
149
|
+
...(input.continuation === true
|
|
150
|
+
? []
|
|
151
|
+
: [
|
|
152
|
+
'⚠️ Текст предпросмотру не обязателен: без message и mailing_variant_id (или когда у рассылки нет текста для сегмента запуска) охват считается без проверок текста, textSource: null, а warnings[] с code TEXT_CHECKS_SKIPPED словами называет причину. Скажи пользователю, что запуск без текста не начнётся: нужен текст или рассылка с текстом для этого сегмента.',
|
|
153
|
+
'totalContacts — сколько ЕЩЁ может получить первое сообщение; alreadyWelcomed — сколько уже получали его раньше (оно одноразово НА ЧЕЛОВЕКА, не на рассылку); foundContacts — сколько нашлось всего.',
|
|
154
|
+
'⚠️⚠️ ФАКТИЧЕСКИЙ охват = totalContacts − narrowedOutByChannels (доказанно недостижимые выбранными каналами). Называй пользователю именно эту разность: сырой totalContacts завысит обещание, а отправку не отозвать. channelsUnknown всегда 0: отправка школу не переспрашивает.',
|
|
155
|
+
]),
|
|
156
|
+
CHANNELS_MODE_DEPRECATED,
|
|
157
|
+
'transportsNotAllowedByChannel — выбранные каналы, не включённые у канала GetCourse: они не уедут ни в каком случае. Назови их пользователю, это чинится в настройках канала, а не повтором запуска.',
|
|
158
|
+
'segment и textSource — какой сегмент (в том числе сегмент рассылки по умолчанию) и какой текст уйдут: разовый (MESSAGE), текст сегмента у рассылки (SEGMENT) или общий текст рассылки (DEFAULT); null — текста нет (причина — в warnings). Назови их пользователю ДО подтверждения.',
|
|
159
|
+
'alreadyInDialog — разговор с человеком уже идёт; blockedByContact — состояние человека запрещает писать (удалён, заблокирован, отказался, у менеджера, бот заглушён) по исходу. Для аудитории по файлу дополнительно приходят notInBase (человека нет на канале: импортируй его до запуска), invalidRows, duplicateRows, rowsWithoutSegmentEntry и rowsWithoutRegistration.',
|
|
160
|
+
'⚠️⚠️ guardForecast — ПРЕДОХРАНИТЕЛЬ: blockedBy — сколько людей он остановит по правилу (идёт вебинарная серия, действующая заявка, оплатил продукт; guardUnverified — проверить было нечем), warned — правило в режиме «предупреждать» сработало, отправка пойдёт; unverifiedCause — почему проверить не смогли. Заявки и оплаты судятся после contacts[].registered_at, если он передан, иначе за всю историю человека.',
|
|
161
|
+
'⚠️⚠️ product_code передавай ТОТ ЖЕ, с которым пойдёт besales_getcourse_cold_welcome_start: им предохранитель сверяет оплату и живую заявку (заявка держит только отправку своего продукта). Не передан — берётся продукт рассылки по умолчанию; нет и его — продукт неизвестен, и прогноз назовёт заблокированными людей, которых запуск с продуктом пропустил бы.',
|
|
162
|
+
'Часть людей отсеется только в прогоне: нет даты эфира календарной цепочки, переменные текста без значения — разбивка будет в outcomes задачи.',
|
|
163
|
+
...(input.continuation === true
|
|
164
|
+
? [
|
|
165
|
+
'policyForecast — правила отправки: alreadySentSegment — этот текст этим сегментом уже отправлен; activeEpisode — идёт приветствие по регистрации; cooldown — тихий период. Причины взаимно исключают друг друга: сумма — люди, а не срабатывания.',
|
|
166
|
+
]
|
|
167
|
+
: [
|
|
168
|
+
'⚠️⚠️ policyForecast — ПРАВИЛА ОТПРАВКИ. blockedBy.alreadySentSegment — этим сегментом человеку уже уходило НАШЕЙ отправкой; blockedBy.alreadyGreeted — уже получал первое сообщение; blockedBy.activeEpisode — идёт приветствие по регистрации; blockedBy.resendPause — пауза повтора сегмента (только у расписания); blockedBy.cooldown — тихий период; touchClaimed — касание этого сегмента уже занято (только у продолжения расписания; у ручного запуска 0). Причины взаимно исключают друг друга, поэтому сумма — это ЛЮДИ, а не срабатывания: называй пользователю сумму, разбор — только по запросу.',
|
|
169
|
+
]),
|
|
170
|
+
'⚠️ policyForecast.externalWaveTouched — ИНФОРМАЦИЯ, а не запрет: этим сегментом человека рассылала школа своими процессами, и наш догон в мессенджерах уйдёт как обычно. В отсев это число НЕ входит.',
|
|
171
|
+
'warnings — предупреждения словами, с кодом: TEXT_CHECKS_SKIPPED — текста нет, охват посчитан без проверок текста (почему — в message); ENTRY_VARIABLE_NOT_IN_FIELD_MAP — переменная входа календарной цепочки не в карте полей сделки: первое сообщение уйдёт, а цепочка человека не подхватит. Назови их пользователю до запуска.',
|
|
172
|
+
'⚠️ Прогноз — на МОМЕНТ ЗАПРОСА. Блокирует сама отправка: она пересчитывает правила постранично вплотную к транспорту, поэтому итог в outcomes может отличаться.',
|
|
178
173
|
]),
|
|
179
174
|
}),
|
|
180
175
|
defineTool({
|
|
@@ -189,39 +184,39 @@ export const getcourseColdWelcomeTools = [
|
|
|
189
184
|
platform_id: uuidSchema.optional(),
|
|
190
185
|
created_after: z.string().datetime({ offset: true }).optional(),
|
|
191
186
|
contacts: z.array(contactSchema).min(1).max(MAX_CONTACTS).optional(),
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
.optional(),
|
|
187
|
+
continuation: continuationSchema,
|
|
188
|
+
deal_fields: dealFieldsSchema.optional(),
|
|
195
189
|
message: z.string().trim().min(1).max(MESSAGE_MAX_LENGTH).optional(),
|
|
196
190
|
mailing_variant_id: uuidSchema.optional(),
|
|
197
191
|
segment: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
198
192
|
product_code: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
199
|
-
/**
|
|
200
|
-
* ⚠️⚠️ Воронка ШКОЛЫ («f11 — ДБО / NR / ВК / In Stream»), а НЕ когорта. Тип отбора идёт
|
|
201
|
-
* в `segment`, продукт в `product_code`, подпись запуска в `cohort_label`. Текст правила
|
|
202
|
-
* живёт в описании поля (`mcp-tools.json`) — его читает агент; здесь напоминание для
|
|
203
|
-
* того, кто правит схему.
|
|
204
|
-
*/
|
|
193
|
+
/** Воронка ШКОЛЫ («f11 — ДБО / NR / ВК / In Stream»), а НЕ когорта: текст правила — в описании поля. */
|
|
205
194
|
funnel: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
206
195
|
cohort_label: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
207
196
|
channels: z.array(getcourseTransportEnum).optional(),
|
|
208
197
|
channels_mode: coldWelcomeChannelsModeEnum.optional(),
|
|
209
198
|
explicit_confirmation: z.literal(true),
|
|
199
|
+
idempotency_key: uuidSchema
|
|
200
|
+
.describe('UUID намерения: сохрани до отправки с подтверждёнными файлом и текстом. Повтор того же запуска — с тем же ключом; новый подтверждённый запуск — с новым. Передаётся заголовком Idempotency-Key.')
|
|
201
|
+
.optional(),
|
|
210
202
|
})
|
|
211
203
|
.strict()
|
|
212
204
|
.refine((input) => (input.message !== undefined) !== (input.mailing_variant_id !== undefined), {
|
|
213
|
-
message:
|
|
205
|
+
message: ONE_TEXT_SOURCE,
|
|
214
206
|
})
|
|
215
207
|
.refine((input) => (input.created_after !== undefined) !== (input.contacts !== undefined), {
|
|
216
|
-
message:
|
|
217
|
-
})
|
|
208
|
+
message: ONE_AUDIENCE,
|
|
209
|
+
})
|
|
210
|
+
.refine(continuationHasContacts, { message: CONTINUATION_AUDIENCE }),
|
|
218
211
|
createRequest: (input) => ({
|
|
219
212
|
method: 'POST',
|
|
220
213
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome`,
|
|
214
|
+
...(input.idempotency_key === undefined ? {} : { idempotencyKey: input.idempotency_key }),
|
|
221
215
|
body: compactObject({
|
|
222
|
-
|
|
216
|
+
channelId: input.platform_id,
|
|
223
217
|
createdAfter: input.created_after,
|
|
224
218
|
contacts: toContacts(input.contacts),
|
|
219
|
+
continuation: input.continuation,
|
|
225
220
|
dealFields: input.deal_fields,
|
|
226
221
|
message: input.message,
|
|
227
222
|
mailingVariantId: input.mailing_variant_id,
|
|
@@ -229,23 +224,30 @@ export const getcourseColdWelcomeTools = [
|
|
|
229
224
|
productCode: input.product_code,
|
|
230
225
|
funnel: input.funnel,
|
|
231
226
|
cohortLabel: input.cohort_label,
|
|
232
|
-
|
|
233
|
-
|
|
227
|
+
transports: input.channels,
|
|
228
|
+
transportsMode: input.channels_mode,
|
|
229
|
+
explicitConfirmation: input.explicit_confirmation,
|
|
234
230
|
}),
|
|
235
231
|
}),
|
|
236
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
237
|
-
'
|
|
238
|
-
'
|
|
232
|
+
enhanceResponse: (response, input) => withInstructions(response, [
|
|
233
|
+
'Сохрани idempotency_key вместе с подтверждёнными параметрами. При неизвестном исходе сверяй статус и повторяй только тот же запуск с тем же ключом, не создавай новое намерение автоматически.',
|
|
234
|
+
'Рассылка запущена фоном: опрашивай besales_getcourse_contact_import_status по jobId каждые 10–30 секунд до COMPLETED, PARTIAL или FAILED; прогресс, разбивка исходов (outcomes), отправленные «вслепую» и штамп полей сделки (dealStamp) живут в этой задаче. Запуск идёт пакетом из одного сегмента: batchId — его пакет, ход виден и через besales_getcourse_cold_welcome_batch_status.',
|
|
235
|
+
'policyForecast — прогноз правил на момент старта; null — прогноз не посчитался (отказ чтения), запуск при этом идёт. null НЕ значит «никого не заблокировали».',
|
|
236
|
+
'cohort_label — имя ЭТОГО запуска в «Аналитике рассылок». Задавай его на каждом запуске: без него разрез «по запускам» различает их только датой.',
|
|
239
237
|
'Текст заморожен снимком: правка рассылки НЕ меняет идущий запуск.',
|
|
240
|
-
'Если у рассылки заданы
|
|
241
|
-
'⚠️
|
|
242
|
-
|
|
238
|
+
'Если у рассылки заданы тексты по сегментам и segment совпал — уедет ТЕКСТ СЕГМЕНТА. Назови пользователю, какой текст выбран, ДО подтверждения: отправку не отозвать.',
|
|
239
|
+
'⚠️ Сегмент аудиторию НЕ отбирает. Поэтому посегментный текст разрешён только с contacts (файл): с created_after он ушёл бы ВСЕЙ когорте после даты. Такой запуск отвергается 400.',
|
|
240
|
+
input.continuation === true
|
|
241
|
+
? 'Продолжение поставлено в очередь. alreadyWelcomed — справка; тот же текст тому же сегменту повторно не уйдёт. Прогноз и постановка не доказывают доставку: итог — в статусе задачи.'
|
|
242
|
+
: 'Повторный запуск по той же границе безопасен: уже получившие первое сообщение не получат второе.',
|
|
243
243
|
'platform_id и deal_fields можно опустить, если они заданы в рассылке как «по умолчанию» — сервер подставит их сам.',
|
|
244
|
-
'Пустой объект deal_fields — НЕ то же, что отсутствие ключа: он означает «на этом запуске без полей» и гасит
|
|
245
|
-
|
|
246
|
-
'deal_fields штампуются ПОСЛЕ успешной отправки (пин из строки файла, иначе
|
|
247
|
-
'contacts[].segment_entered_at — точный ISO-момент (с зоной) входа человека в когорту; на нём считается свежесть в «Аналитике рассылок».
|
|
248
|
-
|
|
244
|
+
'Пустой объект deal_fields — НЕ то же, что отсутствие ключа: он означает «на этом запуске без полей» и гасит умолчания рассылки.',
|
|
245
|
+
CHANNELS_MODE_DEPRECATED,
|
|
246
|
+
'deal_fields штампуются ПОСЛЕ успешной отправки (пин из строки файла, иначе сделка человека); их отказ не отменяет отправку и виден счётчиком dealStamp в besales_getcourse_contact_import_status.',
|
|
247
|
+
'contacts[].segment_entered_at — точный ISO-момент (с зоной) входа человека в когорту; на нём считается свежесть в «Аналитике рассылок». ⚠️ Дату запуска подставлять НЕЛЬЗЯ.',
|
|
248
|
+
GUARD_INSTRUCTION,
|
|
249
|
+
GUARD_PAID_NEEDS_PRODUCT,
|
|
250
|
+
'Человек, у которого переменная текста осталась без значения, ПРОПУСКАЕТСЯ (outcome SKIPPED_UNRESOLVED_VARS) — сырые {скобки} живому человеку не уедут. Отметка приветствия при этом не сгорает: проставь значение и запусти повторно, человек доберётся.',
|
|
249
251
|
]),
|
|
250
252
|
}),
|
|
251
253
|
defineTool({
|
|
@@ -268,19 +270,14 @@ export const getcourseColdWelcomeTools = [
|
|
|
268
270
|
product_code: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
269
271
|
funnel: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
270
272
|
cohort_label: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
271
|
-
deal_fields:
|
|
272
|
-
.record(z
|
|
273
|
-
.string()
|
|
274
|
-
.regex(/^\d+$/, 'Ключ deal_fields обязан быть числовым fieldId GetCourse'), z.union([z.string(), z.number(), z.boolean(), z.null()]))
|
|
275
|
-
.optional(),
|
|
273
|
+
deal_fields: dealFieldsSchema.optional(),
|
|
276
274
|
contacts: z.array(contactSchema).min(1).max(MAX_CONTACTS),
|
|
277
275
|
})
|
|
278
276
|
.strict())
|
|
279
277
|
.min(1)
|
|
280
278
|
.max(MAX_BATCH_SEGMENTS),
|
|
281
|
-
// Перекрытие предохранителей на ЭТОТ пакет. Не передано — настройки
|
|
282
|
-
//
|
|
283
|
-
// в настройках площадки, чтобы его было видно всем, а не только автору вызова.
|
|
279
|
+
// Перекрытие предохранителей на ЭТОТ пакет. Не передано — настройки канала. Ослабление здесь —
|
|
280
|
+
// аварийный обход одной отправки; постоянное решение принимается в настройках канала.
|
|
284
281
|
guards: z
|
|
285
282
|
.object({
|
|
286
283
|
active_series: guardModeEnum.optional(),
|
|
@@ -292,18 +289,16 @@ export const getcourseColdWelcomeTools = [
|
|
|
292
289
|
explicit_confirmation: z.literal(true),
|
|
293
290
|
})
|
|
294
291
|
.strict()
|
|
295
|
-
.refine((input) => (input.message !== undefined) !== (input.mailing_variant_id !== undefined), {
|
|
296
|
-
message: 'Ровно один источник текста: message (разовый) ЛИБО mailing_variant_id (сохранённая рассылка)',
|
|
297
|
-
}),
|
|
292
|
+
.refine((input) => (input.message !== undefined) !== (input.mailing_variant_id !== undefined), { message: ONE_TEXT_SOURCE }),
|
|
298
293
|
createRequest: (input) => ({
|
|
299
294
|
method: 'POST',
|
|
300
295
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/batch`,
|
|
301
296
|
body: compactObject({
|
|
302
|
-
|
|
297
|
+
channelId: input.platform_id,
|
|
303
298
|
message: input.message,
|
|
304
299
|
mailingVariantId: input.mailing_variant_id,
|
|
305
|
-
|
|
306
|
-
|
|
300
|
+
transports: input.channels,
|
|
301
|
+
transportsMode: input.channels_mode,
|
|
307
302
|
segments: input.segments.map((segment) => compactObject({
|
|
308
303
|
segment: segment.segment,
|
|
309
304
|
productCode: segment.product_code,
|
|
@@ -319,24 +314,24 @@ export const getcourseColdWelcomeTools = [
|
|
|
319
314
|
paid: input.guards.paid,
|
|
320
315
|
})
|
|
321
316
|
: undefined,
|
|
317
|
+
explicitConfirmation: input.explicit_confirmation,
|
|
322
318
|
}),
|
|
323
319
|
}),
|
|
324
320
|
enhanceResponse: (response) => withInstructions(response, [
|
|
325
|
-
'Пакет: несколько сегментов одним вызовом, у каждого свой список
|
|
326
|
-
'cohort_label задаётся ПОСЕГМЕНТНО: каждый сегмент — отдельный запуск со своей задачей и
|
|
327
|
-
'Сегменты идут ПО
|
|
328
|
-
'contacts[].segment_entered_at — точный ISO-момент (с зоной) входа человека в когорту;
|
|
329
|
-
'Весь пакет проверяется ДО первой отправки: сегмент без текста ИЛИ текст с переменными, которые не подставляются его
|
|
330
|
-
'⚠️ Проверка переменных на плане ВЫБОРОЧНАЯ (несколько
|
|
331
|
-
'⚠️ Переменные, которые отправка дочитывает из сделки (календарные поля замапленной площадки), план НЕ проверяет — судить по до-синковому снимку значило бы блокировать каждый пакет календарной площадки. Все остальные проверяются. Если пакет упал на календарной переменной — это баг, а не настройка.',
|
|
321
|
+
'Пакет: несколько сегментов одним вызовом, у каждого свой список людей, свои метки и свои поля сделки.',
|
|
322
|
+
'cohort_label задаётся ПОСЕГМЕНТНО: каждый сегмент — отдельный запуск со своей задачей и когортой.',
|
|
323
|
+
'Сегменты идут ПО ОЧЕРЕДИ. Прогресс смотри через besales_getcourse_cold_welcome_batch_status по batchId; о ЗАВЕРШЕНИИ пакета платформа доложит сама в чат уведомлений пространства, поэтому опрашивать в цикле не нужно.',
|
|
324
|
+
'contacts[].segment_entered_at — точный ISO-момент (с зоной) входа человека в когорту; передавай его посегментно, когда предсписок собран ПРАВИЛОМ. ⚠️ Дату запуска подставлять НЕЛЬЗЯ.',
|
|
325
|
+
'Весь пакет проверяется ДО первой отправки: сегмент без текста ИЛИ текст с переменными, которые не подставляются его людям, отменяет пакет целиком, пока никому ничего не ушло. В ошибке названы сегмент и сами переменные: чинить надо значение переменной.',
|
|
326
|
+
'⚠️ Проверка переменных на плане ВЫБОРОЧНАЯ (несколько человек сегмента) и не гарантирует, что подставится всем. Полноту держит гейт на самой отправке — человек с сырыми скобками пропускается с outcome SKIPPED_UNRESOLVED_VARS. Имена, которые отправка дочитает из закреплённой сделки, план у человека с закреплённой сделкой не проверяет.',
|
|
332
327
|
'Отказ одного сегмента НЕ останавливает остальные — смотри разбивку в статусе.',
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
'⚠️
|
|
337
|
-
'
|
|
338
|
-
'⚠️⚠️ policyForecast — прогноз ПРАВИЛ ОТПРАВКИ ПОСЕГМЕНТНО: сколько людей блока не пропустят «этим сегментом уже слали», «уже получал первое сообщение», «идёт приветствие по регистрации», «эфир ещё не прошёл», тихий период и «тот же текст». Показывай пользователю сумму по блокам сразу после запуска: у пакета отдельного предпросмотра нет, и это единственные числа правил, которые он увидит.',
|
|
328
|
+
GUARD_INSTRUCTION,
|
|
329
|
+
GUARD_SERIES_IS_DEFERRAL,
|
|
330
|
+
GUARD_PAID_NEEDS_PRODUCT,
|
|
331
|
+
'⚠️ Поле guards ослабляет проверку на ОДИН пакет и предназначено для аварийного обхода; оно сохраняется в план и переживает возобновление. Постоянное решение принимается в настройках канала (besales_platform_settings_update, getcourse_settings.guard_*) — там его видно всей команде.',
|
|
332
|
+
'⚠️⚠️ policyForecast — прогноз ПРАВИЛ ОТПРАВКИ ПОСЕГМЕНТНО (segment — сегмент блока): сколько людей блока не пропустят «этим сегментом уже слали», «уже получал первое сообщение», «идёт приветствие по регистрации», тихий период. Показывай пользователю сумму по блокам сразу после запуска.',
|
|
339
333
|
'⚠️ policyForecast — best-effort: ПУСТОЙ массив значит «прогноз не посчитался» (отказ чтения), а НЕ «никого не заблокировали». Пакет при этом идёт. Нужны надёжные числа до запуска — сделай besales_getcourse_cold_welcome_preview на каждый блок с его segment.',
|
|
334
|
+
'⚠️ 409 «в пространстве уже идёт пакет „Первого сообщения“» — не сбой: дождись его (besales_getcourse_cold_welcome_batch_status) или отмени. Людям при таком отказе ничего не ушло.',
|
|
340
335
|
]),
|
|
341
336
|
}),
|
|
342
337
|
defineTool({
|
|
@@ -344,20 +339,19 @@ export const getcourseColdWelcomeTools = [
|
|
|
344
339
|
sideEffect: 'none',
|
|
345
340
|
requiredFields: ['batch_id'],
|
|
346
341
|
defaultWorkspaceId: true,
|
|
347
|
-
schema: z
|
|
348
|
-
.object({ workspace_id: uuidSchema.optional(), batch_id: uuidSchema })
|
|
349
|
-
.strict(),
|
|
342
|
+
schema: z.object({ workspace_id: uuidSchema.optional(), batch_id: uuidSchema }).strict(),
|
|
350
343
|
createRequest: (input) => ({
|
|
351
344
|
method: 'GET',
|
|
352
345
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/batch/${input.batch_id}`,
|
|
353
346
|
}),
|
|
354
347
|
enhanceResponse: (response) => withInstructions(response, [
|
|
355
|
-
'state — агрегат по пакету, segments[] — разбивка: у каждого свой статус, свой importJobId и своя причина
|
|
356
|
-
'completedAt — момент, когда закрылись ВСЕ сегменты; null означает «пакет ещё идёт». Это и есть ответ на вопрос «закончилось
|
|
357
|
-
'summary — план, ДОКАЗАННЫЕ доставки
|
|
348
|
+
'state — агрегат по пакету, segments[] — разбивка: у каждого свой статус, свой importJobId и своя причина отказа (error — словами).',
|
|
349
|
+
'completedAt — момент, когда закрылись ВСЕ сегменты; null означает «пакет ещё идёт». Это и есть ответ на вопрос «закончилось ли».',
|
|
350
|
+
'summary — план, ДОКАЗАННЫЕ доставки и слитая разбивка исходов; у каждого сегмента те же delivered/outcomes; sentWithoutChannelEvidence — отправлено «вслепую» (без доказательства, что человек есть в этом канале). SKIPPED_UNRESOLVED_VARS означает «переменные текста без значения»: такие люди не приветствованы и доберутся повторным запуском. SKIPPED_RESEND_PAUSE бывает только у пакета расписания.',
|
|
358
351
|
'⚠️ summary.segmentsWithoutOutcomes > 0 — у стольких сегментов прогон оборвался, не записав итог: их исходы в разбивку НЕ вошли, и судить о них можно только по delivered. outcomes=null у сегмента значит ровно это, а НЕ «все нули».',
|
|
359
|
-
'⚠️ Опрашивать в цикле не нужно: о завершении пакета и о его обрыве платформа сама докладывает в чат уведомлений
|
|
360
|
-
'stalled=true означает, что
|
|
352
|
+
'⚠️ Опрашивать в цикле не нужно: о завершении пакета и о его обрыве платформа сама докладывает в чат уведомлений пространства. Оборванный пакет подметатель находит сам в пределах ~15 минут и освобождает задачу импорта.',
|
|
353
|
+
'stalled=true означает, что исполнитель пакета оборвался (перезапуск сервиса). НЕ запускай пакет заново — зови besales_getcourse_cold_welcome_batch_resume по тому же batch_id: план хранится на сервере, пересобирать списки не нужно, а уже отправленным людям повтор не уйдёт.',
|
|
354
|
+
'⚠️ Исключение — пакет, который собрало РАСПИСАНИЕ (origin = SCHEDULE): resume ответит 409. Не повторяй вызов: не начатые сегменты такого пакета подметатель гасит сам, а их люди уйдут следующим запуском расписания.',
|
|
361
355
|
]),
|
|
362
356
|
}),
|
|
363
357
|
defineTool({
|
|
@@ -365,15 +359,15 @@ export const getcourseColdWelcomeTools = [
|
|
|
365
359
|
sideEffect: 'spend',
|
|
366
360
|
requiredFields: ['batch_id'],
|
|
367
361
|
defaultWorkspaceId: true,
|
|
368
|
-
schema: z
|
|
369
|
-
.object({ workspace_id: uuidSchema.optional(), batch_id: uuidSchema })
|
|
370
|
-
.strict(),
|
|
362
|
+
schema: z.object({ workspace_id: uuidSchema.optional(), batch_id: uuidSchema }).strict(),
|
|
371
363
|
createRequest: (input) => ({
|
|
372
364
|
method: 'POST',
|
|
373
365
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/batch/${input.batch_id}/resume`,
|
|
374
366
|
}),
|
|
375
367
|
enhanceResponse: (response) => withInstructions(response, [
|
|
376
|
-
'Поднимает
|
|
368
|
+
'Поднимает исполнителя для НЕ НАЧАТЫХ сегментов оборвавшегося пакета. Подтверждения не требует: повтора отправки не будет — приветствие одноразово НА ЧЕЛОВЕКА, а оборвавшийся идущий сегмент не переигрывается.',
|
|
369
|
+
'⚠️ Пакет, собранный РАСПИСАНИЕМ, вручную не возобновляется — 409. Это не сбой: владелец его остатка — прогон расписания. Не повторяй вызов и не запускай пакет заново руками.',
|
|
370
|
+
'⚠️ 409 «пакет не оборвался» — возобновлять нечего: пакет идёт сам.',
|
|
377
371
|
]),
|
|
378
372
|
}),
|
|
379
373
|
defineTool({
|
|
@@ -393,7 +387,7 @@ export const getcourseColdWelcomeTools = [
|
|
|
393
387
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/batch/${input.batch_id}/cancel`,
|
|
394
388
|
}),
|
|
395
389
|
enhanceResponse: (response) => withInstructions(response, [
|
|
396
|
-
'Отменяет ОСТАТОК пакета: не начатые сегменты и
|
|
390
|
+
'Отменяет ОСТАТОК пакета: не начатые сегменты и идущий сегмент. Уже отправленное не отзывается.',
|
|
397
391
|
]),
|
|
398
392
|
}),
|
|
399
393
|
defineTool({
|
|
@@ -412,61 +406,7 @@ export const getcourseColdWelcomeTools = [
|
|
|
412
406
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/${input.job_id}/cancel`,
|
|
413
407
|
}),
|
|
414
408
|
enhanceResponse: (response) => withInstructions(response, [
|
|
415
|
-
'Останавливает ОСТАТОК
|
|
416
|
-
]),
|
|
417
|
-
}),
|
|
418
|
-
defineTool({
|
|
419
|
-
name: 'besales_getcourse_contacts_import',
|
|
420
|
-
sideEffect: 'write',
|
|
421
|
-
verifyWithToolName: 'besales_getcourse_contact_import_status',
|
|
422
|
-
requiredFields: ['platform_id', 'contacts'],
|
|
423
|
-
defaultWorkspaceId: true,
|
|
424
|
-
schema: z
|
|
425
|
-
.object({
|
|
426
|
-
workspace_id: uuidSchema.optional(),
|
|
427
|
-
platform_id: uuidSchema,
|
|
428
|
-
contacts: z.array(importContactSchema).min(1).max(MAX_CONTACTS),
|
|
429
|
-
check_messenger_presence: z.boolean().optional(),
|
|
430
|
-
})
|
|
431
|
-
.strict(),
|
|
432
|
-
createRequest: (input) => ({
|
|
433
|
-
method: 'POST',
|
|
434
|
-
path: `/workspaces/${input.workspace_id}/chat-users/import/getcourse-contacts`,
|
|
435
|
-
body: compactObject({
|
|
436
|
-
platformId: input.platform_id,
|
|
437
|
-
contacts: input.contacts,
|
|
438
|
-
checkMessengerPresence: input.check_messenger_presence,
|
|
439
|
-
}),
|
|
440
|
-
}),
|
|
441
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
442
|
-
'НИЧЕГО НЕ ОТПРАВЛЯЕТ: заводит или обновляет контакты в базе платформы, чтобы по ним можно было запускать «Нашу отправку». Матчинг существующих — по contact_id (getcourse_user_id).',
|
|
443
|
-
'Импорт нужен ровно тогда, когда preview показал notInBase > 0: отправке нужен ChatUser, иначе контакт получает исход SKIPPED_NOT_IN_BASE и остаётся без сообщения.',
|
|
444
|
-
'Идёт фоном — вернувшийся jobId опрашивай через besales_getcourse_contact_import_status каждые 10–30 секунд до COMPLETED, PARTIAL или FAILED; отвечает сразу, а не по завершении.',
|
|
445
|
-
'⚠️ Гейт «один активный импорт на воркспейс» общий с волнами и пакетами: 409 означает «идёт другой импорт», а не сбой — дождись его и повтори.',
|
|
446
|
-
'⚠️ first_name прямо влияет на текст: обращение подставляется системным {greeting}, и у контакта без имени обращения не будет вовсе. Передавай имя, если оно есть в источнике.',
|
|
447
|
-
'check_messenger_presence по умолчанию включён и отсеивает контакты без Telegram/MAX/VK. Это API-вызов на КАЖДЫЙ контакт, поэтому на тысячах строк импорт идёт заметно дольше.',
|
|
448
|
-
'Повторный импорт того же списка безопасен: существующий контакт обновляется, второй не создаётся.',
|
|
449
|
-
]),
|
|
450
|
-
}),
|
|
451
|
-
defineTool({
|
|
452
|
-
name: 'besales_getcourse_contact_import_status',
|
|
453
|
-
sideEffect: 'none',
|
|
454
|
-
requiredFields: ['job_id'],
|
|
455
|
-
defaultWorkspaceId: true,
|
|
456
|
-
schema: z
|
|
457
|
-
.object({
|
|
458
|
-
workspace_id: uuidSchema.optional(),
|
|
459
|
-
job_id: uuidSchema,
|
|
460
|
-
})
|
|
461
|
-
.strict(),
|
|
462
|
-
createRequest: (input) => ({
|
|
463
|
-
method: 'GET',
|
|
464
|
-
path: `/workspaces/${input.workspace_id}/getcourse-contact-imports/${input.job_id}`,
|
|
465
|
-
}),
|
|
466
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
467
|
-
'Опрашивай каждые 10–30 секунд до terminal state: COMPLETED, PARTIAL или FAILED.',
|
|
468
|
-
'PARTIAL означает, что часть контактов записана, а часть завершилась ошибками; сверяй successCount, failedCount и errors перед следующим шагом.',
|
|
469
|
-
'Отмены нет: импорт пишет контакты по мере обработки. Повтор того же списка безопасен — существующие карточки обновятся без дублей.',
|
|
409
|
+
'Останавливает ОСТАТОК аудитории в пределах ~10 секунд; уже отправленное не отзывается. 409 — запуск уже завершён, останавливать нечего.',
|
|
470
410
|
]),
|
|
471
411
|
}),
|
|
472
412
|
];
|