@sellable/mcp 0.1.517 → 0.1.519
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/leads.d.ts
CHANGED
|
@@ -206,6 +206,7 @@ export type SelectPromisingPostsInput = {
|
|
|
206
206
|
scrapePlanMode?: "all-selected" | "capacity-target";
|
|
207
207
|
targetEngagerCount?: number;
|
|
208
208
|
maxPostsToScrape?: number;
|
|
209
|
+
workspaceId?: string;
|
|
209
210
|
};
|
|
210
211
|
export type SetHeadlineICPCriteriaInput = {
|
|
211
212
|
campaignOfferId: string;
|
package/dist/tools/leads.js
CHANGED
|
@@ -4648,6 +4648,15 @@ export function getProviderPrompt(input) {
|
|
|
4648
4648
|
}
|
|
4649
4649
|
export async function selectPromisingPosts(input) {
|
|
4650
4650
|
const api = getApi();
|
|
4651
|
+
const workspaceId = normalizeExplicitWorkspaceId(input.workspaceId);
|
|
4652
|
+
const requestOptions = workspaceRequestOptions(workspaceId);
|
|
4653
|
+
const apiGet = (path) => requestOptions ? api.get(path, requestOptions) : api.get(path);
|
|
4654
|
+
const apiPatch = (path, body) => requestOptions
|
|
4655
|
+
? api.patch(path, body, requestOptions)
|
|
4656
|
+
: api.patch(path, body);
|
|
4657
|
+
const apiPut = (path, body) => requestOptions
|
|
4658
|
+
? api.put(path, body, requestOptions)
|
|
4659
|
+
: api.put(path, body);
|
|
4651
4660
|
const { campaignOfferId, selections, headlineICPCriteria, currentStep, selectionMode, mode, scrapePlanMode, targetEngagerCount, maxPostsToScrape, } = input;
|
|
4652
4661
|
const effectiveMode = selectionMode ?? mode ?? "replace";
|
|
4653
4662
|
const effectiveScrapePlanMode = scrapePlanMode ??
|
|
@@ -4667,14 +4676,14 @@ export async function selectPromisingPosts(input) {
|
|
|
4667
4676
|
const postIds = selections.map((s) => s.postId);
|
|
4668
4677
|
let unselectedIds = [];
|
|
4669
4678
|
if (effectiveMode === "replace") {
|
|
4670
|
-
const existing = await
|
|
4679
|
+
const existing = await apiGet(`/api/v3/campaigns/${campaignOfferId}/signal-discovery/posts?selected=true`);
|
|
4671
4680
|
const existingIds = existing?.posts
|
|
4672
4681
|
?.map((post) => post.id)
|
|
4673
4682
|
.filter((id) => Boolean(id)) ?? [];
|
|
4674
4683
|
const selectedSet = new Set(postIds);
|
|
4675
4684
|
unselectedIds = existingIds.filter((id) => !selectedSet.has(id));
|
|
4676
4685
|
}
|
|
4677
|
-
const selectionResult = await
|
|
4686
|
+
const selectionResult = await apiPatch(`/api/v3/campaigns/${campaignOfferId}/signal-discovery/posts`, {
|
|
4678
4687
|
selectedIds: postIds,
|
|
4679
4688
|
unselectedIds,
|
|
4680
4689
|
headlineICPCriteria,
|
|
@@ -4693,7 +4702,7 @@ export async function selectPromisingPosts(input) {
|
|
|
4693
4702
|
let recommendedPostCount = selectionResult.selectedCount;
|
|
4694
4703
|
let recommendationTargetEngagerCount = null;
|
|
4695
4704
|
try {
|
|
4696
|
-
const tabsResponse = await
|
|
4705
|
+
const tabsResponse = await apiGet(`/api/v3/campaigns/${campaignOfferId}/signal-discovery/tabs`);
|
|
4697
4706
|
const reasonsByPostId = new Map(selections.map((selection) => [selection.postId, selection.reason]));
|
|
4698
4707
|
const selectedByUrl = new Map();
|
|
4699
4708
|
for (const tab of tabsResponse.tabs ?? []) {
|
|
@@ -4750,7 +4759,7 @@ Approval card should say:
|
|
|
4750
4759
|
}
|
|
4751
4760
|
const selectionCurrentStep = currentStep === null ? undefined : (currentStep ?? "signal-discovery");
|
|
4752
4761
|
if (selectionCurrentStep) {
|
|
4753
|
-
await
|
|
4762
|
+
await apiPut(`/api/v2/campaign-offers/${campaignOfferId}`, {
|
|
4754
4763
|
currentStep: selectionCurrentStep,
|
|
4755
4764
|
watchNarration: buildSelectedPostApprovalWatchNarration(selectionResult.selectedCount, recommendedPostCount, recommendationTargetEngagerCount),
|
|
4756
4765
|
});
|
|
@@ -33,6 +33,10 @@ export type UserAddedRowsLimitPayload = {
|
|
|
33
33
|
attemptedRows?: number;
|
|
34
34
|
remainingRows?: number;
|
|
35
35
|
};
|
|
36
|
+
export type SourceImportInProgressPayload = {
|
|
37
|
+
error?: string;
|
|
38
|
+
jobId?: string | null;
|
|
39
|
+
};
|
|
36
40
|
export type PrepareRowSelector = {
|
|
37
41
|
type: "needsEnrichment";
|
|
38
42
|
limit?: number;
|
|
@@ -119,6 +123,7 @@ export declare function stringArray(value: unknown): string[];
|
|
|
119
123
|
export declare function prepareRowSelectorValue(value: unknown): PrepareRowSelector | undefined;
|
|
120
124
|
export declare function uniqueStrings(values: Array<string | null | undefined>): string[];
|
|
121
125
|
export declare function userAddedRowsLimitPayloadFromError(error: unknown): UserAddedRowsLimitPayload | null;
|
|
126
|
+
export declare function sourceImportInProgressPayloadFromError(error: unknown): SourceImportInProgressPayload | null;
|
|
122
127
|
export declare function paidRefreshActionFrom(value: unknown): PaidInmailRefreshAction | null;
|
|
123
128
|
export declare function collectPaidInmailRefreshActions(plan: unknown): PaidInmailRefreshAction[];
|
|
124
129
|
export declare function firstGlobalAction(plan: unknown): Record<string, unknown> | null;
|
|
@@ -85,6 +85,44 @@ export function userAddedRowsLimitPayloadFromError(error) {
|
|
|
85
85
|
return null;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
+
function apiErrorStatus(error) {
|
|
89
|
+
if (error instanceof SellableApiError)
|
|
90
|
+
return error.status;
|
|
91
|
+
const record = recordValue(error);
|
|
92
|
+
const status = record?.status;
|
|
93
|
+
return typeof status === "number" && Number.isFinite(status) ? status : null;
|
|
94
|
+
}
|
|
95
|
+
function apiErrorBody(error) {
|
|
96
|
+
if (error instanceof SellableApiError)
|
|
97
|
+
return error.body;
|
|
98
|
+
const record = recordValue(error);
|
|
99
|
+
return stringValue(record?.body) ?? stringValue(record?.message);
|
|
100
|
+
}
|
|
101
|
+
export function sourceImportInProgressPayloadFromError(error) {
|
|
102
|
+
if (apiErrorStatus(error) !== 409)
|
|
103
|
+
return null;
|
|
104
|
+
const body = apiErrorBody(error);
|
|
105
|
+
if (!body)
|
|
106
|
+
return null;
|
|
107
|
+
try {
|
|
108
|
+
const parsed = JSON.parse(body);
|
|
109
|
+
const message = stringValue(parsed.error);
|
|
110
|
+
if (message !== "Import already in progress")
|
|
111
|
+
return null;
|
|
112
|
+
return {
|
|
113
|
+
error: message,
|
|
114
|
+
jobId: stringValue(parsed.jobId),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
if (!body.includes("Import already in progress"))
|
|
119
|
+
return null;
|
|
120
|
+
return {
|
|
121
|
+
error: "Import already in progress",
|
|
122
|
+
jobId: null,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
88
126
|
export function paidRefreshActionFrom(value) {
|
|
89
127
|
const action = recordValue(value);
|
|
90
128
|
if (!action || action.type !== "refresh_paid_inmail_credits")
|
|
@@ -707,6 +745,18 @@ export async function executeOneYoloPrimitive(action, workspaceId) {
|
|
|
707
745
|
result = await confirmLeadList(copyInput);
|
|
708
746
|
}
|
|
709
747
|
catch (error) {
|
|
748
|
+
const sourceImportInProgress = sourceImportInProgressPayloadFromError(error);
|
|
749
|
+
if (sourceImportInProgress) {
|
|
750
|
+
return {
|
|
751
|
+
status: "read_only_reread",
|
|
752
|
+
result: {
|
|
753
|
+
waited: true,
|
|
754
|
+
reason: "source_import_in_progress",
|
|
755
|
+
jobId: sourceImportInProgress.jobId ?? null,
|
|
756
|
+
error: sourceImportInProgress.error,
|
|
757
|
+
},
|
|
758
|
+
};
|
|
759
|
+
}
|
|
710
760
|
const rowLimitPayload = userAddedRowsLimitPayloadFromError(error);
|
|
711
761
|
if (!rowLimitPayload)
|
|
712
762
|
throw error;
|