salesprompter-cli 0.1.26 → 0.1.27
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 +11 -2
- package/dist/cli.js +158 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Salesprompter CLI helps you go from company or product input to qualified leads
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
curl -fsSL https://docs.salesprompter.ai/install.sh | bash
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
or run directly:
|
|
@@ -17,6 +17,12 @@ npx -y salesprompter-cli@latest
|
|
|
17
17
|
## Quickstart
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
+
# Run first-time setup
|
|
21
|
+
salesprompter setup
|
|
22
|
+
|
|
23
|
+
# Run a local health check
|
|
24
|
+
salesprompter doctor
|
|
25
|
+
|
|
20
26
|
# Sign in from the CLI
|
|
21
27
|
salesprompter auth:login
|
|
22
28
|
|
|
@@ -32,7 +38,7 @@ For headless or automation use, generate a CLI token in the app and run `salespr
|
|
|
32
38
|
|
|
33
39
|
```bash
|
|
34
40
|
# Start the guided workflow
|
|
35
|
-
salesprompter
|
|
41
|
+
salesprompter wizard
|
|
36
42
|
|
|
37
43
|
# Show machine-readable output
|
|
38
44
|
salesprompter --json auth:whoami
|
|
@@ -44,6 +50,9 @@ salesprompter contacts:find-linkedin-urls --in ./contacts.tsv --out ./contacts.e
|
|
|
44
50
|
# When authenticated, Salesprompter first enriches company domains in the app, then the CLI builds the email batch.
|
|
45
51
|
salesprompter contacts:resolve-emails --in ./contacts.tsv --out-dir ./email-run --dry-run
|
|
46
52
|
|
|
53
|
+
# See included capability packs
|
|
54
|
+
salesprompter packs:list
|
|
55
|
+
|
|
47
56
|
# Explore the full command surface
|
|
48
57
|
salesprompter --help
|
|
49
58
|
```
|
package/dist/cli.js
CHANGED
|
@@ -248,6 +248,36 @@ const SalesNavigatorCrawlReportResponseSchema = z.object({
|
|
|
248
248
|
status: z.literal("ok"),
|
|
249
249
|
job: SalesNavigatorCrawlJobSummarySchema
|
|
250
250
|
});
|
|
251
|
+
const cliPacks = [
|
|
252
|
+
{
|
|
253
|
+
slug: "contacts",
|
|
254
|
+
title: "Contacts",
|
|
255
|
+
summary: "Resolve profile URLs and work from pasted contact lists.",
|
|
256
|
+
commands: ["contacts:resolve-profiles", "contacts:resolve-emails"],
|
|
257
|
+
installStatus: "included"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
slug: "research",
|
|
261
|
+
title: "Research",
|
|
262
|
+
summary: "Scrape markets and enrich companies before outreach.",
|
|
263
|
+
commands: ["market:scrape", "companies:enrich"],
|
|
264
|
+
installStatus: "included"
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
slug: "discovery",
|
|
268
|
+
title: "Discovery",
|
|
269
|
+
summary: "Find leads from product and market inputs.",
|
|
270
|
+
commands: ["leads:discover", "search:run", "search:status", "search:export", "search:count"],
|
|
271
|
+
installStatus: "included"
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
slug: "outreach",
|
|
275
|
+
title: "Outreach",
|
|
276
|
+
summary: "Prepare and sync qualified leads into downstream systems.",
|
|
277
|
+
commands: ["sync:outreach", "sync:crm"],
|
|
278
|
+
installStatus: "included"
|
|
279
|
+
}
|
|
280
|
+
];
|
|
251
281
|
const helpAliasByCommandName = new Map([
|
|
252
282
|
["contacts:find-linkedin-urls", "contacts:resolve-profiles"],
|
|
253
283
|
["contacts:process-emails", "contacts:resolve-emails"],
|
|
@@ -260,6 +290,11 @@ const helpAliasByCommandName = new Map([
|
|
|
260
290
|
["salesnav:count", "search:count"]
|
|
261
291
|
]);
|
|
262
292
|
const helpVisibleCommandNames = new Set([
|
|
293
|
+
"setup",
|
|
294
|
+
"doctor",
|
|
295
|
+
"packs:list",
|
|
296
|
+
"packs:add",
|
|
297
|
+
"upgrade",
|
|
263
298
|
"auth:login",
|
|
264
299
|
"wizard",
|
|
265
300
|
"auth:whoami",
|
|
@@ -4512,6 +4547,9 @@ program.configureHelp({
|
|
|
4512
4547
|
});
|
|
4513
4548
|
program.addHelpText("after", `
|
|
4514
4549
|
LLM operator tips:
|
|
4550
|
+
- Install with: curl -fsSL https://docs.salesprompter.ai/install.sh | bash
|
|
4551
|
+
- First-run setup: salesprompter setup
|
|
4552
|
+
- Run a quick health check: salesprompter doctor
|
|
4515
4553
|
- New here? Create your account at https://salesprompter.ai/sign-up, then run: salesprompter auth:login
|
|
4516
4554
|
- Prefer non-interactive auth: set SALESPROMPTER_TOKEN (+ optional SALESPROMPTER_API_BASE_URL).
|
|
4517
4555
|
- Use machine output for tools: add --json.
|
|
@@ -4519,6 +4557,117 @@ LLM operator tips:
|
|
|
4519
4557
|
- Preview contact enrichment first: contacts:resolve-profiles --in <contacts.tsv> --dry-run.
|
|
4520
4558
|
- For bigger runs, start with a small sample before processing the full file.
|
|
4521
4559
|
`);
|
|
4560
|
+
program
|
|
4561
|
+
.command("setup")
|
|
4562
|
+
.description("Run the fastest first-run setup path for the Salesprompter CLI.")
|
|
4563
|
+
.option("--api-url <url>", "Salesprompter API base URL, defaults to SALESPROMPTER_API_BASE_URL or salesprompter.ai")
|
|
4564
|
+
.option("--timeout-seconds <number>", "Auth login timeout in seconds when setup needs to sign in", "180")
|
|
4565
|
+
.action(async (options) => {
|
|
4566
|
+
const timeoutSeconds = z.coerce.number().int().min(30).max(1800).parse(options.timeoutSeconds);
|
|
4567
|
+
printOutput({
|
|
4568
|
+
status: "ok",
|
|
4569
|
+
command: "setup",
|
|
4570
|
+
next: [
|
|
4571
|
+
"salesprompter auth:login",
|
|
4572
|
+
"salesprompter auth:whoami --verify",
|
|
4573
|
+
"salesprompter wizard"
|
|
4574
|
+
],
|
|
4575
|
+
docs: "https://docs.salesprompter.ai/quickstart"
|
|
4576
|
+
});
|
|
4577
|
+
if (process.stdin.isTTY && process.stdout.isTTY && !runtimeOutputOptions.json && !runtimeOutputOptions.quiet) {
|
|
4578
|
+
await runWizard({
|
|
4579
|
+
apiUrl: options.apiUrl,
|
|
4580
|
+
timeoutSeconds
|
|
4581
|
+
});
|
|
4582
|
+
}
|
|
4583
|
+
});
|
|
4584
|
+
program
|
|
4585
|
+
.command("doctor")
|
|
4586
|
+
.description("Check local CLI prerequisites, auth state, and optional enrichment setup.")
|
|
4587
|
+
.action(async () => {
|
|
4588
|
+
const nodeMajor = Number(process.versions.node.split(".")[0] ?? "0");
|
|
4589
|
+
const readiness = await resolveLlmAuthReadiness();
|
|
4590
|
+
const hasOpenAiKey = Boolean(process.env.OPENAI_API_KEY || process.env.SALESPROMPTER_OPENAI_API_KEY);
|
|
4591
|
+
const hasLinkedInSession = Boolean(process.env.LINKEDIN_CSRF_TOKEN ||
|
|
4592
|
+
process.env.SALESPROMPTER_LINKEDIN_CSRF_TOKEN ||
|
|
4593
|
+
process.env.LINKEDIN_X_LI_IDENTITY ||
|
|
4594
|
+
process.env.SALESPROMPTER_LINKEDIN_X_LI_IDENTITY ||
|
|
4595
|
+
process.env.LINKEDIN_SALES_NAV_COOKIE ||
|
|
4596
|
+
process.env.SALESPROMPTER_LINKEDIN_SALES_NAV_COOKIE);
|
|
4597
|
+
printOutput({
|
|
4598
|
+
status: "ok",
|
|
4599
|
+
command: "doctor",
|
|
4600
|
+
checks: {
|
|
4601
|
+
node: {
|
|
4602
|
+
ok: nodeMajor >= 20,
|
|
4603
|
+
current: process.versions.node,
|
|
4604
|
+
required: ">=20.0.0"
|
|
4605
|
+
},
|
|
4606
|
+
auth: {
|
|
4607
|
+
ok: readiness.ready,
|
|
4608
|
+
mode: readiness.mode,
|
|
4609
|
+
apiBaseUrl: readiness.apiBaseUrl,
|
|
4610
|
+
reason: readiness.reason ?? null
|
|
4611
|
+
},
|
|
4612
|
+
companyCleaningAi: {
|
|
4613
|
+
ok: hasOpenAiKey,
|
|
4614
|
+
envVarPresent: hasOpenAiKey
|
|
4615
|
+
},
|
|
4616
|
+
linkedInSession: {
|
|
4617
|
+
ok: hasLinkedInSession,
|
|
4618
|
+
envVarPresent: hasLinkedInSession
|
|
4619
|
+
}
|
|
4620
|
+
},
|
|
4621
|
+
recommended: [
|
|
4622
|
+
readiness.ready ? null : "salesprompter auth:login",
|
|
4623
|
+
hasOpenAiKey ? null : "Set OPENAI_API_KEY to enable --company-cleaning ai",
|
|
4624
|
+
hasLinkedInSession ? null : "Set LINKEDIN_CSRF_TOKEN, LINKEDIN_X_LI_IDENTITY, and LINKEDIN_SALES_NAV_COOKIE for direct LinkedIn lookup"
|
|
4625
|
+
].filter(Boolean)
|
|
4626
|
+
});
|
|
4627
|
+
});
|
|
4628
|
+
program
|
|
4629
|
+
.command("packs:list")
|
|
4630
|
+
.description("Show the product capability packs included in the CLI.")
|
|
4631
|
+
.action(() => {
|
|
4632
|
+
printOutput({
|
|
4633
|
+
status: "ok",
|
|
4634
|
+
packs: cliPacks
|
|
4635
|
+
});
|
|
4636
|
+
});
|
|
4637
|
+
program
|
|
4638
|
+
.command("packs:add")
|
|
4639
|
+
.description("Explain how to unlock a capability pack in the Salesprompter CLI.")
|
|
4640
|
+
.argument("<pack>", "Pack slug, for example contacts, research, discovery, or outreach")
|
|
4641
|
+
.action((pack) => {
|
|
4642
|
+
const normalized = String(pack).trim().toLowerCase();
|
|
4643
|
+
const match = cliPacks.find((entry) => entry.slug === normalized);
|
|
4644
|
+
if (!match) {
|
|
4645
|
+
throw new Error(`Unknown pack "${pack}". Run "salesprompter packs:list" to see the supported packs.`);
|
|
4646
|
+
}
|
|
4647
|
+
printOutput({
|
|
4648
|
+
status: "ok",
|
|
4649
|
+
pack: match.slug,
|
|
4650
|
+
title: match.title,
|
|
4651
|
+
available: true,
|
|
4652
|
+
installStatus: match.installStatus,
|
|
4653
|
+
commands: match.commands,
|
|
4654
|
+
message: `The ${match.title} pack is already included. Start with: salesprompter ${match.commands[0]}`
|
|
4655
|
+
});
|
|
4656
|
+
});
|
|
4657
|
+
program
|
|
4658
|
+
.command("upgrade")
|
|
4659
|
+
.description("Show the recommended upgrade command for the current installation.")
|
|
4660
|
+
.action(() => {
|
|
4661
|
+
printOutput({
|
|
4662
|
+
status: "ok",
|
|
4663
|
+
command: "upgrade",
|
|
4664
|
+
recommended: {
|
|
4665
|
+
npmGlobal: "npm i -g salesprompter-cli@latest",
|
|
4666
|
+
npx: "npx -y salesprompter-cli@latest",
|
|
4667
|
+
docs: "https://docs.salesprompter.ai/quickstart"
|
|
4668
|
+
}
|
|
4669
|
+
});
|
|
4670
|
+
});
|
|
4522
4671
|
program
|
|
4523
4672
|
.command("auth:login")
|
|
4524
4673
|
.description("Authenticate CLI with a Salesprompter app token, or device flow if the app supports it.")
|
|
@@ -4734,10 +4883,18 @@ program
|
|
|
4734
4883
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
4735
4884
|
applyGlobalOutputOptions(actionCommand);
|
|
4736
4885
|
const commandName = actionCommand.name();
|
|
4886
|
+
const parentCommandName = actionCommand.parent && typeof actionCommand.parent.name === "function"
|
|
4887
|
+
? actionCommand.parent.name()
|
|
4888
|
+
: "";
|
|
4737
4889
|
if (commandName.startsWith("auth:") ||
|
|
4890
|
+
commandName === "setup" ||
|
|
4891
|
+
commandName === "doctor" ||
|
|
4892
|
+
commandName === "upgrade" ||
|
|
4738
4893
|
commandName === "wizard" ||
|
|
4739
4894
|
commandName === "llm:ready" ||
|
|
4740
|
-
commandName === "contacts:find-linkedin-urls"
|
|
4895
|
+
commandName === "contacts:find-linkedin-urls" ||
|
|
4896
|
+
commandName.startsWith("packs:") ||
|
|
4897
|
+
((commandName === "list" || commandName === "add") && parentCommandName === "packs")) {
|
|
4741
4898
|
return;
|
|
4742
4899
|
}
|
|
4743
4900
|
const commandOptions = actionCommand.opts();
|