salesprompter-cli 0.1.31 → 0.1.33
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/auth.js +8 -2
- package/dist/cli.js +285 -42
- package/package.json +1 -1
package/dist/auth.js
CHANGED
|
@@ -15,7 +15,9 @@ const UserSchema = z.object({
|
|
|
15
15
|
name: nullableOptionalString,
|
|
16
16
|
orgId: nullableOptionalString,
|
|
17
17
|
orgName: nullableOptionalString,
|
|
18
|
-
orgSlug: nullableOptionalString
|
|
18
|
+
orgSlug: nullableOptionalString,
|
|
19
|
+
workspaceClientId: nullableOptionalString,
|
|
20
|
+
workspaceClientName: nullableOptionalString
|
|
19
21
|
});
|
|
20
22
|
const AuthSessionSchema = z.object({
|
|
21
23
|
accessToken: z.string().min(1),
|
|
@@ -84,6 +86,8 @@ const WhoAmIResponseSchema = z
|
|
|
84
86
|
orgId: nullableOptionalString,
|
|
85
87
|
orgName: nullableOptionalString,
|
|
86
88
|
orgSlug: nullableOptionalString,
|
|
89
|
+
workspaceClientId: nullableOptionalString,
|
|
90
|
+
workspaceClientName: nullableOptionalString,
|
|
87
91
|
expiresAt: z.string().datetime().optional()
|
|
88
92
|
}),
|
|
89
93
|
z.object({
|
|
@@ -107,7 +111,9 @@ const WhoAmIResponseSchema = z
|
|
|
107
111
|
name: value.name,
|
|
108
112
|
orgId: value.orgId,
|
|
109
113
|
orgName: value.orgName,
|
|
110
|
-
orgSlug: value.orgSlug
|
|
114
|
+
orgSlug: value.orgSlug,
|
|
115
|
+
workspaceClientId: value.workspaceClientId,
|
|
116
|
+
workspaceClientName: value.workspaceClientName
|
|
111
117
|
},
|
|
112
118
|
expiresAt: value.expiresAt
|
|
113
119
|
};
|
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import { setTimeout as delay } from "node:timers/promises";
|
|
|
10
10
|
import { createClient } from "@supabase/supabase-js";
|
|
11
11
|
import { Command } from "commander";
|
|
12
12
|
import { z } from "zod";
|
|
13
|
-
import { clearAuthSession, loginWithBrowserConnect, loginWithDeviceFlow, loginWithToken, requireAuthSession, shouldBypassAuth, verifySession } from "./auth.js";
|
|
13
|
+
import { clearAuthSession, loginWithBrowserConnect, loginWithDeviceFlow, loginWithToken, requireAuthSession, shouldBypassAuth, verifySession, writeAuthSession } from "./auth.js";
|
|
14
14
|
import { buildBigQueryLeadLookupSql, executeBigQuerySql, normalizeBigQueryLeadRows, runBigQueryQuery, runBigQueryRows } from "./bigquery.js";
|
|
15
15
|
import { AccountProfileSchema, EnrichedLeadSchema, IcpSchema, LeadSchema, ScoredLeadSchema, SyncTargetSchema } from "./domain.js";
|
|
16
16
|
import { auditDomainDecisions, buildDomainfinderBacklogQueries, buildDomainfinderCandidatesSql, buildDomainfinderInputSql, buildDomainfinderWritebackSql, buildExistingDomainRepairSql, buildExistingDomainAuditQueries, compareDomainSelectionStrategies, selectBestDomains } from "./domainfinder.js";
|
|
@@ -311,6 +311,7 @@ const helpVisibleCommandNames = new Set([
|
|
|
311
311
|
"packs:add",
|
|
312
312
|
"upgrade",
|
|
313
313
|
"auth:login",
|
|
314
|
+
"auth:workspace",
|
|
314
315
|
"wizard",
|
|
315
316
|
"auth:whoami",
|
|
316
317
|
"llm:ready",
|
|
@@ -2545,11 +2546,13 @@ function compactOptionalText(value) {
|
|
|
2545
2546
|
return compacted && compacted.length > 0 ? compacted : null;
|
|
2546
2547
|
}
|
|
2547
2548
|
function getOrgLabel(session) {
|
|
2548
|
-
const orgName = compactOptionalText(session.user.orgName);
|
|
2549
|
+
const orgName = compactOptionalText(session.user.orgName) ?? compactOptionalText(session.user.workspaceClientName);
|
|
2549
2550
|
const orgSlug = compactOptionalText(session.user.orgSlug);
|
|
2550
2551
|
const orgId = compactOptionalText(session.user.orgId);
|
|
2552
|
+
const workspaceClientId = compactOptionalText(session.user.workspaceClientId);
|
|
2551
2553
|
if (orgName) {
|
|
2552
|
-
const
|
|
2554
|
+
const clientLabel = workspaceClientId ? `client ${workspaceClientId}` : null;
|
|
2555
|
+
const details = [orgSlug, clientLabel, orgId].filter((value) => Boolean(value));
|
|
2553
2556
|
return details.length > 0 ? `${orgName} (${details.join(", ")})` : orgName;
|
|
2554
2557
|
}
|
|
2555
2558
|
if (orgSlug) {
|
|
@@ -2784,7 +2787,9 @@ async function ensureWizardSession(options) {
|
|
|
2784
2787
|
};
|
|
2785
2788
|
}
|
|
2786
2789
|
try {
|
|
2787
|
-
const
|
|
2790
|
+
const cachedSession = await requireAuthSession();
|
|
2791
|
+
const session = await verifySession(cachedSession);
|
|
2792
|
+
await writeAuthSession(session);
|
|
2788
2793
|
writeSessionSummary(session);
|
|
2789
2794
|
writeWizardLine();
|
|
2790
2795
|
return {
|
|
@@ -2854,6 +2859,13 @@ async function confirmWizardWorkspace(rl, session, options) {
|
|
|
2854
2859
|
writeWizardLine();
|
|
2855
2860
|
return result.session;
|
|
2856
2861
|
}
|
|
2862
|
+
async function switchWorkspaceWithBrowser(options) {
|
|
2863
|
+
await clearAuthSession();
|
|
2864
|
+
return (await performLogin({
|
|
2865
|
+
apiUrl: options?.apiUrl,
|
|
2866
|
+
timeoutSeconds: options?.timeoutSeconds ?? 180
|
|
2867
|
+
})).session;
|
|
2868
|
+
}
|
|
2857
2869
|
async function resolveLlmAuthReadiness() {
|
|
2858
2870
|
const apiBaseUrl = process.env.SALESPROMPTER_API_BASE_URL?.trim() || "https://salesprompter.ai";
|
|
2859
2871
|
const envToken = resolveNonInteractiveAuthToken(process.env);
|
|
@@ -2938,6 +2950,19 @@ function buildSalesNavigatorCrawlLogPath(input) {
|
|
|
2938
2950
|
const slug = slugify(input) || "salesnav-crawl";
|
|
2939
2951
|
return `./data/${slug}-crawl.log.jsonl`;
|
|
2940
2952
|
}
|
|
2953
|
+
function buildSalesNavigatorCrawlOutputPath(input) {
|
|
2954
|
+
const slug = slugify(input) || "salesnav-crawl";
|
|
2955
|
+
return `./data/${slug}-crawl.json`;
|
|
2956
|
+
}
|
|
2957
|
+
function isSalesNavigatorPeopleSearchUrl(input) {
|
|
2958
|
+
try {
|
|
2959
|
+
const parsed = new URL(input);
|
|
2960
|
+
return /(^|\.)linkedin\.com$/i.test(parsed.hostname) && parsed.pathname.replace(/\/+$/, "") === "/sales/search/people";
|
|
2961
|
+
}
|
|
2962
|
+
catch {
|
|
2963
|
+
return false;
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2941
2966
|
function decodeSalesNavigatorQueryParam(url) {
|
|
2942
2967
|
try {
|
|
2943
2968
|
const encoded = new URL(url).searchParams.get("query");
|
|
@@ -5031,11 +5056,192 @@ async function searchTargetCompanyLeads(reference, limit) {
|
|
|
5031
5056
|
limit
|
|
5032
5057
|
});
|
|
5033
5058
|
}
|
|
5059
|
+
async function runDirectSalesNavigatorSearchWizard(input) {
|
|
5060
|
+
const maxResultsPerSearch = 2500;
|
|
5061
|
+
const numberOfProfiles = 2500;
|
|
5062
|
+
const slicePreset = "wizard-salesnav-search";
|
|
5063
|
+
const maxSplitDepth = DEFAULT_SALES_NAVIGATOR_CRAWL_DIMENSIONS.length;
|
|
5064
|
+
const maxSlices = 1000;
|
|
5065
|
+
const maxRetries = 3;
|
|
5066
|
+
const probeProfiles = 100;
|
|
5067
|
+
const agentBusyWaitSeconds = 30;
|
|
5068
|
+
const agentBusyMaxWaits = 20;
|
|
5069
|
+
const idlePollSeconds = 10;
|
|
5070
|
+
const idleMaxPolls = 180;
|
|
5071
|
+
const parallelExports = 3;
|
|
5072
|
+
const outPath = buildSalesNavigatorCrawlOutputPath(input);
|
|
5073
|
+
const dryRun = shouldBypassAuth();
|
|
5074
|
+
const logger = await createWorkflowLogger({
|
|
5075
|
+
logPath: buildSalesNavigatorCrawlLogPath(input)
|
|
5076
|
+
});
|
|
5077
|
+
writeWizardLine("Detected a Sales Navigator people search. I will process this search directly.");
|
|
5078
|
+
if (dryRun) {
|
|
5079
|
+
writeWizardLine("Auth bypass is enabled, so I will preview the crawl plan instead of launching it.");
|
|
5080
|
+
}
|
|
5081
|
+
writeWizardLine();
|
|
5082
|
+
await logger.log("salesnav.crawl.command.started", {
|
|
5083
|
+
queryUrl: input,
|
|
5084
|
+
jobId: null,
|
|
5085
|
+
maxResultsPerSearch,
|
|
5086
|
+
numberOfProfiles,
|
|
5087
|
+
slicePreset,
|
|
5088
|
+
maxSplitDepth,
|
|
5089
|
+
maxSlices,
|
|
5090
|
+
maxRetries,
|
|
5091
|
+
probeProfiles,
|
|
5092
|
+
agentBusyWaitSeconds,
|
|
5093
|
+
agentBusyMaxWaits,
|
|
5094
|
+
idlePollSeconds,
|
|
5095
|
+
idleMaxPolls,
|
|
5096
|
+
parallelExports,
|
|
5097
|
+
dryRun
|
|
5098
|
+
});
|
|
5099
|
+
if (dryRun) {
|
|
5100
|
+
const preview = buildSalesNavigatorCrawlPreview({
|
|
5101
|
+
sourceQueryUrl: input,
|
|
5102
|
+
maxResultsPerSearch,
|
|
5103
|
+
numberOfProfiles,
|
|
5104
|
+
slicePreset
|
|
5105
|
+
});
|
|
5106
|
+
const payload = {
|
|
5107
|
+
status: "ok",
|
|
5108
|
+
dryRun: true,
|
|
5109
|
+
mode: "adaptive",
|
|
5110
|
+
traceId: logger.traceId,
|
|
5111
|
+
logPath: logger.logPath,
|
|
5112
|
+
sourceQueryUrl: input,
|
|
5113
|
+
rootQueryUrl: preview.root.slicedQueryUrl,
|
|
5114
|
+
rootAppliedFilters: preview.root.appliedFilters,
|
|
5115
|
+
dimensionOrder: preview.dimensions.map((dimension) => ({
|
|
5116
|
+
key: dimension.key,
|
|
5117
|
+
filterType: dimension.filterType,
|
|
5118
|
+
valueCount: dimension.values.length
|
|
5119
|
+
})),
|
|
5120
|
+
firstSplitQueries: preview.firstSplit.map((attempt) => ({
|
|
5121
|
+
slicedQueryUrl: attempt.slicedQueryUrl,
|
|
5122
|
+
appliedFilters: attempt.appliedFilters,
|
|
5123
|
+
splitTrail: attempt.splitTrail.map((entry) => ({
|
|
5124
|
+
key: entry.key,
|
|
5125
|
+
filterType: entry.filterType,
|
|
5126
|
+
valueText: entry.value.text
|
|
5127
|
+
}))
|
|
5128
|
+
}))
|
|
5129
|
+
};
|
|
5130
|
+
await logger.log("salesnav.crawl.dry-run.preview", {
|
|
5131
|
+
sourceQueryUrl: input,
|
|
5132
|
+
root: summarizeSalesNavigatorQuery(payload.rootQueryUrl, payload.rootAppliedFilters),
|
|
5133
|
+
dimensionOrder: payload.dimensionOrder,
|
|
5134
|
+
firstSplitQueries: payload.firstSplitQueries.map((attempt) => ({
|
|
5135
|
+
splitTrail: attempt.splitTrail,
|
|
5136
|
+
...summarizeSalesNavigatorQuery(attempt.slicedQueryUrl, attempt.appliedFilters)
|
|
5137
|
+
}))
|
|
5138
|
+
});
|
|
5139
|
+
await writeJsonFile(outPath, payload);
|
|
5140
|
+
writeWizardLine(`Saved Sales Navigator crawl preview to ${outPath}.`);
|
|
5141
|
+
writeWizardLine(`Saved logs to ${logger.logPath}.`);
|
|
5142
|
+
return;
|
|
5143
|
+
}
|
|
5144
|
+
let session = await requireAuthSession();
|
|
5145
|
+
const sessionOrgId = resolveSessionOrgId(session);
|
|
5146
|
+
if (sessionOrgId) {
|
|
5147
|
+
logger.setEventStore(await createSalesNavigatorCrawlEventStore({ orgId: sessionOrgId }));
|
|
5148
|
+
}
|
|
5149
|
+
const seed = createSalesNavigatorCrawlSeed({
|
|
5150
|
+
sourceQueryUrl: input,
|
|
5151
|
+
maxResultsPerSearch,
|
|
5152
|
+
numberOfProfiles,
|
|
5153
|
+
slicePreset
|
|
5154
|
+
});
|
|
5155
|
+
const created = await createOrResumeSalesNavigatorCrawlJob(session, {
|
|
5156
|
+
sourceQueryUrl: input,
|
|
5157
|
+
slicePreset,
|
|
5158
|
+
maxResultsPerSearch,
|
|
5159
|
+
numberOfProfiles,
|
|
5160
|
+
rawPayload: {
|
|
5161
|
+
workflow: "wizard:salesnav-search",
|
|
5162
|
+
traceId: logger.traceId,
|
|
5163
|
+
command: {
|
|
5164
|
+
sourceQueryUrl: input,
|
|
5165
|
+
slicePreset,
|
|
5166
|
+
maxResultsPerSearch,
|
|
5167
|
+
numberOfProfiles,
|
|
5168
|
+
maxSplitDepth,
|
|
5169
|
+
maxSlices,
|
|
5170
|
+
maxRetries,
|
|
5171
|
+
probeProfiles,
|
|
5172
|
+
agentBusyWaitSeconds,
|
|
5173
|
+
agentBusyMaxWaits,
|
|
5174
|
+
idlePollSeconds,
|
|
5175
|
+
idleMaxPolls,
|
|
5176
|
+
parallelExports
|
|
5177
|
+
}
|
|
5178
|
+
},
|
|
5179
|
+
rootSlice: {
|
|
5180
|
+
slicedQueryUrl: seed.slicedQueryUrl,
|
|
5181
|
+
appliedFilters: seed.appliedFilters,
|
|
5182
|
+
depth: seed.depth,
|
|
5183
|
+
splitTrail: seed.splitTrail,
|
|
5184
|
+
rawPayload: {
|
|
5185
|
+
workflow: "wizard:salesnav-search",
|
|
5186
|
+
traceId: logger.traceId
|
|
5187
|
+
}
|
|
5188
|
+
}
|
|
5189
|
+
}, logger.traceId);
|
|
5190
|
+
session = created.session;
|
|
5191
|
+
const jobId = created.value.job.id;
|
|
5192
|
+
writeWizardLine(`${created.value.resumed ? "Resumed" : "Started"} Sales Navigator crawl ${jobId}. Processing the search now...`);
|
|
5193
|
+
const crawl = await executeSalesNavigatorCrawlJob(session, jobId, {
|
|
5194
|
+
maxSplitDepth,
|
|
5195
|
+
maxSlices,
|
|
5196
|
+
maxRetries,
|
|
5197
|
+
probeProfiles,
|
|
5198
|
+
agentBusyWaitSeconds,
|
|
5199
|
+
agentBusyMaxWaits,
|
|
5200
|
+
idlePollSeconds,
|
|
5201
|
+
idleMaxPolls,
|
|
5202
|
+
parallelExports,
|
|
5203
|
+
traceId: logger.traceId,
|
|
5204
|
+
logger
|
|
5205
|
+
});
|
|
5206
|
+
const payload = {
|
|
5207
|
+
status: "ok",
|
|
5208
|
+
dryRun: false,
|
|
5209
|
+
mode: "durable",
|
|
5210
|
+
traceId: logger.traceId,
|
|
5211
|
+
logPath: logger.logPath,
|
|
5212
|
+
jobId,
|
|
5213
|
+
resumed: created.value.resumed,
|
|
5214
|
+
sourceQueryUrl: crawl.job.sourceQueryUrl,
|
|
5215
|
+
slicePreset: crawl.job.slicePreset,
|
|
5216
|
+
maxResultsPerSearch: crawl.job.maxResultsPerSearch,
|
|
5217
|
+
numberOfProfiles: crawl.job.numberOfProfiles,
|
|
5218
|
+
claimedSlices: crawl.claimedSlices,
|
|
5219
|
+
truncated: crawl.truncated,
|
|
5220
|
+
job: crawl.job,
|
|
5221
|
+
lastOutcome: crawl.lastOutcome
|
|
5222
|
+
};
|
|
5223
|
+
await writeJsonFile(outPath, payload);
|
|
5224
|
+
writeWizardLine(`Sales Navigator crawl status: ${crawl.job.status}.`);
|
|
5225
|
+
writeWizardLine(`Imported ${crawl.job.importedPeople} people across ${crawl.job.exportedSlices} exported slice${crawl.job.exportedSlices === 1 ? "" : "s"}.`);
|
|
5226
|
+
if (crawl.job.failedSlices > 0 || crawl.truncated) {
|
|
5227
|
+
writeWizardLine(`Some work still needs attention: ${crawl.job.failedSlices} failed slice${crawl.job.failedSlices === 1 ? "" : "s"}, truncated=${crawl.truncated}.`);
|
|
5228
|
+
}
|
|
5229
|
+
writeWizardLine(`Saved crawl summary to ${outPath}.`);
|
|
5230
|
+
writeWizardLine(`Saved logs to ${logger.logPath}.`);
|
|
5231
|
+
writeWizardLine();
|
|
5232
|
+
writeWizardLine("Equivalent raw command:");
|
|
5233
|
+
writeWizardLine(` ${buildCommandLine(["salesprompter", "salesnav:crawl", "--query-url", input])}`);
|
|
5234
|
+
}
|
|
5034
5235
|
async function runProductMarketWizard(rl) {
|
|
5035
5236
|
writeWizardSection("Find leads from a product market", "Start from a company website, LinkedIn company page, product page, or category page. I will turn that into intended job titles and durable Sales Navigator crawls.");
|
|
5036
5237
|
const input = await promptText(rl, "What company website or LinkedIn page should I start from?", {
|
|
5037
5238
|
required: true
|
|
5038
5239
|
});
|
|
5240
|
+
if (isSalesNavigatorPeopleSearchUrl(input)) {
|
|
5241
|
+
writeWizardLine();
|
|
5242
|
+
await runDirectSalesNavigatorSearchWizard(input);
|
|
5243
|
+
return;
|
|
5244
|
+
}
|
|
5039
5245
|
const productLimit = z.coerce.number().int().min(1).max(5000).parse(await promptText(rl, "How many products should I inspect?", { defaultValue: "25", required: true }));
|
|
5040
5246
|
const titleLimit = z.coerce.number().int().min(1).max(1000).parse(await promptText(rl, "How many job titles should I turn into Sales Navigator crawls?", {
|
|
5041
5247
|
defaultValue: "5",
|
|
@@ -5233,7 +5439,7 @@ async function runWizard(options) {
|
|
|
5233
5439
|
throw new Error("wizard does not support --json or --quiet.");
|
|
5234
5440
|
}
|
|
5235
5441
|
writeWizardLine("Salesprompter");
|
|
5236
|
-
writeWizardLine("Start with a company website, LinkedIn product page, or
|
|
5442
|
+
writeWizardLine("Start with a company website, LinkedIn product page, category URL, or Sales Navigator search. I will guide you from there.");
|
|
5237
5443
|
writeWizardLine();
|
|
5238
5444
|
const rl = createInterface({
|
|
5239
5445
|
input: process.stdin,
|
|
@@ -5244,46 +5450,63 @@ async function runWizard(options) {
|
|
|
5244
5450
|
if (wizardSession.session && wizardSession.restoredFromCache) {
|
|
5245
5451
|
await confirmWizardWorkspace(rl, wizardSession.session, options);
|
|
5246
5452
|
}
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5453
|
+
for (;;) {
|
|
5454
|
+
const flow = await promptChoice(rl, "What do you want help with?", [
|
|
5455
|
+
{
|
|
5456
|
+
value: "product-market",
|
|
5457
|
+
label: "Find leads from a product market",
|
|
5458
|
+
description: "Start from a company, product, or LinkedIn category and crawl Sales Navigator",
|
|
5459
|
+
aliases: ["product market", "linkedin products", "category", "sales navigator", "crawl"]
|
|
5460
|
+
},
|
|
5461
|
+
{
|
|
5462
|
+
value: "reference-company",
|
|
5463
|
+
label: "Use a built-in vendor shortcut",
|
|
5464
|
+
description: "Generate the saved vendor ICP and search workspace leads",
|
|
5465
|
+
aliases: ["vendor", "shortcut", "vendor template", "quick template"]
|
|
5466
|
+
},
|
|
5467
|
+
{
|
|
5468
|
+
value: "target-company",
|
|
5469
|
+
label: "Find people at a specific company",
|
|
5470
|
+
description: "Example: find people at company.com",
|
|
5471
|
+
aliases: ["target company", "company", "find people", "people at a company", "lead generation"]
|
|
5472
|
+
},
|
|
5473
|
+
{
|
|
5474
|
+
value: "switch-workspace",
|
|
5475
|
+
label: "Switch workspace",
|
|
5476
|
+
description: "Choose Gojiberry, SelectLine, or another Salesprompter workspace",
|
|
5477
|
+
aliases: ["switch workspace", "change workspace", "gojiberry", "organization", "org"]
|
|
5478
|
+
},
|
|
5479
|
+
{
|
|
5480
|
+
value: "outreach-sync",
|
|
5481
|
+
label: "Push qualified leads to Instantly",
|
|
5482
|
+
description: "Use a saved leads file to fill an Instantly campaign",
|
|
5483
|
+
aliases: ["instantly", "outreach", "send leads", "campaign"]
|
|
5484
|
+
}
|
|
5485
|
+
], "product-market");
|
|
5486
|
+
writeWizardLine();
|
|
5487
|
+
if (flow === "switch-workspace") {
|
|
5488
|
+
writeWizardLine("Choose the workspace for this CLI session in the browser.");
|
|
5489
|
+
writeWizardLine();
|
|
5490
|
+
const session = await switchWorkspaceWithBrowser(options);
|
|
5491
|
+
writeSessionSummary(session);
|
|
5492
|
+
writeWizardLine();
|
|
5493
|
+
continue;
|
|
5271
5494
|
}
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5495
|
+
if (flow === "product-market") {
|
|
5496
|
+
await runProductMarketWizard(rl);
|
|
5497
|
+
return;
|
|
5498
|
+
}
|
|
5499
|
+
if (flow === "reference-company") {
|
|
5500
|
+
await runVendorShortcutWizard(rl);
|
|
5501
|
+
return;
|
|
5502
|
+
}
|
|
5503
|
+
if (flow === "target-company") {
|
|
5504
|
+
await runTargetCompanyWizard(rl);
|
|
5505
|
+
return;
|
|
5506
|
+
}
|
|
5507
|
+
await runOutreachSyncWizard(rl);
|
|
5284
5508
|
return;
|
|
5285
5509
|
}
|
|
5286
|
-
await runOutreachSyncWizard(rl);
|
|
5287
5510
|
}
|
|
5288
5511
|
finally {
|
|
5289
5512
|
rl.close();
|
|
@@ -5601,6 +5824,26 @@ program
|
|
|
5601
5824
|
expiresAt: result.session.expiresAt ?? null
|
|
5602
5825
|
});
|
|
5603
5826
|
});
|
|
5827
|
+
program
|
|
5828
|
+
.command("auth:workspace")
|
|
5829
|
+
.alias("auth:switch")
|
|
5830
|
+
.description("Switch the active Salesprompter workspace for this CLI session.")
|
|
5831
|
+
.option("--api-url <url>", "Salesprompter API base URL, defaults to SALESPROMPTER_API_BASE_URL or salesprompter.ai")
|
|
5832
|
+
.option("--timeout-seconds <number>", "Browser login timeout in seconds", "180")
|
|
5833
|
+
.action(async (options) => {
|
|
5834
|
+
const timeoutSeconds = z.coerce.number().int().min(30).max(1800).parse(options.timeoutSeconds);
|
|
5835
|
+
const session = await switchWorkspaceWithBrowser({
|
|
5836
|
+
apiUrl: options.apiUrl,
|
|
5837
|
+
timeoutSeconds
|
|
5838
|
+
});
|
|
5839
|
+
printOutput({
|
|
5840
|
+
status: "ok",
|
|
5841
|
+
method: "browser",
|
|
5842
|
+
apiBaseUrl: session.apiBaseUrl,
|
|
5843
|
+
user: session.user,
|
|
5844
|
+
expiresAt: session.expiresAt ?? null
|
|
5845
|
+
});
|
|
5846
|
+
});
|
|
5604
5847
|
program
|
|
5605
5848
|
.command("wizard")
|
|
5606
5849
|
.alias("start")
|
package/package.json
CHANGED