salesprompter-cli 0.1.65 → 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 +56 -1
- 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
|
@@ -296,6 +296,23 @@ const SalesNavigatorLocalImportResponseSchema = z.object({
|
|
|
296
296
|
})
|
|
297
297
|
.nullable()
|
|
298
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),
|
|
299
316
|
});
|
|
300
317
|
const PhantombusterContainersSyncResponseSchema = z.object({
|
|
301
318
|
status: z.literal("ok"),
|
|
@@ -9275,6 +9292,9 @@ async function importLocalSalesNavigatorPeopleViaApp(session, payload) {
|
|
|
9275
9292
|
totalResults: payload.totalResults,
|
|
9276
9293
|
fetchedPages: payload.fetchedPages,
|
|
9277
9294
|
people: payload.people,
|
|
9295
|
+
...(payload.startEmailEnrichment === false
|
|
9296
|
+
? { startEmailEnrichment: false }
|
|
9297
|
+
: {}),
|
|
9278
9298
|
rawPayload: {
|
|
9279
9299
|
...payload.rawPayload,
|
|
9280
9300
|
clientId: workspaceClientId ?? undefined,
|
|
@@ -9305,6 +9325,20 @@ async function importLocalSalesNavigatorPeopleViaApp(session, payload) {
|
|
|
9305
9325
|
}, SalesNavigatorLocalImportResponseSchema);
|
|
9306
9326
|
return value;
|
|
9307
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
|
+
}
|
|
9308
9342
|
const SALESPROMPTER_SUPABASE_TABLES = {
|
|
9309
9343
|
accountSearchRuns: "salesprompter_linkedin_sales_nav_account_search_runs",
|
|
9310
9344
|
accountSearchSlices: "salesprompter_linkedin_sales_nav_account_search_slices",
|
|
@@ -13813,6 +13847,7 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13813
13847
|
.max(accessibleResultLimit)
|
|
13814
13848
|
.parse(options.maxResults);
|
|
13815
13849
|
const complete = Boolean(options.complete || options.maxResults == null);
|
|
13850
|
+
const emailEnrichmentDeferred = Boolean(options.deferEmailEnrichment);
|
|
13816
13851
|
const checkpointPath = complete
|
|
13817
13852
|
? options.checkpoint
|
|
13818
13853
|
? path.resolve(options.checkpoint)
|
|
@@ -13827,13 +13862,18 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13827
13862
|
accessibleResultLimit,
|
|
13828
13863
|
complete,
|
|
13829
13864
|
resumable: complete,
|
|
13865
|
+
emailEnrichmentDeferred,
|
|
13866
|
+
outreachStarted: false,
|
|
13830
13867
|
destination: "/leads/cli-imports"
|
|
13831
13868
|
};
|
|
13832
13869
|
if (options.out)
|
|
13833
13870
|
await writeJsonFile(options.out, payload);
|
|
13834
13871
|
return payload;
|
|
13835
13872
|
}
|
|
13836
|
-
|
|
13873
|
+
let session = await requireAuthSession();
|
|
13874
|
+
if (emailEnrichmentDeferred) {
|
|
13875
|
+
session = await requireDeferredEmailEnrichmentCapability(session);
|
|
13876
|
+
}
|
|
13837
13877
|
const pageDelayMinMs = z.coerce.number().int().min(0).parse(options.pageDelayMinMs);
|
|
13838
13878
|
const pageDelayMaxMs = z.coerce.number().int().min(pageDelayMinMs).parse(options.pageDelayMaxMs);
|
|
13839
13879
|
const browserRelayPort = options.browserRelayPort == null
|
|
@@ -13899,6 +13939,9 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13899
13939
|
slicePreset: adaptiveCollection
|
|
13900
13940
|
? "local-salesnav-people-adaptive"
|
|
13901
13941
|
: "local-salesnav-people",
|
|
13942
|
+
...(emailEnrichmentDeferred
|
|
13943
|
+
? { startEmailEnrichment: false }
|
|
13944
|
+
: {}),
|
|
13902
13945
|
rawPayload: adaptiveCollection
|
|
13903
13946
|
? {
|
|
13904
13947
|
collectionMode: adaptiveCollection.collectionMode,
|
|
@@ -13914,6 +13957,13 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13914
13957
|
accessibleResultLimit,
|
|
13915
13958
|
},
|
|
13916
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
|
+
}
|
|
13917
13967
|
const payload = {
|
|
13918
13968
|
status: "ok",
|
|
13919
13969
|
dryRun: false,
|
|
@@ -13942,6 +13992,10 @@ async function runSalesNavigatorPeopleCollectCommand(options) {
|
|
|
13942
13992
|
runId: imported.runId,
|
|
13943
13993
|
imported: imported.imported,
|
|
13944
13994
|
upserted: imported.upserted,
|
|
13995
|
+
emailEnrichmentDeferred: imported.enrichmentDeferred ??
|
|
13996
|
+
imported.emailEnrichment?.deferred ??
|
|
13997
|
+
false,
|
|
13998
|
+
outreachStarted: imported.outreachStarted ?? false,
|
|
13945
13999
|
workspaceUrl: `${session.apiBaseUrl}/leads/cli-imports?runId=` +
|
|
13946
14000
|
encodeURIComponent(imported.runId)
|
|
13947
14001
|
};
|
|
@@ -14807,6 +14861,7 @@ program
|
|
|
14807
14861
|
.option("--max-results <number>", "Bounded collection size; defaults to exhaustive collection with a 2500-person window")
|
|
14808
14862
|
.option("--complete", "Split oversized searches by company headcount and deduplicate the complete result", false)
|
|
14809
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)
|
|
14810
14865
|
.option("--curl-file <path>", "Optional copied Sales Navigator Lead Search curl request")
|
|
14811
14866
|
.option("--browser-relay-port <number>", "Use the signed-in browser through a loopback relay")
|
|
14812
14867
|
.option("--page-size <number>", "Direct Sales Navigator page size", "100")
|
package/package.json
CHANGED