@sellable/mcp 0.1.186 → 0.1.188
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/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/tools/auth.js +5 -5
- package/dist/tools/campaigns.js +32 -6
- package/dist/tools/leads.d.ts +28 -13
- package/dist/tools/leads.js +61 -22
- package/dist/tools/readiness.js +16 -11
- package/dist/tools/registry.d.ts +17 -0
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +33 -24
- package/skills/create-campaign-v2/SKILL.md +50 -69
- package/skills/create-campaign-v2/SOUL.md +12 -6
- package/skills/create-campaign-v2/core/flow.v2.json +1 -1
- package/skills/create-campaign-v2/references/step-13-import-leads.md +25 -5
- package/skills/create-campaign-v2/references/watch-link-handoff.md +23 -11
package/dist/index-dev.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/tools/auth.js
CHANGED
|
@@ -92,8 +92,8 @@ export async function getAuthStatus() {
|
|
|
92
92
|
const envLabel = config.activeEnvName || null;
|
|
93
93
|
const wsLabel = workspaceName || activeWorkspaceId;
|
|
94
94
|
const notice = envLabel
|
|
95
|
-
? `
|
|
96
|
-
: `
|
|
95
|
+
? `You're in ${wsLabel} (${envLabel}).`
|
|
96
|
+
: `You're in ${wsLabel}.`;
|
|
97
97
|
return {
|
|
98
98
|
ok: true,
|
|
99
99
|
configPath,
|
|
@@ -137,9 +137,9 @@ export async function getAuthStatus() {
|
|
|
137
137
|
" (If your team already uses Sellable, ask an admin to invite you into their shared workspace instead — that gets you straight in.)` " +
|
|
138
138
|
"5) Call `mcp__sellable__wait_for_cli_login({ sessionId })` using the sessionId returned by start_cli_login. " +
|
|
139
139
|
"6) If the result is `error.type === 'tool_timeout_guard'`, IMMEDIATELY re-call wait_for_cli_login with the SAME sessionId — do not narrate, do not call start_cli_login again. Loop until you get a different result. " +
|
|
140
|
-
"7) On `ok: true`, the user is signed in and `~/.sellable/config.json` has been written. Branch on `isReturningUser`: " +
|
|
141
|
-
"if true, say `You're in.\\n\\
|
|
142
|
-
"if false, say `You're set up.\\n\\
|
|
140
|
+
"7) On `ok: true`, the user is signed in and `~/.sellable/config.json` has been written. Branch on `isReturningUser` and use `activeWorkspaceName` when present, otherwise `activeWorkspaceId`, as `{workspaceLabel}`: " +
|
|
141
|
+
"if true, say `You're in {workspaceLabel}.\\n\\nExcited to help you launch your LinkedIn outbound campaign. We're at setup: first I'll use your LinkedIn profile to understand the company, then I'll draft the campaign brief, help choose where to find buyers, review messages, and wait for final launch approval.\\n\\nWhat's your LinkedIn profile URL or handle?`; " +
|
|
142
|
+
"if false, say `You're set up in {workspaceLabel}.\\n\\nExcited to help you launch your LinkedIn outbound campaign. We're at setup: first I'll use your LinkedIn profile to understand the company, then I'll draft the campaign brief, help choose where to find buyers, review messages, and wait for final launch approval.\\n\\nWhat's your LinkedIn profile URL or handle?`";
|
|
143
143
|
if (error instanceof SellableApiError && error.isAuthError) {
|
|
144
144
|
return {
|
|
145
145
|
...base,
|
package/dist/tools/campaigns.js
CHANGED
|
@@ -40,6 +40,26 @@ export function getCampaignBuilderWatchModeParam() {
|
|
|
40
40
|
function buildCampaignBuilderWatchPath(campaignId) {
|
|
41
41
|
return `/campaign-builder/${campaignId}?mode=${getCampaignBuilderWatchModeParam()}`;
|
|
42
42
|
}
|
|
43
|
+
function isValidBriefHandoffWatchUrl(watchUrl, campaignId) {
|
|
44
|
+
try {
|
|
45
|
+
const url = new URL(watchUrl);
|
|
46
|
+
const mode = url.searchParams.get("mode");
|
|
47
|
+
return (url.pathname === `/campaign-builder/${campaignId}` &&
|
|
48
|
+
(mode === "claude" || mode === "codex") &&
|
|
49
|
+
Boolean(url.searchParams.get("workspaceId")) &&
|
|
50
|
+
Boolean(url.searchParams.get("token")));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function assertBriefHandoffWatchUrl(watchUrl, campaignId) {
|
|
57
|
+
if (isValidBriefHandoffWatchUrl(watchUrl, campaignId))
|
|
58
|
+
return;
|
|
59
|
+
throw new Error("create_campaign produced an invalid watchUrl for the brief approval handoff. " +
|
|
60
|
+
"Recover a fresh direct /campaign-builder/{campaignId}?mode={claude|codex}&workspaceId=...&token=... URL " +
|
|
61
|
+
"with create_campaign({ campaignId }) or get_campaign before asking for approval.");
|
|
62
|
+
}
|
|
43
63
|
export const campaignToolDefinitions = [
|
|
44
64
|
{
|
|
45
65
|
name: "get_campaigns",
|
|
@@ -648,22 +668,28 @@ function deriveOfferValue(name, briefContent) {
|
|
|
648
668
|
return heading.slice(0, 120);
|
|
649
669
|
return lines[0].slice(0, 120);
|
|
650
670
|
}
|
|
651
|
-
function buildBriefApprovalGate(watchUrl) {
|
|
671
|
+
function buildBriefApprovalGate(campaignId, watchUrl) {
|
|
672
|
+
assertBriefHandoffWatchUrl(watchUrl, campaignId);
|
|
652
673
|
return {
|
|
653
674
|
approvalGate: {
|
|
654
675
|
kind: "brief-review",
|
|
655
676
|
mustShowBeforeQuestion: [
|
|
656
|
-
"the full campaignBrief markdown the user is approving",
|
|
657
|
-
`
|
|
677
|
+
"the full campaignBrief markdown the user is approving, shown exactly once",
|
|
678
|
+
`the exact create_campaign.watchUrl value, shown exactly once: ${watchUrl}`,
|
|
658
679
|
],
|
|
659
680
|
questionToolBlockedUntilShown: true,
|
|
660
681
|
},
|
|
661
|
-
nextStep: "Before asking for approval,
|
|
682
|
+
nextStep: "Before asking for approval, make sure the user has seen the full campaign brief exactly once in normal chat text. " +
|
|
683
|
+
"If you already rendered the brief immediately before this tool call, do not render it again. " +
|
|
684
|
+
"Then print exactly one watch-link handoff using this exact create_campaign.watchUrl value. " +
|
|
685
|
+
"Do not derive, shorten, reconstruct, or print any bare /campaign-builder/{campaignId} URL. " +
|
|
686
|
+
"Print this handoff exactly in normal chat text: " +
|
|
662
687
|
`"Campaign shell is ready. We'll keep building the campaign in this chat.\n` +
|
|
663
688
|
`You can watch it being built in real time in the app here:\n\n` +
|
|
664
689
|
`Watch link: ${watchUrl}\n\n` +
|
|
665
690
|
`Send changes here. I'll ask for your approval whenever I need your expertise or taste before moving forward." ` +
|
|
666
|
-
"Do not
|
|
691
|
+
"Do not print another Watch link during source/provider selection. " +
|
|
692
|
+
"Do not call AskUserQuestion or request_user_input until the user has seen both the brief content and this exact watch-link handoff.",
|
|
667
693
|
};
|
|
668
694
|
}
|
|
669
695
|
function buildResumeNextStep() {
|
|
@@ -804,7 +830,7 @@ export async function createCampaign(input) {
|
|
|
804
830
|
createdAt: result.createdAt,
|
|
805
831
|
currentStep: result.currentStep,
|
|
806
832
|
watchUrl,
|
|
807
|
-
...buildBriefApprovalGate(watchUrl),
|
|
833
|
+
...buildBriefApprovalGate(result.id, watchUrl),
|
|
808
834
|
};
|
|
809
835
|
}
|
|
810
836
|
export async function updateCampaign(campaignId, input) {
|
package/dist/tools/leads.d.ts
CHANGED
|
@@ -146,6 +146,7 @@ export type ConfirmLeadListInput = {
|
|
|
146
146
|
keepInSync?: boolean;
|
|
147
147
|
jobId?: string;
|
|
148
148
|
reviewBatchLimit?: number;
|
|
149
|
+
allowPartialSourceList?: boolean;
|
|
149
150
|
/**
|
|
150
151
|
* Deprecated alias for reviewBatchLimit. Confirming a lead list now copies the
|
|
151
152
|
* confirmed source into the campaign table; this value no longer caps clone
|
|
@@ -244,6 +245,7 @@ export declare const leadToolDefinitions: ({
|
|
|
244
245
|
keepInSync?: undefined;
|
|
245
246
|
jobId?: undefined;
|
|
246
247
|
reviewBatchLimit?: undefined;
|
|
248
|
+
allowPartialSourceList?: undefined;
|
|
247
249
|
selections?: undefined;
|
|
248
250
|
selectionMode?: undefined;
|
|
249
251
|
};
|
|
@@ -420,6 +422,7 @@ export declare const leadToolDefinitions: ({
|
|
|
420
422
|
keepInSync?: undefined;
|
|
421
423
|
jobId?: undefined;
|
|
422
424
|
reviewBatchLimit?: undefined;
|
|
425
|
+
allowPartialSourceList?: undefined;
|
|
423
426
|
selections?: undefined;
|
|
424
427
|
selectionMode?: undefined;
|
|
425
428
|
};
|
|
@@ -495,6 +498,7 @@ export declare const leadToolDefinitions: ({
|
|
|
495
498
|
keepInSync?: undefined;
|
|
496
499
|
jobId?: undefined;
|
|
497
500
|
reviewBatchLimit?: undefined;
|
|
501
|
+
allowPartialSourceList?: undefined;
|
|
498
502
|
selections?: undefined;
|
|
499
503
|
selectionMode?: undefined;
|
|
500
504
|
};
|
|
@@ -642,6 +646,7 @@ export declare const leadToolDefinitions: ({
|
|
|
642
646
|
keepInSync?: undefined;
|
|
643
647
|
jobId?: undefined;
|
|
644
648
|
reviewBatchLimit?: undefined;
|
|
649
|
+
allowPartialSourceList?: undefined;
|
|
645
650
|
selections?: undefined;
|
|
646
651
|
selectionMode?: undefined;
|
|
647
652
|
};
|
|
@@ -731,6 +736,7 @@ export declare const leadToolDefinitions: ({
|
|
|
731
736
|
keepInSync?: undefined;
|
|
732
737
|
jobId?: undefined;
|
|
733
738
|
reviewBatchLimit?: undefined;
|
|
739
|
+
allowPartialSourceList?: undefined;
|
|
734
740
|
selections?: undefined;
|
|
735
741
|
selectionMode?: undefined;
|
|
736
742
|
};
|
|
@@ -829,6 +835,7 @@ export declare const leadToolDefinitions: ({
|
|
|
829
835
|
keepInSync?: undefined;
|
|
830
836
|
jobId?: undefined;
|
|
831
837
|
reviewBatchLimit?: undefined;
|
|
838
|
+
allowPartialSourceList?: undefined;
|
|
832
839
|
selections?: undefined;
|
|
833
840
|
selectionMode?: undefined;
|
|
834
841
|
};
|
|
@@ -909,6 +916,7 @@ export declare const leadToolDefinitions: ({
|
|
|
909
916
|
keepInSync?: undefined;
|
|
910
917
|
jobId?: undefined;
|
|
911
918
|
reviewBatchLimit?: undefined;
|
|
919
|
+
allowPartialSourceList?: undefined;
|
|
912
920
|
selections?: undefined;
|
|
913
921
|
selectionMode?: undefined;
|
|
914
922
|
};
|
|
@@ -1528,6 +1536,7 @@ export declare const leadToolDefinitions: ({
|
|
|
1528
1536
|
keepInSync?: undefined;
|
|
1529
1537
|
jobId?: undefined;
|
|
1530
1538
|
reviewBatchLimit?: undefined;
|
|
1539
|
+
allowPartialSourceList?: undefined;
|
|
1531
1540
|
selections?: undefined;
|
|
1532
1541
|
selectionMode?: undefined;
|
|
1533
1542
|
};
|
|
@@ -1660,6 +1669,7 @@ export declare const leadToolDefinitions: ({
|
|
|
1660
1669
|
keepInSync?: undefined;
|
|
1661
1670
|
jobId?: undefined;
|
|
1662
1671
|
reviewBatchLimit?: undefined;
|
|
1672
|
+
allowPartialSourceList?: undefined;
|
|
1663
1673
|
selections?: undefined;
|
|
1664
1674
|
selectionMode?: undefined;
|
|
1665
1675
|
};
|
|
@@ -1780,6 +1790,7 @@ export declare const leadToolDefinitions: ({
|
|
|
1780
1790
|
keepInSync?: undefined;
|
|
1781
1791
|
jobId?: undefined;
|
|
1782
1792
|
reviewBatchLimit?: undefined;
|
|
1793
|
+
allowPartialSourceList?: undefined;
|
|
1783
1794
|
selections?: undefined;
|
|
1784
1795
|
selectionMode?: undefined;
|
|
1785
1796
|
};
|
|
@@ -1858,6 +1869,7 @@ export declare const leadToolDefinitions: ({
|
|
|
1858
1869
|
keepInSync?: undefined;
|
|
1859
1870
|
jobId?: undefined;
|
|
1860
1871
|
reviewBatchLimit?: undefined;
|
|
1872
|
+
allowPartialSourceList?: undefined;
|
|
1861
1873
|
selections?: undefined;
|
|
1862
1874
|
selectionMode?: undefined;
|
|
1863
1875
|
};
|
|
@@ -1901,6 +1913,10 @@ export declare const leadToolDefinitions: ({
|
|
|
1901
1913
|
type: string;
|
|
1902
1914
|
description: string;
|
|
1903
1915
|
};
|
|
1916
|
+
allowPartialSourceList: {
|
|
1917
|
+
type: string;
|
|
1918
|
+
description: string;
|
|
1919
|
+
};
|
|
1904
1920
|
confirmed: {
|
|
1905
1921
|
type: string;
|
|
1906
1922
|
description: string;
|
|
@@ -2066,6 +2082,7 @@ export declare const leadToolDefinitions: ({
|
|
|
2066
2082
|
keepInSync?: undefined;
|
|
2067
2083
|
jobId?: undefined;
|
|
2068
2084
|
reviewBatchLimit?: undefined;
|
|
2085
|
+
allowPartialSourceList?: undefined;
|
|
2069
2086
|
};
|
|
2070
2087
|
required: string[];
|
|
2071
2088
|
};
|
|
@@ -2146,6 +2163,7 @@ export declare const leadToolDefinitions: ({
|
|
|
2146
2163
|
keepInSync?: undefined;
|
|
2147
2164
|
jobId?: undefined;
|
|
2148
2165
|
reviewBatchLimit?: undefined;
|
|
2166
|
+
allowPartialSourceList?: undefined;
|
|
2149
2167
|
selections?: undefined;
|
|
2150
2168
|
selectionMode?: undefined;
|
|
2151
2169
|
};
|
|
@@ -2388,25 +2406,14 @@ export declare function importLeads(input: ImportLeadsInput): Promise<{
|
|
|
2388
2406
|
existingLeadListId: string;
|
|
2389
2407
|
reusedExistingSourceList: boolean;
|
|
2390
2408
|
message: string;
|
|
2391
|
-
suggestedToolCalls:
|
|
2409
|
+
suggestedToolCalls: {
|
|
2392
2410
|
tool: string;
|
|
2393
2411
|
args: {
|
|
2394
2412
|
campaignOfferId: string;
|
|
2395
2413
|
leadListId: string;
|
|
2396
2414
|
provider: string;
|
|
2397
|
-
sourceLeadListId?: undefined;
|
|
2398
|
-
confirmed?: undefined;
|
|
2399
2415
|
};
|
|
2400
|
-
}
|
|
2401
|
-
tool: string;
|
|
2402
|
-
args: {
|
|
2403
|
-
campaignOfferId: string;
|
|
2404
|
-
sourceLeadListId: string;
|
|
2405
|
-
confirmed: boolean;
|
|
2406
|
-
leadListId?: undefined;
|
|
2407
|
-
provider?: undefined;
|
|
2408
|
-
};
|
|
2409
|
-
})[];
|
|
2416
|
+
}[];
|
|
2410
2417
|
error?: undefined;
|
|
2411
2418
|
needsModeSelection?: undefined;
|
|
2412
2419
|
modeOptions?: undefined;
|
|
@@ -2648,6 +2655,14 @@ export declare function confirmLeadList(input: ConfirmLeadListInput): Promise<{
|
|
|
2648
2655
|
copyStillRunning: boolean;
|
|
2649
2656
|
trimmedOverflowRowCount: number;
|
|
2650
2657
|
sourceShortfall: boolean;
|
|
2658
|
+
partialSourceListAccepted: boolean;
|
|
2659
|
+
};
|
|
2660
|
+
sourceListSnapshot: {
|
|
2661
|
+
partial: boolean;
|
|
2662
|
+
sourceRowCountAtConfirmation: number;
|
|
2663
|
+
targetLeadCount: number | null;
|
|
2664
|
+
importStatus: string | null;
|
|
2665
|
+
warning: string | null;
|
|
2651
2666
|
};
|
|
2652
2667
|
message: string;
|
|
2653
2668
|
}>;
|
package/dist/tools/leads.js
CHANGED
|
@@ -1510,6 +1510,10 @@ export const leadToolDefinitions = [
|
|
|
1510
1510
|
type: "number",
|
|
1511
1511
|
description: "Number of campaign rows to use as the initial review/process sample. Defaults to 15.",
|
|
1512
1512
|
},
|
|
1513
|
+
allowPartialSourceList: {
|
|
1514
|
+
type: "boolean",
|
|
1515
|
+
description: "Explicit override for user-approved early continuation. Default false. When true, confirm_lead_list may copy the currently materialized rows from a still-running source import; use only after the user explicitly asks to keep going with the partial list.",
|
|
1516
|
+
},
|
|
1513
1517
|
confirmed: {
|
|
1514
1518
|
type: "boolean",
|
|
1515
1519
|
description: "Set true after user approval when interaction mode requires confirmation for confirm/import.",
|
|
@@ -2398,7 +2402,7 @@ export async function importLeads(input) {
|
|
|
2398
2402
|
leadListId: campaignSelectedLeadListId,
|
|
2399
2403
|
existingLeadListId: campaignSelectedLeadListId,
|
|
2400
2404
|
reusedExistingSourceList: true,
|
|
2401
|
-
message: "A Signal Discovery source list already exists for the approved selected-post scrape. Reuse it and continue with wait_for_lead_list_ready
|
|
2405
|
+
message: "A Signal Discovery source list already exists for the approved selected-post scrape. Reuse it and continue with wait_for_lead_list_ready before confirm_lead_list; do not ask add/replace and do not rescrape unless the user approves a different selected-post scrape.",
|
|
2402
2406
|
suggestedToolCalls: [
|
|
2403
2407
|
{
|
|
2404
2408
|
tool: "wait_for_lead_list_ready",
|
|
@@ -2408,14 +2412,6 @@ export async function importLeads(input) {
|
|
|
2408
2412
|
provider: "signal-discovery",
|
|
2409
2413
|
},
|
|
2410
2414
|
},
|
|
2411
|
-
{
|
|
2412
|
-
tool: "confirm_lead_list",
|
|
2413
|
-
args: {
|
|
2414
|
-
campaignOfferId,
|
|
2415
|
-
sourceLeadListId: campaignSelectedLeadListId,
|
|
2416
|
-
confirmed: true,
|
|
2417
|
-
},
|
|
2418
|
-
},
|
|
2419
2415
|
],
|
|
2420
2416
|
};
|
|
2421
2417
|
}
|
|
@@ -2585,7 +2581,7 @@ export async function importLeads(input) {
|
|
|
2585
2581
|
targetLeadCount: cappedTargetLeadCount ?? null,
|
|
2586
2582
|
message: `Started scraping ${postsToScrape.length} posts (~${result.estimatedEngagers} people to check). Leads will appear as scraping completes.${importSelection.limited
|
|
2587
2583
|
? ` Limited from ${uniqueSelectedPosts.length} selected posts by the approved source-capacity scrape plan.`
|
|
2588
|
-
: ""} The watched campaign has been moved to confirm-lead-list with import progress copy;
|
|
2584
|
+
: ""} The watched campaign has been moved to confirm-lead-list with import progress copy. Keep calling wait_for_lead_list_ready until it reports ready, failed, or cancelled before confirm_lead_list; only confirm a partial list with allowPartialSourceList after the user explicitly asks to keep going early. Do not call update_campaign to fix that step.`,
|
|
2589
2585
|
};
|
|
2590
2586
|
}
|
|
2591
2587
|
// === SALES NAV / PROSPEO FLOW ===
|
|
@@ -2698,7 +2694,7 @@ export async function importLeads(input) {
|
|
|
2698
2694
|
jobResult,
|
|
2699
2695
|
jobId,
|
|
2700
2696
|
targetLeadCount: cappedTargetLeadCount ?? null,
|
|
2701
|
-
message: "Import started and the watched campaign has been moved to confirm-lead-list with import progress copy.
|
|
2697
|
+
message: "Import started and the watched campaign has been moved to confirm-lead-list with import progress copy. Wait until wait_for_lead_list_ready reports the source import is complete before calling confirm_lead_list. If the user explicitly asks to keep going early, call confirm_lead_list with allowPartialSourceList: true; otherwise keep polling, stop on failure/cancellation, and do not call update_campaign to fix the import step.",
|
|
2702
2698
|
};
|
|
2703
2699
|
}
|
|
2704
2700
|
export async function cancelLeadImport(input) {
|
|
@@ -2745,7 +2741,7 @@ export async function cancelLeadImport(input) {
|
|
|
2745
2741
|
}
|
|
2746
2742
|
export async function confirmLeadList(input) {
|
|
2747
2743
|
const api = getApi();
|
|
2748
|
-
const { campaignOfferId, currentStep, confirmed, sourceLeadListId, campaignName, keepInSync, jobId, reviewBatchLimit, targetLeadCount, } = input;
|
|
2744
|
+
const { campaignOfferId, currentStep, confirmed, sourceLeadListId, campaignName, keepInSync, jobId, reviewBatchLimit, allowPartialSourceList, targetLeadCount, } = input;
|
|
2749
2745
|
assertInteractionApproval({
|
|
2750
2746
|
campaignId: campaignOfferId,
|
|
2751
2747
|
action: "confirm-lead-list",
|
|
@@ -2859,26 +2855,61 @@ export async function confirmLeadList(input) {
|
|
|
2859
2855
|
intervalMs: 1000,
|
|
2860
2856
|
});
|
|
2861
2857
|
}
|
|
2858
|
+
let partialSourceListAccepted = false;
|
|
2859
|
+
let partialSourceListWarning = null;
|
|
2862
2860
|
if (!readiness.ready) {
|
|
2863
|
-
if (
|
|
2861
|
+
if (allowPartialSourceList === true &&
|
|
2862
|
+
readiness.reason === "import_still_running" &&
|
|
2863
|
+
leadListRowCount > 0) {
|
|
2864
|
+
partialSourceListAccepted = true;
|
|
2865
|
+
partialSourceListWarning =
|
|
2866
|
+
"User explicitly asked to continue before the source import completed. This campaign table is based on the currently materialized source-list rows only.";
|
|
2867
|
+
readiness = {
|
|
2868
|
+
ready: true,
|
|
2869
|
+
leadListId: resolvedLeadListId,
|
|
2870
|
+
provider: resolvedProvider ?? null,
|
|
2871
|
+
attempts: typeof readiness.attempts === "number" ? readiness.attempts : 1,
|
|
2872
|
+
elapsedMs: typeof readiness.elapsedMs === "number" ? readiness.elapsedMs : 0,
|
|
2873
|
+
rowCount: leadListRowCount,
|
|
2874
|
+
status: typeof readiness.status === "string"
|
|
2875
|
+
? readiness.status
|
|
2876
|
+
: leadListConfig?.importStatus ?? null,
|
|
2877
|
+
targetLeadCount: typeof readiness.targetLeadCount === "number"
|
|
2878
|
+
? readiness.targetLeadCount
|
|
2879
|
+
: typeof leadListConfig?.targetLeadCount === "number"
|
|
2880
|
+
? leadListConfig.targetLeadCount
|
|
2881
|
+
: null,
|
|
2882
|
+
partialSourceListAccepted: true,
|
|
2883
|
+
};
|
|
2884
|
+
}
|
|
2885
|
+
else if (readiness.reason === "missing_job_id") {
|
|
2864
2886
|
const recoveryNarration = buildSourceImportRecoveryWatchNarration({
|
|
2865
2887
|
reason: "pending",
|
|
2866
2888
|
provider: resolvedProvider,
|
|
2867
2889
|
});
|
|
2868
2890
|
throw new Error(`${recoveryNarration.headline}: Import job ID is missing. Keep the campaign at confirm-lead-list; provide the jobId, retry readiness, cancel the import, or re-run-source before confirming. ${recoveryNarration.safety}`);
|
|
2869
2891
|
}
|
|
2870
|
-
if (readiness.reason === "
|
|
2892
|
+
else if (readiness.reason === "cancelled") {
|
|
2893
|
+
const recoveryNarration = buildSourceImportRecoveryWatchNarration({
|
|
2894
|
+
reason: "failed",
|
|
2895
|
+
provider: resolvedProvider,
|
|
2896
|
+
});
|
|
2897
|
+
throw new Error(`${recoveryNarration.headline}: Import was cancelled. Keep the campaign at confirm-lead-list; do not copy partial rows unless the user explicitly asks to continue from the partial list. ${recoveryNarration.safety}`);
|
|
2898
|
+
}
|
|
2899
|
+
else if (readiness.reason === "import_failed") {
|
|
2871
2900
|
const recoveryNarration = buildSourceImportRecoveryWatchNarration({
|
|
2872
2901
|
reason: "failed",
|
|
2873
2902
|
provider: resolvedProvider,
|
|
2874
2903
|
});
|
|
2875
2904
|
throw new Error(`${recoveryNarration.headline}: Import failed. Keep the campaign at confirm-lead-list; retry the provider import, cancel it, or re-run-source before confirming. ${recoveryNarration.safety}`);
|
|
2876
2905
|
}
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2906
|
+
else {
|
|
2907
|
+
const recoveryNarration = buildSourceImportRecoveryWatchNarration({
|
|
2908
|
+
reason: "timeout",
|
|
2909
|
+
provider: resolvedProvider,
|
|
2910
|
+
});
|
|
2911
|
+
throw new Error(`${recoveryNarration.headline}: Import still in progress. Keep the campaign at confirm-lead-list; retry readiness, cancel the import, or re-run-source before launching post-import scouts. ${recoveryNarration.safety}`);
|
|
2912
|
+
}
|
|
2882
2913
|
}
|
|
2883
2914
|
const isTerminalAccessError = (error) => error instanceof SellableApiError && [401, 403, 404].includes(error.status);
|
|
2884
2915
|
const formatTerminalAccessError = (error) => {
|
|
@@ -3022,12 +3053,20 @@ export async function confirmLeadList(input) {
|
|
|
3022
3053
|
sourceShortfall: signalSourceTargetLeadCount !== null &&
|
|
3023
3054
|
leadListRowCount > 0 &&
|
|
3024
3055
|
leadListRowCount < signalSourceTargetLeadCount,
|
|
3056
|
+
partialSourceListAccepted,
|
|
3057
|
+
},
|
|
3058
|
+
sourceListSnapshot: {
|
|
3059
|
+
partial: partialSourceListAccepted,
|
|
3060
|
+
sourceRowCountAtConfirmation: leadListRowCount,
|
|
3061
|
+
targetLeadCount: readiness.targetLeadCount ?? null,
|
|
3062
|
+
importStatus: readiness.status ?? null,
|
|
3063
|
+
warning: partialSourceListWarning,
|
|
3025
3064
|
},
|
|
3026
3065
|
message: copyStillRunning
|
|
3027
|
-
?
|
|
3066
|
+
? `${partialSourceListAccepted ? "Using the user-approved partial source snapshot. " : ""}First ${importedRowCount.toLocaleString("en-US")} source candidate${importedRowCount === 1 ? "" : "s"} are copied into the campaign table and the rest of the confirmed source list is still copying. Use the first ${keptReviewRowCount.toLocaleString("en-US")} as the review/process sample. The watched campaign is now on filter-choice; ask add filters vs skip filters before loading post-lead workers.`
|
|
3028
3067
|
: importedRowCount > keptReviewRowCount
|
|
3029
|
-
?
|
|
3030
|
-
:
|
|
3068
|
+
? `${partialSourceListAccepted ? "Using the user-approved partial source snapshot. " : ""}Copied ${importedRowCount.toLocaleString("en-US")} source candidate${importedRowCount === 1 ? "" : "s"} into the campaign table. Use the first ${keptReviewRowCount.toLocaleString("en-US")} as the review/process sample. The watched campaign is now on filter-choice; ask add filters vs skip filters before loading post-lead workers.`
|
|
3069
|
+
: `${partialSourceListAccepted ? "Using the user-approved partial source snapshot. " : ""}Copied ${importedRowCount.toLocaleString("en-US")} source candidate${importedRowCount === 1 ? "" : "s"} into the campaign table for the review/process sample. The watched campaign is now on filter-choice; ask add filters vs skip filters before loading post-lead workers.`,
|
|
3031
3070
|
};
|
|
3032
3071
|
}
|
|
3033
3072
|
export function getProviderPrompt(input) {
|
package/dist/tools/readiness.js
CHANGED
|
@@ -500,15 +500,18 @@ export async function waitForLeadListReady(input) {
|
|
|
500
500
|
await sleep(intervalMs);
|
|
501
501
|
}
|
|
502
502
|
const timedOutWithRows = (lastRowCount ?? 0) > 0;
|
|
503
|
+
const stillRunningWithRows = requireComplete && timedOutWithRows;
|
|
503
504
|
const timeoutReason = missingJobId
|
|
504
505
|
? "missing_job_id"
|
|
505
|
-
:
|
|
506
|
-
? "
|
|
507
|
-
:
|
|
508
|
-
? "
|
|
509
|
-
:
|
|
506
|
+
: stillRunningWithRows
|
|
507
|
+
? "import_still_running"
|
|
508
|
+
: timedOutWithRows
|
|
509
|
+
? "timeout_with_rows"
|
|
510
|
+
: guardApplied
|
|
511
|
+
? "tool_timeout_guard"
|
|
512
|
+
: "timeout";
|
|
510
513
|
return {
|
|
511
|
-
ready: !missingJobId && timedOutWithRows,
|
|
514
|
+
ready: !requireComplete && !missingJobId && timedOutWithRows,
|
|
512
515
|
reason: timeoutReason,
|
|
513
516
|
leadListId,
|
|
514
517
|
provider: provider ?? null,
|
|
@@ -517,11 +520,13 @@ export async function waitForLeadListReady(input) {
|
|
|
517
520
|
rowCount: lastRowCount,
|
|
518
521
|
status: lastStatus ?? undefined,
|
|
519
522
|
targetLeadCount: targetLeadCount ?? undefined,
|
|
520
|
-
warning:
|
|
521
|
-
? "
|
|
522
|
-
:
|
|
523
|
-
?
|
|
524
|
-
:
|
|
523
|
+
warning: stillRunningWithRows
|
|
524
|
+
? `Import still appears to be running with ${lastRowCount?.toLocaleString("en-US") ?? "some"} row(s) available. Re-run wait_for_lead_list_ready to keep polling, or only call confirm_lead_list with allowPartialSourceList after the user explicitly asks to continue early.`
|
|
525
|
+
: !missingJobId && timedOutWithRows
|
|
526
|
+
? "Timed out waiting for import status, but rows exist."
|
|
527
|
+
: guardApplied
|
|
528
|
+
? `Stopped after ${effectiveTimeoutMs}ms to avoid host tool timeout (requested ${requestedTimeoutMs}ms). Re-run wait_for_lead_list_ready to keep polling.`
|
|
529
|
+
: undefined,
|
|
525
530
|
error: lastError ?? undefined,
|
|
526
531
|
};
|
|
527
532
|
}
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -1392,6 +1392,7 @@ export declare const allTools: ({
|
|
|
1392
1392
|
keepInSync?: undefined;
|
|
1393
1393
|
jobId?: undefined;
|
|
1394
1394
|
reviewBatchLimit?: undefined;
|
|
1395
|
+
allowPartialSourceList?: undefined;
|
|
1395
1396
|
selections?: undefined;
|
|
1396
1397
|
selectionMode?: undefined;
|
|
1397
1398
|
};
|
|
@@ -1568,6 +1569,7 @@ export declare const allTools: ({
|
|
|
1568
1569
|
keepInSync?: undefined;
|
|
1569
1570
|
jobId?: undefined;
|
|
1570
1571
|
reviewBatchLimit?: undefined;
|
|
1572
|
+
allowPartialSourceList?: undefined;
|
|
1571
1573
|
selections?: undefined;
|
|
1572
1574
|
selectionMode?: undefined;
|
|
1573
1575
|
};
|
|
@@ -1643,6 +1645,7 @@ export declare const allTools: ({
|
|
|
1643
1645
|
keepInSync?: undefined;
|
|
1644
1646
|
jobId?: undefined;
|
|
1645
1647
|
reviewBatchLimit?: undefined;
|
|
1648
|
+
allowPartialSourceList?: undefined;
|
|
1646
1649
|
selections?: undefined;
|
|
1647
1650
|
selectionMode?: undefined;
|
|
1648
1651
|
};
|
|
@@ -1790,6 +1793,7 @@ export declare const allTools: ({
|
|
|
1790
1793
|
keepInSync?: undefined;
|
|
1791
1794
|
jobId?: undefined;
|
|
1792
1795
|
reviewBatchLimit?: undefined;
|
|
1796
|
+
allowPartialSourceList?: undefined;
|
|
1793
1797
|
selections?: undefined;
|
|
1794
1798
|
selectionMode?: undefined;
|
|
1795
1799
|
};
|
|
@@ -1879,6 +1883,7 @@ export declare const allTools: ({
|
|
|
1879
1883
|
keepInSync?: undefined;
|
|
1880
1884
|
jobId?: undefined;
|
|
1881
1885
|
reviewBatchLimit?: undefined;
|
|
1886
|
+
allowPartialSourceList?: undefined;
|
|
1882
1887
|
selections?: undefined;
|
|
1883
1888
|
selectionMode?: undefined;
|
|
1884
1889
|
};
|
|
@@ -1977,6 +1982,7 @@ export declare const allTools: ({
|
|
|
1977
1982
|
keepInSync?: undefined;
|
|
1978
1983
|
jobId?: undefined;
|
|
1979
1984
|
reviewBatchLimit?: undefined;
|
|
1985
|
+
allowPartialSourceList?: undefined;
|
|
1980
1986
|
selections?: undefined;
|
|
1981
1987
|
selectionMode?: undefined;
|
|
1982
1988
|
};
|
|
@@ -2057,6 +2063,7 @@ export declare const allTools: ({
|
|
|
2057
2063
|
keepInSync?: undefined;
|
|
2058
2064
|
jobId?: undefined;
|
|
2059
2065
|
reviewBatchLimit?: undefined;
|
|
2066
|
+
allowPartialSourceList?: undefined;
|
|
2060
2067
|
selections?: undefined;
|
|
2061
2068
|
selectionMode?: undefined;
|
|
2062
2069
|
};
|
|
@@ -2676,6 +2683,7 @@ export declare const allTools: ({
|
|
|
2676
2683
|
keepInSync?: undefined;
|
|
2677
2684
|
jobId?: undefined;
|
|
2678
2685
|
reviewBatchLimit?: undefined;
|
|
2686
|
+
allowPartialSourceList?: undefined;
|
|
2679
2687
|
selections?: undefined;
|
|
2680
2688
|
selectionMode?: undefined;
|
|
2681
2689
|
};
|
|
@@ -2808,6 +2816,7 @@ export declare const allTools: ({
|
|
|
2808
2816
|
keepInSync?: undefined;
|
|
2809
2817
|
jobId?: undefined;
|
|
2810
2818
|
reviewBatchLimit?: undefined;
|
|
2819
|
+
allowPartialSourceList?: undefined;
|
|
2811
2820
|
selections?: undefined;
|
|
2812
2821
|
selectionMode?: undefined;
|
|
2813
2822
|
};
|
|
@@ -2928,6 +2937,7 @@ export declare const allTools: ({
|
|
|
2928
2937
|
keepInSync?: undefined;
|
|
2929
2938
|
jobId?: undefined;
|
|
2930
2939
|
reviewBatchLimit?: undefined;
|
|
2940
|
+
allowPartialSourceList?: undefined;
|
|
2931
2941
|
selections?: undefined;
|
|
2932
2942
|
selectionMode?: undefined;
|
|
2933
2943
|
};
|
|
@@ -3006,6 +3016,7 @@ export declare const allTools: ({
|
|
|
3006
3016
|
keepInSync?: undefined;
|
|
3007
3017
|
jobId?: undefined;
|
|
3008
3018
|
reviewBatchLimit?: undefined;
|
|
3019
|
+
allowPartialSourceList?: undefined;
|
|
3009
3020
|
selections?: undefined;
|
|
3010
3021
|
selectionMode?: undefined;
|
|
3011
3022
|
};
|
|
@@ -3049,6 +3060,10 @@ export declare const allTools: ({
|
|
|
3049
3060
|
type: string;
|
|
3050
3061
|
description: string;
|
|
3051
3062
|
};
|
|
3063
|
+
allowPartialSourceList: {
|
|
3064
|
+
type: string;
|
|
3065
|
+
description: string;
|
|
3066
|
+
};
|
|
3052
3067
|
confirmed: {
|
|
3053
3068
|
type: string;
|
|
3054
3069
|
description: string;
|
|
@@ -3214,6 +3229,7 @@ export declare const allTools: ({
|
|
|
3214
3229
|
keepInSync?: undefined;
|
|
3215
3230
|
jobId?: undefined;
|
|
3216
3231
|
reviewBatchLimit?: undefined;
|
|
3232
|
+
allowPartialSourceList?: undefined;
|
|
3217
3233
|
};
|
|
3218
3234
|
required: string[];
|
|
3219
3235
|
};
|
|
@@ -3294,6 +3310,7 @@ export declare const allTools: ({
|
|
|
3294
3310
|
keepInSync?: undefined;
|
|
3295
3311
|
jobId?: undefined;
|
|
3296
3312
|
reviewBatchLimit?: undefined;
|
|
3313
|
+
allowPartialSourceList?: undefined;
|
|
3297
3314
|
selections?: undefined;
|
|
3298
3315
|
selectionMode?: undefined;
|
|
3299
3316
|
};
|