salesprompter-cli 0.1.2 → 0.1.3
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 +27 -7
- package/dist/auth.js +27 -4
- package/dist/cli.js +9 -4
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -12,6 +12,25 @@
|
|
|
12
12
|
- Analyze upstream lead-list and domain-enrichment bottlenecks
|
|
13
13
|
- Replace opaque Pipedream logic with deterministic CLI workflows
|
|
14
14
|
|
|
15
|
+
## Documentation
|
|
16
|
+
|
|
17
|
+
This repository now includes a Mintlify docs site for the wider Salesprompter universe, including the app contract, CLI surface, Chrome extension contract, and the main warehouse-backed workflows.
|
|
18
|
+
|
|
19
|
+
- Docs home: `./index.mdx`
|
|
20
|
+
- Quickstart: `./quickstart.mdx`
|
|
21
|
+
- Architecture: `./architecture.mdx`
|
|
22
|
+
- App: `./platform/app.mdx`
|
|
23
|
+
- CLI: `./platform/cli.mdx`
|
|
24
|
+
- Chrome extension: `./platform/chrome-extension.mdx`
|
|
25
|
+
- Domain finder: `./workflows/domain-finder.mdx`
|
|
26
|
+
- Command reference: `./reference/cli.mdx`
|
|
27
|
+
|
|
28
|
+
Run the docs locally with:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm run docs:dev
|
|
32
|
+
```
|
|
33
|
+
|
|
15
34
|
## Integration Contract
|
|
16
35
|
|
|
17
36
|
This CLI is not a standalone toy. It is a production integration surface for the Salesprompter app.
|
|
@@ -39,11 +58,11 @@ Global output flags:
|
|
|
39
58
|
The CLI stores a local session file at `~/.config/salesprompter/auth-session.json` (or `SALESPROMPTER_CONFIG_DIR`).
|
|
40
59
|
|
|
41
60
|
```bash
|
|
42
|
-
#
|
|
43
|
-
salesprompter auth:login
|
|
61
|
+
# Production path: generate a short-lived CLI token in the Salesprompter app
|
|
62
|
+
salesprompter auth:login --token "$SALESPROMPTER_TOKEN" --api-url "https://salesprompter.ai"
|
|
44
63
|
|
|
45
|
-
#
|
|
46
|
-
salesprompter auth:login
|
|
64
|
+
# Optional: use device flow only if your Salesprompter app exposes it
|
|
65
|
+
salesprompter auth:login
|
|
47
66
|
|
|
48
67
|
# Verify active identity with backend
|
|
49
68
|
salesprompter auth:whoami --verify
|
|
@@ -54,7 +73,7 @@ salesprompter auth:logout
|
|
|
54
73
|
|
|
55
74
|
Environment variables:
|
|
56
75
|
|
|
57
|
-
- `SALESPROMPTER_API_BASE_URL`: override backend URL (default `https://
|
|
76
|
+
- `SALESPROMPTER_API_BASE_URL`: override backend URL (default `https://salesprompter.ai`)
|
|
58
77
|
- `SALESPROMPTER_CONFIG_DIR`: override local config dir
|
|
59
78
|
- `SALESPROMPTER_SKIP_AUTH=1`: bypass auth guard (tests/dev only)
|
|
60
79
|
- `INSTANTLY_API_KEY`: required for real `sync:outreach --target instantly`
|
|
@@ -63,11 +82,12 @@ Environment variables:
|
|
|
63
82
|
|
|
64
83
|
App compatibility:
|
|
65
84
|
|
|
66
|
-
-
|
|
85
|
+
- Current Salesprompter production uses app-issued CLI tokens.
|
|
86
|
+
- If your app exposes `/api/cli/auth/device/start` and `/api/cli/auth/device/poll`, `salesprompter auth:login` will use device flow.
|
|
67
87
|
- If device auth is not enabled, create a CLI token from the app endpoint `POST /api/cli/auth/token` and use:
|
|
68
88
|
|
|
69
89
|
```bash
|
|
70
|
-
salesprompter auth:login --token "<token-from-app>"
|
|
90
|
+
salesprompter auth:login --token "<token-from-app>" --api-url "https://salesprompter.ai"
|
|
71
91
|
```
|
|
72
92
|
|
|
73
93
|
## Why this shape works for humans and LLMs
|
package/dist/auth.js
CHANGED
|
@@ -2,7 +2,7 @@ import os from "node:os";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
const DEFAULT_API_BASE_URL = "https://
|
|
5
|
+
const DEFAULT_API_BASE_URL = "https://salesprompter.ai";
|
|
6
6
|
const CLIENT_HEADER = "salesprompter-cli/0.2";
|
|
7
7
|
const DEFAULT_DEVICE_POLL_INTERVAL_SECONDS = 3;
|
|
8
8
|
const DEFAULT_DEVICE_TIMEOUT_SECONDS = 180;
|
|
@@ -94,6 +94,18 @@ function normalizeApiBaseUrl(apiBaseUrl) {
|
|
|
94
94
|
const value = (apiBaseUrl ?? process.env.SALESPROMPTER_API_BASE_URL ?? DEFAULT_API_BASE_URL).trim();
|
|
95
95
|
return value.replace(/\/+$/, "");
|
|
96
96
|
}
|
|
97
|
+
function isDeviceFlowUnavailableError(message) {
|
|
98
|
+
if (message.includes("invalid JSON response")) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
return /request failed \((401|403|404|405|500|501|502|503|504)\)/.test(message);
|
|
102
|
+
}
|
|
103
|
+
function buildDeviceFlowUnavailableMessage(apiBaseUrl) {
|
|
104
|
+
return [
|
|
105
|
+
"device login is not configured on this Salesprompter app.",
|
|
106
|
+
`Generate a CLI token in the app and run \`salesprompter auth:login --token <token> --api-url "${apiBaseUrl}"\`.`
|
|
107
|
+
].join(" ");
|
|
108
|
+
}
|
|
97
109
|
async function hasSessionFile() {
|
|
98
110
|
try {
|
|
99
111
|
await access(getSessionPath());
|
|
@@ -106,7 +118,18 @@ async function hasSessionFile() {
|
|
|
106
118
|
async function httpJson(url, init, schema) {
|
|
107
119
|
const response = await fetch(url, init);
|
|
108
120
|
const text = await response.text();
|
|
109
|
-
|
|
121
|
+
let payload = {};
|
|
122
|
+
if (text.length > 0) {
|
|
123
|
+
try {
|
|
124
|
+
payload = JSON.parse(text);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
if (!response.ok) {
|
|
128
|
+
throw new Error(`request failed (${response.status}) for ${url}`);
|
|
129
|
+
}
|
|
130
|
+
throw new Error(`invalid JSON response for ${url}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
110
133
|
if (!response.ok) {
|
|
111
134
|
throw new Error(`request failed (${response.status}) for ${url}`);
|
|
112
135
|
}
|
|
@@ -195,8 +218,8 @@ export async function loginWithDeviceFlow(options) {
|
|
|
195
218
|
}
|
|
196
219
|
catch (error) {
|
|
197
220
|
const message = error instanceof Error ? error.message : String(error);
|
|
198
|
-
if (message
|
|
199
|
-
throw new Error(
|
|
221
|
+
if (isDeviceFlowUnavailableError(message)) {
|
|
222
|
+
throw new Error(buildDeviceFlowUnavailableMessage(apiBaseUrl));
|
|
200
223
|
}
|
|
201
224
|
throw error;
|
|
202
225
|
}
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import { Command } from "commander";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import { clearAuthSession, loginWithDeviceFlow, loginWithToken, requireAuthSession, shouldBypassAuth, verifySession } from "./auth.js";
|
|
@@ -11,6 +12,8 @@ import { buildHistoricalVendorIcp, buildVendorIcp } from "./icp-templates.js";
|
|
|
11
12
|
import { InstantlySyncProvider } from "./instantly.js";
|
|
12
13
|
import { buildLeadlistsFunnelQueries } from "./leadlists-funnel.js";
|
|
13
14
|
import { readJsonFile, splitCsv, writeJsonFile, writeTextFile } from "./io.js";
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
const { version: packageVersion } = require("../package.json");
|
|
14
17
|
const program = new Command();
|
|
15
18
|
const leadProvider = new AccountLeadProvider(new HeuristicCompanyProvider(), new HeuristicPeopleSearchProvider());
|
|
16
19
|
const enrichmentProvider = new HeuristicEnrichmentProvider();
|
|
@@ -166,14 +169,14 @@ async function fetchHistoricalQueryRows(tables) {
|
|
|
166
169
|
program
|
|
167
170
|
.name("salesprompter")
|
|
168
171
|
.description("Sales workflow CLI for ICP definition, lead generation, enrichment, scoring, and sync.")
|
|
169
|
-
.version(
|
|
172
|
+
.version(packageVersion)
|
|
170
173
|
.option("--json", "Emit compact machine-readable JSON output", false)
|
|
171
174
|
.option("--quiet", "Suppress successful stdout output", false);
|
|
172
175
|
program
|
|
173
176
|
.command("auth:login")
|
|
174
|
-
.description("Authenticate CLI with Salesprompter app
|
|
177
|
+
.description("Authenticate CLI with a Salesprompter app token, or device flow if the app supports it.")
|
|
175
178
|
.option("--token <token>", "App-issued bearer token for direct login")
|
|
176
|
-
.option("--api-url <url>", "Salesprompter API base URL, defaults to SALESPROMPTER_API_BASE_URL or
|
|
179
|
+
.option("--api-url <url>", "Salesprompter API base URL, defaults to SALESPROMPTER_API_BASE_URL or salesprompter.ai")
|
|
177
180
|
.option("--timeout-seconds <number>", "Device flow wait timeout in seconds", "180")
|
|
178
181
|
.action(async (options) => {
|
|
179
182
|
const timeoutSeconds = z.coerce.number().int().min(30).max(1800).parse(options.timeoutSeconds);
|
|
@@ -190,7 +193,9 @@ program
|
|
|
190
193
|
return;
|
|
191
194
|
}
|
|
192
195
|
const startedAt = new Date().toISOString();
|
|
193
|
-
|
|
196
|
+
if (!runtimeOutputOptions.json && !runtimeOutputOptions.quiet) {
|
|
197
|
+
process.stderr.write("Starting device login flow. Complete login in the browser.\n");
|
|
198
|
+
}
|
|
194
199
|
const result = await loginWithDeviceFlow({
|
|
195
200
|
apiBaseUrl: options.apiUrl,
|
|
196
201
|
timeoutSeconds
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "salesprompter-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "CLI for defining ICPs, generating leads, enriching them, scoring them, and syncing to GTM tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsc -p tsconfig.json",
|
|
15
15
|
"check": "tsc --noEmit -p tsconfig.json",
|
|
16
|
+
"docs:dev": "npx mint dev",
|
|
17
|
+
"docs:broken-links": "npx mint broken-links",
|
|
18
|
+
"docs:a11y": "npx mint a11y",
|
|
16
19
|
"start": "node ./dist/cli.js",
|
|
17
20
|
"test": "npm run build && tsc -p tsconfig.test.json && node --test dist-tests/tests/**/*.test.js"
|
|
18
21
|
},
|