@sellable/mcp 0.1.497 → 0.1.499
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/dist/tools/refill-sends.js +97 -13
- package/package.json +1 -1
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { refreshPaidInmailCredits } from "./senders.js";
|
|
1
|
+
import { getApi, SellableApiError } from "../api.js";
|
|
3
2
|
import { startPrepareCampaignMessages } from "./campaign-message-preparation.js";
|
|
4
3
|
import { confirmLeadList, importLeads, searchSignals, selectPromisingPosts, } from "./leads.js";
|
|
5
4
|
import { markProviderPromptLoaded } from "./provider-preflight.js";
|
|
6
|
-
import {
|
|
5
|
+
import { getRefillTargetPlan } from "./refill-target-plan.js";
|
|
6
|
+
import { refreshPaidInmailCredits } from "./senders.js";
|
|
7
7
|
const DEFAULT_SCHEDULER_FORWARD_HOURS = 48;
|
|
8
8
|
const PAID_INMAIL_REFRESH_MAX_ATTEMPTS = 3;
|
|
9
9
|
const PAID_INMAIL_REFRESH_RETRY_DELAY_MS = Number(process.env.SELLABLE_MCP_PAID_REFRESH_RETRY_DELAY_MS ?? "1000");
|
|
10
|
+
const SIGNAL_DISCOVERY_MIN_REFILL_POSTS = 3;
|
|
11
|
+
const SIGNAL_DISCOVERY_MAX_REFILL_POSTS = 10;
|
|
12
|
+
const SIGNAL_DISCOVERY_TARGET_ROWS_PER_POST = 150;
|
|
10
13
|
function normalizeStrings(values) {
|
|
11
14
|
if (!Array.isArray(values))
|
|
12
15
|
return [];
|
|
@@ -66,6 +69,20 @@ function normalizeTargetDate(value) {
|
|
|
66
69
|
}
|
|
67
70
|
return trimmed;
|
|
68
71
|
}
|
|
72
|
+
function userAddedRowsLimitPayloadFromError(error) {
|
|
73
|
+
if (!(error instanceof SellableApiError) || error.status !== 400) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const parsed = JSON.parse(error.body);
|
|
78
|
+
if (parsed?.code !== "USER_ADDED_ROWS_LIMIT_EXCEEDED")
|
|
79
|
+
return null;
|
|
80
|
+
return parsed;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
69
86
|
export const refillSendsToolDefinitions = [
|
|
70
87
|
{
|
|
71
88
|
name: "refill_sends",
|
|
@@ -194,9 +211,7 @@ export function refillSendsCommand(input = {}) {
|
|
|
194
211
|
firstOperationalSteps: [
|
|
195
212
|
'Load get_subskill_prompt({ subskillName: "refill-sends-workflow" }) before any product operation.',
|
|
196
213
|
"A skill cannot create or invoke /goal by itself. If this refill is already running inside an active Codex goal, keep that goal open until every selected sender lane is horizon-filled by projected coverage (sent + scheduled), Christian explicitly stops/statuses the run, or a concrete non-scheduler blocker appears.",
|
|
197
|
-
`Call get_refill_target_plan({ intent: "${intent}"${input.campaignId ? `, campaignId: "${input.campaignId}"` : ""}${input.tableId ? `, tableId: "${input.tableId}"` : ""}${senderIds.length > 0
|
|
198
|
-
? `, senderIds: ${JSON.stringify(senderIds)}`
|
|
199
|
-
: ""}${senderNames.length > 0
|
|
214
|
+
`Call get_refill_target_plan({ intent: "${intent}"${input.campaignId ? `, campaignId: "${input.campaignId}"` : ""}${input.tableId ? `, tableId: "${input.tableId}"` : ""}${senderIds.length > 0 ? `, senderIds: ${JSON.stringify(senderIds)}` : ""}${senderNames.length > 0
|
|
200
215
|
? `, senderNames: ${JSON.stringify(senderNames)}`
|
|
201
216
|
: ""}${senders.length > 0 ? `, senders: ${JSON.stringify(senders)}` : ""}${targetDate
|
|
202
217
|
? `, targetDate: "${targetDate}"`
|
|
@@ -490,6 +505,9 @@ function postIdsFromSignalSearch(summary, maxPosts) {
|
|
|
490
505
|
: [];
|
|
491
506
|
return uniqueStrings([...recommendedPostIds, ...topPostIds]).slice(0, Math.max(1, maxPosts));
|
|
492
507
|
}
|
|
508
|
+
function maxSignalDiscoveryPostsForSourceLimit(sourceRowLimit) {
|
|
509
|
+
return Math.min(SIGNAL_DISCOVERY_MAX_REFILL_POSTS, Math.max(SIGNAL_DISCOVERY_MIN_REFILL_POSTS, Math.ceil(sourceRowLimit / SIGNAL_DISCOVERY_TARGET_ROWS_PER_POST)));
|
|
510
|
+
}
|
|
493
511
|
function refillPrepareRequestHash(params) {
|
|
494
512
|
return [
|
|
495
513
|
"refill_sends",
|
|
@@ -541,7 +559,7 @@ async function continueSignalDiscoverySource(action) {
|
|
|
541
559
|
numberValue(toolInput.targetRows) ??
|
|
542
560
|
numberValue(action.targetRows) ??
|
|
543
561
|
100)));
|
|
544
|
-
const maxPostsToScrape =
|
|
562
|
+
const maxPostsToScrape = maxSignalDiscoveryPostsForSourceLimit(sourceRowLimit);
|
|
545
563
|
if (!campaignOfferId || !sourceLeadListId || !sourceFingerprint) {
|
|
546
564
|
return {
|
|
547
565
|
status: "refused",
|
|
@@ -707,7 +725,9 @@ async function executeOneYoloPrimitive(action) {
|
|
|
707
725
|
const toolInput = actionToolInput(action);
|
|
708
726
|
const targetPreparedMessages = numberValue(toolInput.targetPreparedMessages);
|
|
709
727
|
const approvalMode = toolInput.approvalMode === "approve" ? "approve" : "mark_ready";
|
|
710
|
-
if (!campaignId ||
|
|
728
|
+
if (!campaignId ||
|
|
729
|
+
!targetPreparedMessages ||
|
|
730
|
+
targetPreparedMessages <= 0) {
|
|
711
731
|
return {
|
|
712
732
|
status: "refused",
|
|
713
733
|
refusalReason: "prepare_messages action is missing campaignId or bounded targetPreparedMessages",
|
|
@@ -747,21 +767,85 @@ async function executeOneYoloPrimitive(action) {
|
|
|
747
767
|
refusalReason: "copy_selected_source_rows action is missing campaignOfferId, sourceLeadListId, or sourceFingerprint",
|
|
748
768
|
};
|
|
749
769
|
}
|
|
750
|
-
if (sourceRowIds.length === 0 &&
|
|
770
|
+
if (sourceRowIds.length === 0 &&
|
|
771
|
+
(!sourceRowLimit || sourceRowLimit <= 0)) {
|
|
751
772
|
return {
|
|
752
773
|
status: "refused",
|
|
753
774
|
refusalReason: "copy_selected_source_rows action is missing exact sourceRowIds or a bounded sourceRowLimit",
|
|
754
775
|
};
|
|
755
776
|
}
|
|
756
|
-
const
|
|
777
|
+
const copyInput = {
|
|
757
778
|
campaignOfferId,
|
|
758
779
|
sourceLeadListId,
|
|
759
780
|
currentStep: null,
|
|
760
781
|
confirmed: true,
|
|
761
782
|
sourceRowIds: sourceRowIds.length > 0 ? sourceRowIds : undefined,
|
|
762
|
-
sourceRowLimit: sourceRowIds.length > 0 ? undefined : sourceRowLimit ?? undefined,
|
|
763
|
-
reviewBatchLimit: sourceRowIds.length > 0
|
|
764
|
-
|
|
783
|
+
sourceRowLimit: sourceRowIds.length > 0 ? undefined : (sourceRowLimit ?? undefined),
|
|
784
|
+
reviewBatchLimit: sourceRowIds.length > 0
|
|
785
|
+
? sourceRowIds.length
|
|
786
|
+
: (sourceRowLimit ?? undefined),
|
|
787
|
+
};
|
|
788
|
+
let result;
|
|
789
|
+
try {
|
|
790
|
+
result = await confirmLeadList(copyInput);
|
|
791
|
+
}
|
|
792
|
+
catch (error) {
|
|
793
|
+
const rowLimitPayload = userAddedRowsLimitPayloadFromError(error);
|
|
794
|
+
if (!rowLimitPayload)
|
|
795
|
+
throw error;
|
|
796
|
+
const remainingRows = typeof rowLimitPayload.remainingRows === "number" &&
|
|
797
|
+
Number.isFinite(rowLimitPayload.remainingRows)
|
|
798
|
+
? Math.floor(rowLimitPayload.remainingRows)
|
|
799
|
+
: 0;
|
|
800
|
+
if (remainingRows <= 0) {
|
|
801
|
+
return {
|
|
802
|
+
status: "refused",
|
|
803
|
+
refusalReason: rowLimitPayload.error ??
|
|
804
|
+
"selected campaign table is at the workflow row limit",
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
const retrySourceRowIds = sourceRowIds.length > 0 ? sourceRowIds.slice(0, remainingRows) : [];
|
|
808
|
+
const retrySourceRowLimit = retrySourceRowIds.length > 0
|
|
809
|
+
? undefined
|
|
810
|
+
: Math.min(sourceRowLimit ?? remainingRows, remainingRows);
|
|
811
|
+
const retryReviewBatchLimit = retrySourceRowIds.length > 0
|
|
812
|
+
? retrySourceRowIds.length
|
|
813
|
+
: retrySourceRowLimit;
|
|
814
|
+
if (!retryReviewBatchLimit || retryReviewBatchLimit <= 0) {
|
|
815
|
+
return {
|
|
816
|
+
status: "refused",
|
|
817
|
+
refusalReason: rowLimitPayload.error ??
|
|
818
|
+
"selected campaign table cannot accept more workflow rows",
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
const retryResult = await confirmLeadList({
|
|
822
|
+
...copyInput,
|
|
823
|
+
sourceRowIds: retrySourceRowIds.length > 0 ? retrySourceRowIds : undefined,
|
|
824
|
+
sourceRowLimit: retrySourceRowIds.length > 0 ? undefined : retrySourceRowLimit,
|
|
825
|
+
reviewBatchLimit: retryReviewBatchLimit,
|
|
826
|
+
});
|
|
827
|
+
result =
|
|
828
|
+
retryResult && typeof retryResult === "object"
|
|
829
|
+
? {
|
|
830
|
+
...retryResult,
|
|
831
|
+
rowLimitRetry: {
|
|
832
|
+
code: rowLimitPayload.code,
|
|
833
|
+
maxRows: rowLimitPayload.maxRows,
|
|
834
|
+
currentRows: rowLimitPayload.currentRows,
|
|
835
|
+
requestedRows: rowLimitPayload.requestedRows,
|
|
836
|
+
remainingRows,
|
|
837
|
+
retriedRows: retryReviewBatchLimit,
|
|
838
|
+
},
|
|
839
|
+
}
|
|
840
|
+
: {
|
|
841
|
+
result: retryResult,
|
|
842
|
+
rowLimitRetry: {
|
|
843
|
+
code: rowLimitPayload.code,
|
|
844
|
+
remainingRows,
|
|
845
|
+
retriedRows: retryReviewBatchLimit,
|
|
846
|
+
},
|
|
847
|
+
};
|
|
848
|
+
}
|
|
765
849
|
return { status: "executed_and_reread", result };
|
|
766
850
|
}
|
|
767
851
|
case "continue_signal_discovery_source":
|