@sellable/mcp 0.1.479 → 0.1.481

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.
@@ -13,6 +13,8 @@ type StartPrepareMessagesInput = PrepareMessagesBaseInput & {
13
13
  approvalMode?: ApprovalMode;
14
14
  autoContinue?: boolean;
15
15
  disableLowPassRateStop?: boolean;
16
+ requestHash?: string;
17
+ requestSource?: string;
16
18
  };
17
19
  type StatusPrepareMessagesInput = PrepareMessagesBaseInput;
18
20
  type CancelPrepareMessagesInput = PrepareMessagesBaseInput;
@@ -88,6 +88,8 @@ export function startPrepareCampaignMessages(input) {
88
88
  approvalMode: input.approvalMode,
89
89
  autoContinue: input.autoContinue,
90
90
  disableLowPassRateStop: input.disableLowPassRateStop,
91
+ requestHash: input.requestHash,
92
+ requestSource: input.requestSource,
91
93
  });
92
94
  }
93
95
  export function getPrepareCampaignMessagesStatus(input) {
@@ -241,11 +241,15 @@ export declare function executeRefillSendsCommand(input?: RefillSendsCommandInpu
241
241
  refreshedPaidInmailSenderIds: string[];
242
242
  failedPaidInmailRefreshes: {
243
243
  senderId: string;
244
+ attempts?: number;
244
245
  error: string;
246
+ errors?: string[];
245
247
  }[];
246
248
  refreshReceipts: {
247
249
  senderId: string;
248
250
  actionKey: string | null;
251
+ attempts: number;
252
+ retryErrors: string[];
249
253
  receipt: import("./senders.js").RefreshPaidInmailCreditsResponse;
250
254
  }[];
251
255
  attemptedSenderIds: string[];
@@ -4,6 +4,8 @@ import { startPrepareCampaignMessages } from "./campaign-message-preparation.js"
4
4
  import { confirmLeadList } from "./leads.js";
5
5
  import { getApi } from "../api.js";
6
6
  const DEFAULT_SCHEDULER_FORWARD_HOURS = 48;
7
+ const PAID_INMAIL_REFRESH_MAX_ATTEMPTS = 3;
8
+ const PAID_INMAIL_REFRESH_RETRY_DELAY_MS = Number(process.env.SELLABLE_MCP_PAID_REFRESH_RETRY_DELAY_MS ?? "1000");
7
9
  function normalizeStrings(values) {
8
10
  if (!Array.isArray(values))
9
11
  return [];
@@ -13,6 +15,11 @@ function normalizeStrings(values) {
13
15
  .filter(Boolean)),
14
16
  ];
15
17
  }
18
+ function sleep(ms) {
19
+ if (!Number.isFinite(ms) || ms <= 0)
20
+ return Promise.resolve();
21
+ return new Promise((resolve) => setTimeout(resolve, ms));
22
+ }
16
23
  function normalizeHorizonSendDays(value) {
17
24
  if (value === undefined || value === null)
18
25
  return null;
@@ -397,6 +404,32 @@ function actionSourceLeadListId(action) {
397
404
  stringValue(ids.sourceLeadListId) ??
398
405
  stringValue(action.sourceLeadListId));
399
406
  }
407
+ function actionSenderId(action) {
408
+ const ids = actionIds(action);
409
+ const toolInput = actionToolInput(action);
410
+ return (stringValue(toolInput.senderId) ??
411
+ stringValue(ids.senderId) ??
412
+ stringValue(action.senderId));
413
+ }
414
+ function actionSourceFingerprint(action) {
415
+ const ids = actionIds(action);
416
+ const toolInput = actionToolInput(action);
417
+ return (stringValue(toolInput.sourceFingerprint) ??
418
+ stringValue(ids.sourceFingerprint) ??
419
+ stringValue(action.sourceFingerprint));
420
+ }
421
+ function refillPrepareRequestHash(params) {
422
+ return [
423
+ "refill_sends",
424
+ "prepare_messages",
425
+ params.campaignId,
426
+ params.tableId ?? "no-table",
427
+ actionSenderId(params.action) ?? "all-senders",
428
+ actionSourceLeadListId(params.action) ?? "no-source-list",
429
+ actionSourceFingerprint(params.action) ?? "no-source-fingerprint",
430
+ params.approvalMode,
431
+ ].join(":");
432
+ }
400
433
  function boundedApprovalLimit(action) {
401
434
  const toolInput = actionToolInput(action);
402
435
  const rowSelector = recordValue(toolInput.rowSelector);
@@ -427,6 +460,26 @@ async function approveGeneratedMessagesBatch(action) {
427
460
  });
428
461
  return { status: "executed_and_reread", result };
429
462
  }
463
+ async function refreshPaidInmailCreditsWithRetry(senderId) {
464
+ const errors = [];
465
+ for (let attempt = 1; attempt <= PAID_INMAIL_REFRESH_MAX_ATTEMPTS; attempt += 1) {
466
+ try {
467
+ const receipt = await refreshPaidInmailCredits({ senderId });
468
+ return { receipt, attempts: attempt, errors };
469
+ }
470
+ catch (error) {
471
+ errors.push(error instanceof Error ? error.message : String(error));
472
+ if (attempt < PAID_INMAIL_REFRESH_MAX_ATTEMPTS) {
473
+ await sleep(PAID_INMAIL_REFRESH_RETRY_DELAY_MS);
474
+ }
475
+ }
476
+ }
477
+ return {
478
+ receipt: null,
479
+ attempts: PAID_INMAIL_REFRESH_MAX_ATTEMPTS,
480
+ errors,
481
+ };
482
+ }
430
483
  async function executeOneYoloPrimitive(action) {
431
484
  if (!action)
432
485
  return { status: "no_action" };
@@ -457,8 +510,17 @@ async function executeOneYoloPrimitive(action) {
457
510
  campaignId,
458
511
  tableId,
459
512
  targetPreparedMessages,
513
+ maxRowsToCheck: numberValue(toolInput.maxRowsToCheck) ?? 300,
460
514
  approvalMode,
461
515
  autoContinue: true,
516
+ disableLowPassRateStop: true,
517
+ requestHash: refillPrepareRequestHash({
518
+ action,
519
+ campaignId,
520
+ tableId,
521
+ approvalMode,
522
+ }),
523
+ requestSource: "refill_sends",
462
524
  });
463
525
  return { status: "executed_and_reread", result };
464
526
  }
@@ -529,21 +591,24 @@ export async function executeRefillSendsCommand(input = {}) {
529
591
  const failedPaidInmailRefreshes = [];
530
592
  const refreshReceipts = [];
531
593
  for (const action of refreshActions) {
532
- try {
533
- const receipt = await refreshPaidInmailCredits({
534
- senderId: action.senderId,
535
- });
594
+ const refreshResult = await refreshPaidInmailCreditsWithRetry(action.senderId);
595
+ if (refreshResult.receipt) {
536
596
  refreshedPaidInmailSenderIds.push(action.senderId);
537
597
  refreshReceipts.push({
538
598
  senderId: action.senderId,
539
599
  actionKey: action.actionKey ?? null,
540
- receipt,
600
+ attempts: refreshResult.attempts,
601
+ retryErrors: refreshResult.errors,
602
+ receipt: refreshResult.receipt,
541
603
  });
542
604
  }
543
- catch (error) {
605
+ else {
544
606
  failedPaidInmailRefreshes.push({
545
607
  senderId: action.senderId,
546
- error: error instanceof Error ? error.message : String(error),
608
+ attempts: refreshResult.attempts,
609
+ error: refreshResult.errors[refreshResult.errors.length - 1] ??
610
+ "paid InMail credit refresh failed",
611
+ errors: refreshResult.errors,
547
612
  });
548
613
  }
549
614
  }
@@ -578,7 +643,7 @@ export async function executeRefillSendsCommand(input = {}) {
578
643
  attemptedSenderIds: refreshActions.map((action) => action.senderId),
579
644
  targetPlanReread: refreshActions.length > 0,
580
645
  note: refreshActions.length > 0
581
- ? "refill_sends refreshed stale paid InMail credit facts internally, once per sender, then returned the post-refresh targetPlan."
646
+ ? "refill_sends refreshed stale paid InMail credit facts internally with bounded retries, once per sender, then returned the post-refresh targetPlan."
582
647
  : "No stale or missing paid InMail credit refresh candidates were present in the initial target plan.",
583
648
  },
584
649
  yoloExecution: refreshActions.length > 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.479",
3
+ "version": "0.1.481",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",