salesprompter-cli 0.1.64 → 0.1.66
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/README.md +5 -0
- package/dist/cli.js +57 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,6 +73,11 @@ salesprompter contacts:resolve-emails --in ./contacts.tsv --out-dir ./email-run
|
|
|
73
73
|
salesprompter leads:collect \
|
|
74
74
|
--linkedin-url "$SALES_NAV_PEOPLE_URL"
|
|
75
75
|
|
|
76
|
+
# For large discovery runs, store the leads now and enrich selected imports later
|
|
77
|
+
salesprompter leads:collect \
|
|
78
|
+
--linkedin-url "$SALES_NAV_PEOPLE_URL" \
|
|
79
|
+
--defer-email-enrichment
|
|
80
|
+
|
|
76
81
|
# Enrich one or more stored imports: Sales Navigator company -> official domain -> Hunter email
|
|
77
82
|
# This updates workspace data only. It does not create or start outreach.
|
|
78
83
|
# Stale ids and raw legal-name misses use conservative exact-name recovery.
|
package/dist/cli.js
CHANGED
|
@@ -186,21 +186,6 @@ const AffiliateStrictSequenceSchema = z.tuple([
|
|
|
186
186
|
AffiliateStrictSequenceStepSchema.extend({ step: z.literal(2) }),
|
|
187
187
|
AffiliateStrictSequenceStepSchema.extend({ step: z.literal(3) })
|
|
188
188
|
]);
|
|
189
|
-
const AffiliateOutreachLeadSchema = z.object({
|
|
190
|
-
rowIndex: z.number().int().nonnegative(),
|
|
191
|
-
fullName: z.string().min(1),
|
|
192
|
-
firstName: z.string().min(1),
|
|
193
|
-
lastName: z.string().min(1),
|
|
194
|
-
jobTitle: z.string().nullable(),
|
|
195
|
-
companyName: z.string().min(1),
|
|
196
|
-
companyDomain: z.string().min(1),
|
|
197
|
-
location: z.string().nullable(),
|
|
198
|
-
profileUrl: z.string().nullable(),
|
|
199
|
-
email: z.string().email(),
|
|
200
|
-
emailScore: z.number().min(0).max(100),
|
|
201
|
-
acceptAll: z.boolean(),
|
|
202
|
-
emailSource: z.enum(["hunter", "phantombuster"]).optional()
|
|
203
|
-
});
|
|
204
189
|
const AffiliateOutreachRunBaseSchema = z.object({
|
|
205
190
|
id: z.string().uuid(),
|
|
206
191
|
audience_run_id: z.string().uuid(),
|
|
@@ -210,7 +195,6 @@ const AffiliateOutreachRunBaseSchema = z.object({
|
|
|
210
195
|
instantly_campaign_id: z.string().min(1).nullable(),
|
|
211
196
|
instantly_campaign_name: z.string().min(1).nullable(),
|
|
212
197
|
sequence: z.array(AffiliateHistoricalSequenceStepSchema),
|
|
213
|
-
enriched_leads: z.array(AffiliateOutreachLeadSchema),
|
|
214
198
|
stats: z.record(z.string(), z.unknown()),
|
|
215
199
|
settings: z.record(z.string(), z.unknown()),
|
|
216
200
|
error_message: z.string().nullable(),
|
|
@@ -234,9 +218,7 @@ const AffiliateOutreachResponseSchema = z.object({
|
|
|
234
218
|
status: z.literal("ok"),
|
|
235
219
|
outreach: AffiliateOutreachRunSchema
|
|
236
220
|
});
|
|
237
|
-
const AffiliateOutreachSummarySchema = AffiliateOutreachRunBaseSchema
|
|
238
|
-
enriched_leads: true
|
|
239
|
-
});
|
|
221
|
+
const AffiliateOutreachSummarySchema = AffiliateOutreachRunBaseSchema;
|
|
240
222
|
const AffiliateAudienceSummarySchema = z.object({
|
|
241
223
|
public_token: z.string().min(1),
|
|
242
224
|
status: z.enum(["launching", "running", "finished", "failed"]),
|
|
@@ -314,6 +296,23 @@ const SalesNavigatorLocalImportResponseSchema = z.object({
|
|
|
314
296
|
})
|
|
315
297
|
.nullable()
|
|
316
298
|
.optional(),
|
|
299
|
+
emailEnrichment: z
|
|
300
|
+
.object({
|
|
301
|
+
scheduled: z.boolean(),
|
|
302
|
+
deferred: z.boolean().optional(),
|
|
303
|
+
provider: z.string().min(1).optional(),
|
|
304
|
+
fallbackProvider: z.string().min(1).optional(),
|
|
305
|
+
})
|
|
306
|
+
.optional(),
|
|
307
|
+
enrichmentDeferred: z.boolean().optional(),
|
|
308
|
+
outreachStarted: z.literal(false).optional(),
|
|
309
|
+
});
|
|
310
|
+
const SalesNavigatorLocalImportCapabilitiesResponseSchema = z.object({
|
|
311
|
+
status: z.literal("ok"),
|
|
312
|
+
capabilities: z.object({
|
|
313
|
+
deferredEmailEnrichment: z.literal(true),
|
|
314
|
+
}),
|
|
315
|
+
outreachStarted: z.literal(false),
|
|
317
316
|
});
|
|
318
317
|
const PhantombusterContainersSyncResponseSchema = z.object({
|
|
319
318
|
status: z.literal("ok"),
|
|
@@ -9293,6 +9292,9 @@ async function importLocalSalesNavigatorPeopleViaApp(session, payload) {
|
|
|
9293
9292
|
totalResults: payload.totalResults,
|
|
9294
9293
|
fetchedPages: payload.fetchedPages,
|
|
9295
9294
|
people: payload.people,
|
|
9295
|
+
...(payload.startEmailEnrichment === false
|
|
9296
|
+
? { startEmailEnrichment: false }
|
|
9297
|
+
: {}),
|
|
9296
9298
|
rawPayload: {
|
|
9297
9299
|
...payload.rawPayload,
|
|
9298
9300
|
clientId: workspaceClientId ?? undefined,
|
|
@@ -9323,6 +9325,20 @@ async function importLocalSalesNavigatorPeopleViaApp(session, payload) {
|
|
|
9323
9325
|
}, SalesNavigatorLocalImportResponseSchema);
|
|
9324
9326
|
return value;
|
|
9325
9327
|
}
|
|
9328
|
+
async function requireDeferredEmailEnrichmentCapability(session) {
|
|
9329
|
+
try {
|
|
9330
|
+
const result = await fetchCliJson(session, (currentSession) => fetch(`${currentSession.apiBaseUrl}/api/cli/salesnav/local-import`, {
|
|
9331
|
+
method: "GET",
|
|
9332
|
+
headers: {
|
|
9333
|
+
Authorization: `Bearer ${currentSession.accessToken}`,
|
|
9334
|
+
},
|
|
9335
|
+
}), SalesNavigatorLocalImportCapabilitiesResponseSchema);
|
|
9336
|
+
return result.session;
|
|
9337
|
+
}
|
|
9338
|
+
catch {
|
|
9339
|
+
throw new Error("This Salesprompter workspace cannot safely defer email enrichment yet. Update the app before collecting leads with --defer-email-enrichment.");
|
|
9340
|
+
}
|
|
9341
|
+
}
|
|
9326
9342
|
const SALESPROMPTER_SUPABASE_TABLES = {
|
|
9327
9343
|
accountSearchRuns: "salesprompter_linkedin_sales_nav_account_search_runs",
|
|
9328
9344
|
accountSearchSlices: "salesprompter_linkedin_sales_nav_account_search_slices",
|
|
@@ -13831,6 +13847,7 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13831
13847
|
.max(accessibleResultLimit)
|
|
13832
13848
|
.parse(options.maxResults);
|
|
13833
13849
|
const complete = Boolean(options.complete || options.maxResults == null);
|
|
13850
|
+
const emailEnrichmentDeferred = Boolean(options.deferEmailEnrichment);
|
|
13834
13851
|
const checkpointPath = complete
|
|
13835
13852
|
? options.checkpoint
|
|
13836
13853
|
? path.resolve(options.checkpoint)
|
|
@@ -13845,13 +13862,18 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13845
13862
|
accessibleResultLimit,
|
|
13846
13863
|
complete,
|
|
13847
13864
|
resumable: complete,
|
|
13865
|
+
emailEnrichmentDeferred,
|
|
13866
|
+
outreachStarted: false,
|
|
13848
13867
|
destination: "/leads/cli-imports"
|
|
13849
13868
|
};
|
|
13850
13869
|
if (options.out)
|
|
13851
13870
|
await writeJsonFile(options.out, payload);
|
|
13852
13871
|
return payload;
|
|
13853
13872
|
}
|
|
13854
|
-
|
|
13873
|
+
let session = await requireAuthSession();
|
|
13874
|
+
if (emailEnrichmentDeferred) {
|
|
13875
|
+
session = await requireDeferredEmailEnrichmentCapability(session);
|
|
13876
|
+
}
|
|
13855
13877
|
const pageDelayMinMs = z.coerce.number().int().min(0).parse(options.pageDelayMinMs);
|
|
13856
13878
|
const pageDelayMaxMs = z.coerce.number().int().min(pageDelayMinMs).parse(options.pageDelayMaxMs);
|
|
13857
13879
|
const browserRelayPort = options.browserRelayPort == null
|
|
@@ -13917,6 +13939,9 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13917
13939
|
slicePreset: adaptiveCollection
|
|
13918
13940
|
? "local-salesnav-people-adaptive"
|
|
13919
13941
|
: "local-salesnav-people",
|
|
13942
|
+
...(emailEnrichmentDeferred
|
|
13943
|
+
? { startEmailEnrichment: false }
|
|
13944
|
+
: {}),
|
|
13920
13945
|
rawPayload: adaptiveCollection
|
|
13921
13946
|
? {
|
|
13922
13947
|
collectionMode: adaptiveCollection.collectionMode,
|
|
@@ -13932,6 +13957,13 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13932
13957
|
accessibleResultLimit,
|
|
13933
13958
|
},
|
|
13934
13959
|
});
|
|
13960
|
+
if (emailEnrichmentDeferred &&
|
|
13961
|
+
!(imported.enrichmentDeferred === true &&
|
|
13962
|
+
imported.emailEnrichment?.deferred === true &&
|
|
13963
|
+
imported.emailEnrichment.scheduled === false &&
|
|
13964
|
+
imported.outreachStarted === false)) {
|
|
13965
|
+
throw new Error(`Import ${imported.runId} was stored, but the workspace did not confirm that email enrichment was deferred. Do not repeat the collection until that run's enrichment state is verified.`);
|
|
13966
|
+
}
|
|
13935
13967
|
const payload = {
|
|
13936
13968
|
status: "ok",
|
|
13937
13969
|
dryRun: false,
|
|
@@ -13960,6 +13992,10 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13960
13992
|
runId: imported.runId,
|
|
13961
13993
|
imported: imported.imported,
|
|
13962
13994
|
upserted: imported.upserted,
|
|
13995
|
+
emailEnrichmentDeferred: imported.enrichmentDeferred ??
|
|
13996
|
+
imported.emailEnrichment?.deferred ??
|
|
13997
|
+
false,
|
|
13998
|
+
outreachStarted: imported.outreachStarted ?? false,
|
|
13963
13999
|
workspaceUrl: `${session.apiBaseUrl}/leads/cli-imports?runId=` +
|
|
13964
14000
|
encodeURIComponent(imported.runId)
|
|
13965
14001
|
};
|
|
@@ -14825,6 +14861,7 @@ program
|
|
|
14825
14861
|
.option("--max-results <number>", "Bounded collection size; defaults to exhaustive collection with a 2500-person window")
|
|
14826
14862
|
.option("--complete", "Split oversized searches by company headcount and deduplicate the complete result", false)
|
|
14827
14863
|
.option("--checkpoint <path>", "Optional resume checkpoint; exhaustive runs use a per-query checkpoint by default")
|
|
14864
|
+
.option("--defer-email-enrichment", "Store leads without starting email enrichment", false)
|
|
14828
14865
|
.option("--curl-file <path>", "Optional copied Sales Navigator Lead Search curl request")
|
|
14829
14866
|
.option("--browser-relay-port <number>", "Use the signed-in browser through a loopback relay")
|
|
14830
14867
|
.option("--page-size <number>", "Direct Sales Navigator page size", "100")
|
package/package.json
CHANGED