salesprompter-cli 0.1.69 → 0.1.70

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +90 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -109,7 +109,7 @@ salesprompter affiliate:grow \
109
109
  --send-from 09:00 \
110
110
  --send-to 16:00
111
111
 
112
- # Review the persisted sequence and enrichment summary, then activate explicitly
112
+ # Verify live campaign state, lead safety, and contact activity, then activate explicitly
113
113
  salesprompter affiliate:list
114
114
  salesprompter affiliate:status "$AFFILIATE_RUN_ID"
115
115
  salesprompter affiliate:analytics "$AFFILIATE_RUN_ID"
package/dist/cli.js CHANGED
@@ -247,6 +247,57 @@ const AffiliateOutreachResponseSchema = z.object({
247
247
  status: z.literal("ok"),
248
248
  outreach: AffiliateOutreachRunSchema
249
249
  });
250
+ const AffiliateOutreachHealthSchema = z.object({
251
+ checkedAt: DatabaseTimestampSchema,
252
+ liveChecked: z.boolean(),
253
+ done: z.boolean(),
254
+ verdict: z.enum([
255
+ "preparing",
256
+ "failed",
257
+ "unavailable",
258
+ "not_running",
259
+ "ready_to_activate",
260
+ "running",
261
+ "unsafe_running"
262
+ ]),
263
+ running: z.boolean(),
264
+ activationReady: z.boolean(),
265
+ safeToSend: z.boolean(),
266
+ dataPreparationComplete: z.boolean(),
267
+ campaign: z
268
+ .object({
269
+ id: z.string().min(1),
270
+ name: z.string().min(1).nullable(),
271
+ status: z.number().int().nullable(),
272
+ statusLabel: z.string().min(1),
273
+ dailyLimit: z.number().nonnegative().nullable(),
274
+ sendingAccountCount: z.number().int().nonnegative()
275
+ })
276
+ .nullable(),
277
+ leads: z
278
+ .object({
279
+ total: z.number().int().nonnegative(),
280
+ active: z.number().int().nonnegative(),
281
+ inactive: z.number().int().nonnegative(),
282
+ verified: z.number().int().nonnegative(),
283
+ pendingVerification: z.number().int().nonnegative(),
284
+ invalid: z.number().int().nonnegative(),
285
+ unsafe: z.number().int().nonnegative(),
286
+ contacted: z.number().int().nonnegative(),
287
+ replied: z.number().int().nonnegative(),
288
+ statusCounts: z.record(z.string(), z.number().int().nonnegative()),
289
+ verificationStatusCounts: z.record(z.string(), z.number().int().nonnegative())
290
+ })
291
+ .nullable(),
292
+ blockers: z.array(z.object({
293
+ code: z.string().min(1),
294
+ message: z.string().min(1),
295
+ count: z.number().int().nonnegative().optional()
296
+ }))
297
+ });
298
+ const AffiliateOutreachLiveStatusResponseSchema = AffiliateOutreachResponseSchema.extend({
299
+ health: AffiliateOutreachHealthSchema
300
+ });
250
301
  const AffiliateOutreachSummarySchema = AffiliateOutreachRunBaseSchema;
251
302
  const AffiliateAudienceSummarySchema = z.object({
252
303
  public_token: z.string().min(1),
@@ -6765,6 +6816,35 @@ async function getAffiliateOutreachViaApp(session, audienceRunId) {
6765
6816
  }), AffiliateOutreachResponseSchema);
6766
6817
  return value.outreach;
6767
6818
  }
6819
+ async function getAffiliateOutreachLiveStatusViaApp(session, audienceRunId) {
6820
+ const { value } = await fetchCliJson(session, (currentSession) => {
6821
+ const url = new URL(`/api/cli/affiliate-outreach/${encodeURIComponent(audienceRunId)}`, currentSession.apiBaseUrl);
6822
+ url.searchParams.set("live", "1");
6823
+ return fetch(url, {
6824
+ headers: {
6825
+ Authorization: `Bearer ${currentSession.accessToken}`
6826
+ }
6827
+ });
6828
+ }, AffiliateOutreachLiveStatusResponseSchema);
6829
+ return value;
6830
+ }
6831
+ function describeAffiliateOutreachHealth(health) {
6832
+ const leads = health.leads;
6833
+ if (health.done && leads) {
6834
+ return `Done: the campaign is running with ${leads.verified}/${leads.total} verified leads.`;
6835
+ }
6836
+ if (health.verdict === "unsafe_running" && leads) {
6837
+ return `Attention: the campaign is running with ${leads.unsafe} unsafe leads.`;
6838
+ }
6839
+ if (health.verdict === "ready_to_activate" && leads) {
6840
+ return `Ready to activate: ${leads.verified}/${leads.total} leads are verified.`;
6841
+ }
6842
+ if (health.liveChecked && leads) {
6843
+ const campaignState = health.campaign?.statusLabel ?? "unknown";
6844
+ return `Not done: the campaign is ${campaignState}; ${leads.verified}/${leads.total} leads are verified; ${leads.contacted} contacted.`;
6845
+ }
6846
+ return health.blockers[0]?.message ?? "Live campaign status could not be verified.";
6847
+ }
6768
6848
  async function getAffiliateOutreachAnalyticsViaApp(session, audienceRunId) {
6769
6849
  const { value } = await fetchCliJson(session, (currentSession) => fetch(`${currentSession.apiBaseUrl}/api/cli/affiliate-outreach/${encodeURIComponent(audienceRunId)}/analytics`, {
6770
6850
  headers: {
@@ -15108,11 +15188,18 @@ program
15108
15188
  });
15109
15189
  program
15110
15190
  .command("affiliate:status <run-id>")
15111
- .description("Show enrichment, sequence, Instantly, and activation status for an affiliate run.")
15191
+ .description("Verify whether an affiliate campaign is prepared, safe, and actually running.")
15112
15192
  .action(async (runId) => {
15113
15193
  const session = await requireAuthSession();
15114
- const outreach = await getAffiliateOutreachViaApp(session, z.string().uuid().parse(runId));
15115
- printOutput({ status: "ok", outreach });
15194
+ const result = await getAffiliateOutreachLiveStatusViaApp(session, z.string().uuid().parse(runId));
15195
+ printOutput({
15196
+ status: "ok",
15197
+ done: result.health.done,
15198
+ verdict: result.health.verdict,
15199
+ message: describeAffiliateOutreachHealth(result.health),
15200
+ health: result.health,
15201
+ outreach: result.outreach
15202
+ });
15116
15203
  });
15117
15204
  program
15118
15205
  .command("affiliate:analytics <run-id>")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "salesprompter-cli",
3
- "version": "0.1.69",
3
+ "version": "0.1.70",
4
4
  "description": "Sales workflow CLI for guided lead generation, enrichment, scoring, and sync.",
5
5
  "author": "Daniel Sinewe <hello@danielsinewe.com>",
6
6
  "type": "module",