@sendinel/mcp-server 1.0.33 → 1.0.34
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.
|
@@ -307,6 +307,15 @@ export function registerCampaignSetTools(server) {
|
|
|
307
307
|
const empty = set.campaigns.filter((c) => !set.steps.some((s) => s.campaign_id === c.id));
|
|
308
308
|
if (empty.length)
|
|
309
309
|
return j({ error: 'Some campaigns have no emails yet.', code: 'NO_EMAILS', campaigns: empty.map((c) => ({ id: c.id, name: c.name })) });
|
|
310
|
+
// An imported email whose wait wasn't in the source has no delay; it would never send (#3689).
|
|
311
|
+
const waitNotSet = set.steps.filter((s) => s.delay_days == null && s.delay_hours == null);
|
|
312
|
+
if (waitNotSet.length) {
|
|
313
|
+
return j({
|
|
314
|
+
error: 'Some emails have no wait set. Set how long to wait before each one, then try again.',
|
|
315
|
+
code: 'STEP_WAIT_NOT_SET',
|
|
316
|
+
emails: waitNotSet.map((s) => ({ campaign: set.campaigns.find((c) => c.id === s.campaign_id)?.name ?? s.campaign_id, email: s.step_order + 1, subject: s.subject })),
|
|
317
|
+
});
|
|
318
|
+
}
|
|
310
319
|
const approvalParams = { campaign_ids: [...ids].sort(), content_hash: campaignSetContentHash(set.campaigns, set.steps) };
|
|
311
320
|
const channelContext = currentChannelContext();
|
|
312
321
|
const decision = assertChannelCanExecute('activate_campaigns', approvalParams, channelContext);
|
package/build/tools/campaigns.js
CHANGED
|
@@ -595,6 +595,22 @@ export function registerCampaignTools(server) {
|
|
|
595
595
|
}, async ({ campaign_id, status, approval_id }) => {
|
|
596
596
|
// Human approval required for activation
|
|
597
597
|
if (status === 'active') {
|
|
598
|
+
// An imported email whose wait wasn't in the source has no delay; it would never send (#3689).
|
|
599
|
+
const { data: unsetSteps, error: stepsErr } = await db()
|
|
600
|
+
.from('campaign_steps')
|
|
601
|
+
.select('step_order, subject')
|
|
602
|
+
.eq('campaign_id', campaign_id)
|
|
603
|
+
.is('delay_days', null)
|
|
604
|
+
.is('delay_hours', null);
|
|
605
|
+
if (stepsErr)
|
|
606
|
+
return j({ error: `Could not check the campaign's emails: ${stepsErr.message}`, code: 'STEP_LOOKUP_FAILED' });
|
|
607
|
+
if (unsetSteps?.length) {
|
|
608
|
+
return j({
|
|
609
|
+
error: 'Some emails have no wait set. Set how long to wait before each one, then try again.',
|
|
610
|
+
code: 'STEP_WAIT_NOT_SET',
|
|
611
|
+
emails: unsetSteps.map((s) => ({ email: s.step_order + 1, subject: s.subject })),
|
|
612
|
+
});
|
|
613
|
+
}
|
|
598
614
|
const approvalParams = { campaign_id, status };
|
|
599
615
|
if (!approval_id) {
|
|
600
616
|
const channelContext = currentChannelContext();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendinel/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.34",
|
|
4
4
|
"description": "AI-controlled email operations control plane for campaigns, contacts, segments, analytics, and multi-provider sending via MCP.",
|
|
5
5
|
"mcpName": "ai.sendinel/mcp-server",
|
|
6
6
|
"type": "module",
|