@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
|
@@ -1,140 +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
|
-
* `segment_entered_at` или «созрел с» НЕЛЬЗЯ — у reg-no-show и postweb это конец серии плюс
|
|
46
|
-
* ожидание, и заявка или оплата во время серии выпала бы из правила (холодное сообщение
|
|
47
|
-
* купившему). Не знаешь момента регистрации — не передавай ключ: судится вся история. Зона
|
|
48
|
-
* обязательна, как у `segment_entered_at`.
|
|
66
|
+
* Момент РЕГИСТРАЦИИ, по которой человек попал в сегмент, — граница потока у предохранителя: заявки и
|
|
67
|
+
* оплаты раньше неё не держат. Подставлять `segment_entered_at` или «созрел с» НЕЛЬЗЯ. Зона обязательна.
|
|
49
68
|
*/
|
|
50
69
|
registered_at: z.string().datetime({ offset: true }).optional(),
|
|
51
|
-
/**
|
|
52
|
-
* Воронка ЭТОГО контакта — паритет со строкой волнового импорта (колонка
|
|
53
|
-
* `funnel | funnel_name | воронка | funnel_code`).
|
|
54
|
-
*
|
|
55
|
-
* ⚠️⚠️ Заполняй, когда файл собран из НЕСКОЛЬКИХ воронок: одна метка на запуск заставляла
|
|
56
|
-
* писать в поле воронки когорту («reg-no-show|дбо»), и ось «Воронка» переставала отвечать
|
|
57
|
-
* на свой вопрос — по f11 фильтр показывал НОЛЬ отправок за 30 дней при 3267 регистрациях
|
|
58
|
-
* и 1496 реально написанных людях (замер 02.09.2026). Когорта и продукт при этом уже лежат
|
|
59
|
-
* в своих полях `segment` и `product_code` — дублировать их в воронке нечем.
|
|
60
|
-
*
|
|
61
|
-
* Не передан — берётся воронка запуска (`funnel`), поведение прежнее.
|
|
62
|
-
*/
|
|
70
|
+
/** Воронка ЭТОГО человека (файл из нескольких воронок); не передана — воронка запуска. */
|
|
63
71
|
funnel: z.string().min(1).max(LABEL_MAX_LENGTH).optional(),
|
|
64
72
|
})
|
|
65
73
|
.strict();
|
|
66
|
-
const toContacts = (contacts) => contacts?.map((contact) => ({
|
|
67
|
-
|
|
74
|
+
const toContacts = (contacts) => contacts?.map((contact) => compactObject({
|
|
75
|
+
getcourseUserId: contact.contact_id,
|
|
68
76
|
dealId: contact.deal_id,
|
|
69
77
|
segmentEnteredAt: contact.segment_entered_at,
|
|
70
78
|
registeredAt: contact.registered_at,
|
|
71
79
|
funnel: contact.funnel,
|
|
72
80
|
}));
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
* Строка ИМПОРТА — шире отправочной: кроме идентификаторов несёт данные самого контакта.
|
|
84
|
-
*
|
|
85
|
-
* Ключи остаются snake_case и уезжают на бэкенд КАК ЕСТЬ: там их читает разбор по алиасам колонок
|
|
86
|
-
* экспорта GetCourse (`contact_id`, `gc_deal_id`, `first_name`, …), тот же, что и для файла.
|
|
87
|
-
* Переименование в camelCase завело бы вторую копию правил разбора — а разбор решает, какой
|
|
88
|
-
* транспорт у контакта и попадёт ли он в базу вообще.
|
|
89
|
-
*/
|
|
90
|
-
const importContactSchema = z
|
|
91
|
-
.object({
|
|
92
|
-
contact_id: numericIdSchema('contact_id'),
|
|
93
|
-
deal_id: emptyAsAbsent(numericIdSchema('deal_id')),
|
|
94
|
-
dialog_id: emptyAsAbsent(numericIdSchema('dialog_id')),
|
|
95
|
-
transport: emptyAsAbsent(z.string().trim().max(50)),
|
|
96
|
-
email: emptyAsAbsent(z.string().trim().email('email невалиден').max(320)),
|
|
97
|
-
phone: emptyAsAbsent(z.string().trim().max(64)),
|
|
98
|
-
first_name: emptyAsAbsent(z.string().trim().max(200)),
|
|
99
|
-
last_name: emptyAsAbsent(z.string().trim().max(200)),
|
|
100
|
-
})
|
|
101
|
-
.strict();
|
|
102
|
-
/**
|
|
103
|
-
* Рассылка «Первое сообщение» (холодное приветствие GetCourse): МЫ пишем первыми тем, кому НАШЕГО
|
|
104
|
-
* исходящего ещё не было.
|
|
105
|
-
*
|
|
106
|
-
* ⚠️⚠️ Именно «нашего исходящего не было», а не «диалога нет»: человек, который написал школе и
|
|
107
|
-
* остался без ответа, — законный адресат (замер 01.09.2026: 4216 таких карточек из 8428 с диалогом,
|
|
108
|
-
* и их частые реплики «я буду», «ок», «+» это подтверждения участия в эфире). Исключать их из
|
|
109
|
-
* когорты НЕ надо. Отправка НЕОБРАТИМА и не идемпотентна на стороне GetCourse — повтор создал
|
|
110
|
-
* бы второе сообщение живому человеку, поэтому старт требует explicit_confirmation и всегда
|
|
111
|
-
* предваряется preview.
|
|
112
|
-
*/
|
|
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 («сверять не с чем»): чинится запуском с продуктом.';
|
|
113
91
|
export const getcourseColdWelcomeTools = [
|
|
114
|
-
defineTool({
|
|
115
|
-
name: 'besales_contact_touch_history',
|
|
116
|
-
sideEffect: 'none',
|
|
117
|
-
requiredFields: ['getcourse_user_id'],
|
|
118
|
-
defaultWorkspaceId: true,
|
|
119
|
-
schema: z
|
|
120
|
-
.object({
|
|
121
|
-
workspace_id: uuidSchema.optional(),
|
|
122
|
-
getcourse_user_id: z.number().int().positive(),
|
|
123
|
-
})
|
|
124
|
-
.strict(),
|
|
125
|
-
createRequest: (input) => ({
|
|
126
|
-
method: 'GET',
|
|
127
|
-
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/touch-history/${input.getcourse_user_id}`,
|
|
128
|
-
}),
|
|
129
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
130
|
-
'⚠️⚠️ touches и sends отвечают на РАЗНЫЕ вопросы, складывать их нельзя. touches — журнал касаний: это ПРАВО, взятое ДО отправки, поэтому строка есть и у попытки, которая никуда не ушла (status UNKNOWN или зависший CLAIMED). sends — реестр получателей, он пишется ПОСЛЕ доставки и best-effort: его отсутствие неотправки НЕ доказывает (замер: 10 198 приветствий против 9 802 строк).',
|
|
131
|
-
'На вопрос «писали ли мы этому человеку» отвечает НАЛИЧИЕ строки в touches со статусом не RELEASED (RELEASED — доказанная неотправка, касание свободно) либо непустой firstWelcomeAt.',
|
|
132
|
-
'touchKey — служебное имя права, не показывай его пользователю как есть. Роды: ярлык сегмента; text:<отпечаток шаблона>@segment:<ярлык> (продолжение сегмента с 16.09.2026: этот текст этим сегментом не дважды, другим сегментом — после трёх суток тишины), с хвостом @after:<мс> — повтор сегмента по новой регистрации; голый text:<отпечаток шаблона> (отправка без ярлыка и продолжения до 16.09.2026); registration:<заказ> (приветствие регистранта); legacy:welcome (право, восстановленное за период до появления журнала). Человеку называй mailingName и дату.',
|
|
133
|
-
'mailingName пуст у строк до 09.09.2026 — колонки тогда не было; это не потеря данных.',
|
|
134
|
-
'Ключ — человек ШКОЛЫ, поэтому история включает касания со ВСЕХ площадок воркспейса. Это и есть право: две площадки одной школы — один живой человек.',
|
|
135
|
-
'truncated=true — строк больше, чем поместилось; для разбора этого обычно достаточно, полная выгрузка сюда не помещается намеренно.',
|
|
136
|
-
]),
|
|
137
|
-
}),
|
|
138
92
|
defineTool({
|
|
139
93
|
name: 'besales_getcourse_cold_welcome_preview',
|
|
140
94
|
sideEffect: 'none',
|
|
@@ -146,47 +100,76 @@ export const getcourseColdWelcomeTools = [
|
|
|
146
100
|
platform_id: uuidSchema,
|
|
147
101
|
created_after: z.string().datetime({ offset: true }).optional(),
|
|
148
102
|
contacts: z.array(contactSchema).min(1).max(MAX_CONTACTS).optional(),
|
|
103
|
+
continuation: continuationSchema,
|
|
149
104
|
mailing_variant_id: uuidSchema.optional(),
|
|
150
105
|
/**
|
|
151
|
-
* ⚠️⚠️ ИДЕНТИЧНОСТЬ КАСАНИЯ:
|
|
152
|
-
*
|
|
153
|
-
* отпечатком шаблона. Без них прогноз молчит там, где старт ответит DUPLICATE.
|
|
106
|
+
* ⚠️⚠️ ИДЕНТИЧНОСТЬ КАСАНИЯ: сегмент и текст запуска — ими считается прогноз правил («этим сегментом
|
|
107
|
+
* уже слали», «тот же текст не дважды»). Передавай ровно те, с которыми пойдёт старт.
|
|
154
108
|
*/
|
|
155
109
|
segment: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
156
110
|
message: z.string().max(MESSAGE_MAX_LENGTH).optional(),
|
|
111
|
+
/**
|
|
112
|
+
* ⚠️⚠️ Продукт запуска — тот же, что пойдёт в старт: им предохранитель сверяет оплату и живую заявку.
|
|
113
|
+
* Без него прогноз судил бы «продукт неизвестен» и показал бы охват, которого у запуска с продуктом не будет.
|
|
114
|
+
*/
|
|
115
|
+
product_code: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
157
116
|
channels: z.array(getcourseTransportEnum).optional(),
|
|
158
117
|
channels_mode: coldWelcomeChannelsModeEnum.optional(),
|
|
159
118
|
})
|
|
160
119
|
.strict()
|
|
161
120
|
.refine((input) => (input.created_after !== undefined) !== (input.contacts !== undefined), {
|
|
162
|
-
message:
|
|
163
|
-
})
|
|
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 }),
|
|
164
128
|
createRequest: (input) => ({
|
|
165
129
|
method: 'POST',
|
|
166
130
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/preview`,
|
|
167
131
|
body: compactObject({
|
|
168
|
-
|
|
132
|
+
channelId: input.platform_id,
|
|
169
133
|
createdAfter: input.created_after,
|
|
170
134
|
contacts: toContacts(input.contacts),
|
|
135
|
+
continuation: input.continuation,
|
|
171
136
|
mailingVariantId: input.mailing_variant_id,
|
|
172
137
|
segment: input.segment,
|
|
173
138
|
message: input.message,
|
|
174
|
-
|
|
175
|
-
|
|
139
|
+
productCode: input.product_code,
|
|
140
|
+
transports: input.channels,
|
|
141
|
+
transportsMode: input.channels_mode,
|
|
176
142
|
}),
|
|
177
143
|
}),
|
|
178
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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 может отличаться.',
|
|
190
173
|
]),
|
|
191
174
|
}),
|
|
192
175
|
defineTool({
|
|
@@ -201,39 +184,39 @@ export const getcourseColdWelcomeTools = [
|
|
|
201
184
|
platform_id: uuidSchema.optional(),
|
|
202
185
|
created_after: z.string().datetime({ offset: true }).optional(),
|
|
203
186
|
contacts: z.array(contactSchema).min(1).max(MAX_CONTACTS).optional(),
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
.optional(),
|
|
187
|
+
continuation: continuationSchema,
|
|
188
|
+
deal_fields: dealFieldsSchema.optional(),
|
|
207
189
|
message: z.string().trim().min(1).max(MESSAGE_MAX_LENGTH).optional(),
|
|
208
190
|
mailing_variant_id: uuidSchema.optional(),
|
|
209
191
|
segment: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
210
192
|
product_code: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
211
|
-
/**
|
|
212
|
-
* ⚠️⚠️ Воронка ШКОЛЫ («f11 — ДБО / NR / ВК / In Stream»), а НЕ когорта. Тип отбора идёт
|
|
213
|
-
* в `segment`, продукт в `product_code`, подпись запуска в `cohort_label`. Текст правила
|
|
214
|
-
* живёт в описании поля (`mcp-tools.json`) — его читает агент; здесь напоминание для
|
|
215
|
-
* того, кто правит схему.
|
|
216
|
-
*/
|
|
193
|
+
/** Воронка ШКОЛЫ («f11 — ДБО / NR / ВК / In Stream»), а НЕ когорта: текст правила — в описании поля. */
|
|
217
194
|
funnel: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
218
195
|
cohort_label: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
219
196
|
channels: z.array(getcourseTransportEnum).optional(),
|
|
220
197
|
channels_mode: coldWelcomeChannelsModeEnum.optional(),
|
|
221
198
|
explicit_confirmation: z.literal(true),
|
|
199
|
+
idempotency_key: uuidSchema
|
|
200
|
+
.describe('UUID намерения: сохрани до отправки с подтверждёнными файлом и текстом. Повтор того же запуска — с тем же ключом; новый подтверждённый запуск — с новым. Передаётся заголовком Idempotency-Key.')
|
|
201
|
+
.optional(),
|
|
222
202
|
})
|
|
223
203
|
.strict()
|
|
224
204
|
.refine((input) => (input.message !== undefined) !== (input.mailing_variant_id !== undefined), {
|
|
225
|
-
message:
|
|
205
|
+
message: ONE_TEXT_SOURCE,
|
|
226
206
|
})
|
|
227
207
|
.refine((input) => (input.created_after !== undefined) !== (input.contacts !== undefined), {
|
|
228
|
-
message:
|
|
229
|
-
})
|
|
208
|
+
message: ONE_AUDIENCE,
|
|
209
|
+
})
|
|
210
|
+
.refine(continuationHasContacts, { message: CONTINUATION_AUDIENCE }),
|
|
230
211
|
createRequest: (input) => ({
|
|
231
212
|
method: 'POST',
|
|
232
213
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome`,
|
|
214
|
+
...(input.idempotency_key === undefined ? {} : { idempotencyKey: input.idempotency_key }),
|
|
233
215
|
body: compactObject({
|
|
234
|
-
|
|
216
|
+
channelId: input.platform_id,
|
|
235
217
|
createdAfter: input.created_after,
|
|
236
218
|
contacts: toContacts(input.contacts),
|
|
219
|
+
continuation: input.continuation,
|
|
237
220
|
dealFields: input.deal_fields,
|
|
238
221
|
message: input.message,
|
|
239
222
|
mailingVariantId: input.mailing_variant_id,
|
|
@@ -241,23 +224,30 @@ export const getcourseColdWelcomeTools = [
|
|
|
241
224
|
productCode: input.product_code,
|
|
242
225
|
funnel: input.funnel,
|
|
243
226
|
cohortLabel: input.cohort_label,
|
|
244
|
-
|
|
245
|
-
|
|
227
|
+
transports: input.channels,
|
|
228
|
+
transportsMode: input.channels_mode,
|
|
229
|
+
explicitConfirmation: input.explicit_confirmation,
|
|
246
230
|
}),
|
|
247
231
|
}),
|
|
248
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
249
|
-
'
|
|
250
|
-
'
|
|
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 — имя ЭТОГО запуска в «Аналитике рассылок». Задавай его на каждом запуске: без него разрез «по запускам» различает их только датой.',
|
|
251
237
|
'Текст заморожен снимком: правка рассылки НЕ меняет идущий запуск.',
|
|
252
|
-
'Если у рассылки заданы
|
|
253
|
-
'⚠️
|
|
254
|
-
|
|
238
|
+
'Если у рассылки заданы тексты по сегментам и segment совпал — уедет ТЕКСТ СЕГМЕНТА. Назови пользователю, какой текст выбран, ДО подтверждения: отправку не отозвать.',
|
|
239
|
+
'⚠️ Сегмент аудиторию НЕ отбирает. Поэтому посегментный текст разрешён только с contacts (файл): с created_after он ушёл бы ВСЕЙ когорте после даты. Такой запуск отвергается 400.',
|
|
240
|
+
input.continuation === true
|
|
241
|
+
? 'Продолжение поставлено в очередь. alreadyWelcomed — справка; тот же текст тому же сегменту повторно не уйдёт. Прогноз и постановка не доказывают доставку: итог — в статусе задачи.'
|
|
242
|
+
: 'Повторный запуск по той же границе безопасен: уже получившие первое сообщение не получат второе.',
|
|
255
243
|
'platform_id и deal_fields можно опустить, если они заданы в рассылке как «по умолчанию» — сервер подставит их сам.',
|
|
256
|
-
'Пустой объект deal_fields — НЕ то же, что отсутствие ключа: он означает «на этом запуске без полей» и гасит
|
|
257
|
-
|
|
258
|
-
'deal_fields штампуются ПОСЛЕ успешной отправки (пин из строки файла, иначе
|
|
259
|
-
'contacts[].segment_entered_at — точный ISO-момент (с зоной) входа человека в когорту; на нём считается свежесть в «Аналитике рассылок».
|
|
260
|
-
|
|
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) — сырые {скобки} живому человеку не уедут. Отметка приветствия при этом не сгорает: проставь значение и запусти повторно, человек доберётся.',
|
|
261
251
|
]),
|
|
262
252
|
}),
|
|
263
253
|
defineTool({
|
|
@@ -280,19 +270,14 @@ export const getcourseColdWelcomeTools = [
|
|
|
280
270
|
product_code: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
281
271
|
funnel: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
282
272
|
cohort_label: z.string().max(LABEL_MAX_LENGTH).optional(),
|
|
283
|
-
deal_fields:
|
|
284
|
-
.record(z
|
|
285
|
-
.string()
|
|
286
|
-
.regex(/^\d+$/, 'Ключ deal_fields обязан быть числовым fieldId GetCourse'), z.union([z.string(), z.number(), z.boolean(), z.null()]))
|
|
287
|
-
.optional(),
|
|
273
|
+
deal_fields: dealFieldsSchema.optional(),
|
|
288
274
|
contacts: z.array(contactSchema).min(1).max(MAX_CONTACTS),
|
|
289
275
|
})
|
|
290
276
|
.strict())
|
|
291
277
|
.min(1)
|
|
292
278
|
.max(MAX_BATCH_SEGMENTS),
|
|
293
|
-
// Перекрытие предохранителей на ЭТОТ пакет. Не передано — настройки
|
|
294
|
-
//
|
|
295
|
-
// в настройках площадки, чтобы его было видно всем, а не только автору вызова.
|
|
279
|
+
// Перекрытие предохранителей на ЭТОТ пакет. Не передано — настройки канала. Ослабление здесь —
|
|
280
|
+
// аварийный обход одной отправки; постоянное решение принимается в настройках канала.
|
|
296
281
|
guards: z
|
|
297
282
|
.object({
|
|
298
283
|
active_series: guardModeEnum.optional(),
|
|
@@ -304,18 +289,16 @@ export const getcourseColdWelcomeTools = [
|
|
|
304
289
|
explicit_confirmation: z.literal(true),
|
|
305
290
|
})
|
|
306
291
|
.strict()
|
|
307
|
-
.refine((input) => (input.message !== undefined) !== (input.mailing_variant_id !== undefined), {
|
|
308
|
-
message: 'Ровно один источник текста: message (разовый) ЛИБО mailing_variant_id (сохранённая рассылка)',
|
|
309
|
-
}),
|
|
292
|
+
.refine((input) => (input.message !== undefined) !== (input.mailing_variant_id !== undefined), { message: ONE_TEXT_SOURCE }),
|
|
310
293
|
createRequest: (input) => ({
|
|
311
294
|
method: 'POST',
|
|
312
295
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/batch`,
|
|
313
296
|
body: compactObject({
|
|
314
|
-
|
|
297
|
+
channelId: input.platform_id,
|
|
315
298
|
message: input.message,
|
|
316
299
|
mailingVariantId: input.mailing_variant_id,
|
|
317
|
-
|
|
318
|
-
|
|
300
|
+
transports: input.channels,
|
|
301
|
+
transportsMode: input.channels_mode,
|
|
319
302
|
segments: input.segments.map((segment) => compactObject({
|
|
320
303
|
segment: segment.segment,
|
|
321
304
|
productCode: segment.product_code,
|
|
@@ -331,24 +314,24 @@ export const getcourseColdWelcomeTools = [
|
|
|
331
314
|
paid: input.guards.paid,
|
|
332
315
|
})
|
|
333
316
|
: undefined,
|
|
317
|
+
explicitConfirmation: input.explicit_confirmation,
|
|
334
318
|
}),
|
|
335
319
|
}),
|
|
336
320
|
enhanceResponse: (response) => withInstructions(response, [
|
|
337
|
-
'Пакет: несколько сегментов одним вызовом, у каждого свой список
|
|
338
|
-
'cohort_label задаётся ПОСЕГМЕНТНО: каждый сегмент — отдельный запуск со своей задачей и
|
|
339
|
-
'Сегменты идут ПО
|
|
340
|
-
'contacts[].segment_entered_at — точный ISO-момент (с зоной) входа человека в когорту;
|
|
341
|
-
'Весь пакет проверяется ДО первой отправки: сегмент без текста ИЛИ текст с переменными, которые не подставляются его
|
|
342
|
-
'⚠️ Проверка переменных на плане ВЫБОРОЧНАЯ (несколько
|
|
343
|
-
'⚠️ Переменные, которые отправка дочитывает из сделки (календарные поля замапленной площадки), план НЕ проверяет — судить по до-синковому снимку значило бы блокировать каждый пакет календарной площадки. Все остальные проверяются. Если пакет упал на календарной переменной — это баг, а не настройка.',
|
|
321
|
+
'Пакет: несколько сегментов одним вызовом, у каждого свой список людей, свои метки и свои поля сделки.',
|
|
322
|
+
'cohort_label задаётся ПОСЕГМЕНТНО: каждый сегмент — отдельный запуск со своей задачей и когортой.',
|
|
323
|
+
'Сегменты идут ПО ОЧЕРЕДИ. Прогресс смотри через besales_getcourse_cold_welcome_batch_status по batchId; о ЗАВЕРШЕНИИ пакета платформа доложит сама в чат уведомлений пространства, поэтому опрашивать в цикле не нужно.',
|
|
324
|
+
'contacts[].segment_entered_at — точный ISO-момент (с зоной) входа человека в когорту; передавай его посегментно, когда предсписок собран ПРАВИЛОМ. ⚠️ Дату запуска подставлять НЕЛЬЗЯ.',
|
|
325
|
+
'Весь пакет проверяется ДО первой отправки: сегмент без текста ИЛИ текст с переменными, которые не подставляются его людям, отменяет пакет целиком, пока никому ничего не ушло. В ошибке названы сегмент и сами переменные: чинить надо значение переменной.',
|
|
326
|
+
'⚠️ Проверка переменных на плане ВЫБОРОЧНАЯ (несколько человек сегмента) и не гарантирует, что подставится всем. Полноту держит гейт на самой отправке — человек с сырыми скобками пропускается с outcome SKIPPED_UNRESOLVED_VARS. Имена, которые отправка дочитает из закреплённой сделки, план у человека с закреплённой сделкой не проверяет.',
|
|
344
327
|
'Отказ одного сегмента НЕ останавливает остальные — смотри разбивку в статусе.',
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
'⚠️
|
|
349
|
-
'
|
|
350
|
-
'⚠️⚠️ 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 — сегмент блока): сколько людей блока не пропустят «этим сегментом уже слали», «уже получал первое сообщение», «идёт приветствие по регистрации», тихий период. Показывай пользователю сумму по блокам сразу после запуска.',
|
|
351
333
|
'⚠️ policyForecast — best-effort: ПУСТОЙ массив значит «прогноз не посчитался» (отказ чтения), а НЕ «никого не заблокировали». Пакет при этом идёт. Нужны надёжные числа до запуска — сделай besales_getcourse_cold_welcome_preview на каждый блок с его segment.',
|
|
334
|
+
'⚠️ 409 «в пространстве уже идёт пакет „Первого сообщения“» — не сбой: дождись его (besales_getcourse_cold_welcome_batch_status) или отмени. Людям при таком отказе ничего не ушло.',
|
|
352
335
|
]),
|
|
353
336
|
}),
|
|
354
337
|
defineTool({
|
|
@@ -356,21 +339,19 @@ export const getcourseColdWelcomeTools = [
|
|
|
356
339
|
sideEffect: 'none',
|
|
357
340
|
requiredFields: ['batch_id'],
|
|
358
341
|
defaultWorkspaceId: true,
|
|
359
|
-
schema: z
|
|
360
|
-
.object({ workspace_id: uuidSchema.optional(), batch_id: uuidSchema })
|
|
361
|
-
.strict(),
|
|
342
|
+
schema: z.object({ workspace_id: uuidSchema.optional(), batch_id: uuidSchema }).strict(),
|
|
362
343
|
createRequest: (input) => ({
|
|
363
344
|
method: 'GET',
|
|
364
345
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/batch/${input.batch_id}`,
|
|
365
346
|
}),
|
|
366
347
|
enhanceResponse: (response) => withInstructions(response, [
|
|
367
|
-
'state — агрегат по пакету, segments[] — разбивка: у каждого свой статус, свой importJobId и своя причина
|
|
368
|
-
'completedAt — момент, когда закрылись ВСЕ сегменты; null означает «пакет ещё идёт». Это и есть ответ на вопрос «закончилось
|
|
369
|
-
'summary — план, ДОКАЗАННЫЕ доставки
|
|
348
|
+
'state — агрегат по пакету, segments[] — разбивка: у каждого свой статус, свой importJobId и своя причина отказа (error — словами).',
|
|
349
|
+
'completedAt — момент, когда закрылись ВСЕ сегменты; null означает «пакет ещё идёт». Это и есть ответ на вопрос «закончилось ли».',
|
|
350
|
+
'summary — план, ДОКАЗАННЫЕ доставки и слитая разбивка исходов; у каждого сегмента те же delivered/outcomes; sentWithoutChannelEvidence — отправлено «вслепую» (без доказательства, что человек есть в этом канале). SKIPPED_UNRESOLVED_VARS означает «переменные текста без значения»: такие люди не приветствованы и доберутся повторным запуском. SKIPPED_RESEND_PAUSE бывает только у пакета расписания.',
|
|
370
351
|
'⚠️ summary.segmentsWithoutOutcomes > 0 — у стольких сегментов прогон оборвался, не записав итог: их исходы в разбивку НЕ вошли, и судить о них можно только по delivered. outcomes=null у сегмента значит ровно это, а НЕ «все нули».',
|
|
371
|
-
'⚠️ Опрашивать в цикле не нужно: о завершении пакета и о его обрыве платформа сама докладывает в чат уведомлений
|
|
372
|
-
'stalled=true означает, что
|
|
373
|
-
'⚠️ Исключение — пакет, который
|
|
352
|
+
'⚠️ Опрашивать в цикле не нужно: о завершении пакета и о его обрыве платформа сама докладывает в чат уведомлений пространства. Оборванный пакет подметатель находит сам в пределах ~15 минут и освобождает задачу импорта.',
|
|
353
|
+
'stalled=true означает, что исполнитель пакета оборвался (перезапуск сервиса). НЕ запускай пакет заново — зови besales_getcourse_cold_welcome_batch_resume по тому же batch_id: план хранится на сервере, пересобирать списки не нужно, а уже отправленным людям повтор не уйдёт.',
|
|
354
|
+
'⚠️ Исключение — пакет, который собрало РАСПИСАНИЕ (origin = SCHEDULE): resume ответит 409. Не повторяй вызов: не начатые сегменты такого пакета подметатель гасит сам, а их люди уйдут следующим запуском расписания.',
|
|
374
355
|
]),
|
|
375
356
|
}),
|
|
376
357
|
defineTool({
|
|
@@ -378,16 +359,15 @@ export const getcourseColdWelcomeTools = [
|
|
|
378
359
|
sideEffect: 'spend',
|
|
379
360
|
requiredFields: ['batch_id'],
|
|
380
361
|
defaultWorkspaceId: true,
|
|
381
|
-
schema: z
|
|
382
|
-
.object({ workspace_id: uuidSchema.optional(), batch_id: uuidSchema })
|
|
383
|
-
.strict(),
|
|
362
|
+
schema: z.object({ workspace_id: uuidSchema.optional(), batch_id: uuidSchema }).strict(),
|
|
384
363
|
createRequest: (input) => ({
|
|
385
364
|
method: 'POST',
|
|
386
365
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/batch/${input.batch_id}/resume`,
|
|
387
366
|
}),
|
|
388
367
|
enhanceResponse: (response) => withInstructions(response, [
|
|
389
|
-
'Поднимает
|
|
390
|
-
'⚠️ Пакет, собранный РАСПИСАНИЕМ, вручную не возобновляется — 409
|
|
368
|
+
'Поднимает исполнителя для НЕ НАЧАТЫХ сегментов оборвавшегося пакета. Подтверждения не требует: повтора отправки не будет — приветствие одноразово НА ЧЕЛОВЕКА, а оборвавшийся идущий сегмент не переигрывается.',
|
|
369
|
+
'⚠️ Пакет, собранный РАСПИСАНИЕМ, вручную не возобновляется — 409. Это не сбой: владелец его остатка — прогон расписания. Не повторяй вызов и не запускай пакет заново руками.',
|
|
370
|
+
'⚠️ 409 «пакет не оборвался» — возобновлять нечего: пакет идёт сам.',
|
|
391
371
|
]),
|
|
392
372
|
}),
|
|
393
373
|
defineTool({
|
|
@@ -407,7 +387,7 @@ export const getcourseColdWelcomeTools = [
|
|
|
407
387
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/batch/${input.batch_id}/cancel`,
|
|
408
388
|
}),
|
|
409
389
|
enhanceResponse: (response) => withInstructions(response, [
|
|
410
|
-
'Отменяет ОСТАТОК пакета: не начатые сегменты и
|
|
390
|
+
'Отменяет ОСТАТОК пакета: не начатые сегменты и идущий сегмент. Уже отправленное не отзывается.',
|
|
411
391
|
]),
|
|
412
392
|
}),
|
|
413
393
|
defineTool({
|
|
@@ -426,61 +406,7 @@ export const getcourseColdWelcomeTools = [
|
|
|
426
406
|
path: `/workspaces/${input.workspace_id}/getcourse-cold-welcome/${input.job_id}/cancel`,
|
|
427
407
|
}),
|
|
428
408
|
enhanceResponse: (response) => withInstructions(response, [
|
|
429
|
-
'Останавливает ОСТАТОК
|
|
430
|
-
]),
|
|
431
|
-
}),
|
|
432
|
-
defineTool({
|
|
433
|
-
name: 'besales_getcourse_contacts_import',
|
|
434
|
-
sideEffect: 'write',
|
|
435
|
-
verifyWithToolName: 'besales_getcourse_contact_import_status',
|
|
436
|
-
requiredFields: ['platform_id', 'contacts'],
|
|
437
|
-
defaultWorkspaceId: true,
|
|
438
|
-
schema: z
|
|
439
|
-
.object({
|
|
440
|
-
workspace_id: uuidSchema.optional(),
|
|
441
|
-
platform_id: uuidSchema,
|
|
442
|
-
contacts: z.array(importContactSchema).min(1).max(MAX_CONTACTS),
|
|
443
|
-
check_messenger_presence: z.boolean().optional(),
|
|
444
|
-
})
|
|
445
|
-
.strict(),
|
|
446
|
-
createRequest: (input) => ({
|
|
447
|
-
method: 'POST',
|
|
448
|
-
path: `/workspaces/${input.workspace_id}/chat-users/import/getcourse-contacts`,
|
|
449
|
-
body: compactObject({
|
|
450
|
-
platformId: input.platform_id,
|
|
451
|
-
contacts: input.contacts,
|
|
452
|
-
checkMessengerPresence: input.check_messenger_presence,
|
|
453
|
-
}),
|
|
454
|
-
}),
|
|
455
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
456
|
-
'НИЧЕГО НЕ ОТПРАВЛЯЕТ: заводит или обновляет контакты в базе платформы, чтобы по ним можно было запускать «Нашу отправку». Матчинг существующих — по contact_id (getcourse_user_id).',
|
|
457
|
-
'Импорт нужен ровно тогда, когда preview показал notInBase > 0: отправке нужен ChatUser, иначе контакт получает исход SKIPPED_NOT_IN_BASE и остаётся без сообщения.',
|
|
458
|
-
'Идёт фоном — вернувшийся jobId опрашивай через besales_getcourse_contact_import_status каждые 10–30 секунд до COMPLETED, PARTIAL или FAILED; отвечает сразу, а не по завершении.',
|
|
459
|
-
'⚠️ Гейт «один активный импорт на воркспейс» общий с волнами и пакетами: 409 означает «идёт другой импорт», а не сбой — дождись его и повтори.',
|
|
460
|
-
'⚠️ first_name прямо влияет на текст: обращение подставляется системным {greeting}, и у контакта без имени обращения не будет вовсе. Передавай имя, если оно есть в источнике.',
|
|
461
|
-
'check_messenger_presence по умолчанию включён и отсеивает контакты без Telegram/MAX/VK. Это API-вызов на КАЖДЫЙ контакт, поэтому на тысячах строк импорт идёт заметно дольше.',
|
|
462
|
-
'Повторный импорт того же списка безопасен: существующий контакт обновляется, второй не создаётся.',
|
|
463
|
-
]),
|
|
464
|
-
}),
|
|
465
|
-
defineTool({
|
|
466
|
-
name: 'besales_getcourse_contact_import_status',
|
|
467
|
-
sideEffect: 'none',
|
|
468
|
-
requiredFields: ['job_id'],
|
|
469
|
-
defaultWorkspaceId: true,
|
|
470
|
-
schema: z
|
|
471
|
-
.object({
|
|
472
|
-
workspace_id: uuidSchema.optional(),
|
|
473
|
-
job_id: uuidSchema,
|
|
474
|
-
})
|
|
475
|
-
.strict(),
|
|
476
|
-
createRequest: (input) => ({
|
|
477
|
-
method: 'GET',
|
|
478
|
-
path: `/workspaces/${input.workspace_id}/getcourse-contact-imports/${input.job_id}`,
|
|
479
|
-
}),
|
|
480
|
-
enhanceResponse: (response) => withInstructions(response, [
|
|
481
|
-
'Опрашивай каждые 10–30 секунд до terminal state: COMPLETED, PARTIAL или FAILED.',
|
|
482
|
-
'PARTIAL означает, что часть контактов записана, а часть завершилась ошибками; сверяй successCount, failedCount и errors перед следующим шагом.',
|
|
483
|
-
'Отмены нет: импорт пишет контакты по мере обработки. Повтор того же списка безопасен — существующие карточки обновятся без дублей.',
|
|
409
|
+
'Останавливает ОСТАТОК аудитории в пределах ~10 секунд; уже отправленное не отзывается. 409 — запуск уже завершён, останавливать нечего.',
|
|
484
410
|
]),
|
|
485
411
|
}),
|
|
486
412
|
];
|