@letterstory/cli 0.30.1 → 0.31.1

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/lib/cli.mjs CHANGED
@@ -44,7 +44,7 @@ import {
44
44
  } from "./commands.mjs";
45
45
 
46
46
  // Keep in sync with cli/package.json.
47
- export const VERSION = "0.30.1";
47
+ export const VERSION = "0.31.1";
48
48
 
49
49
  // Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
50
50
  // can't accidentally swallow the id as --json's value.
@@ -571,6 +571,7 @@ Ledes (opening lines for cold email, chosen per prospect from a hand-approved li
571
571
  arrive in time (fewer lines may qualify).
572
572
  lede runs [--endpoint <id>] [--limit <n>] Recent lede calls (telemetry), newest first
573
573
  lede history [<domain>] [--days <n>] [--limit <n>] Openers already sent to an account
574
+ lede evals [--sweep] Lede quality evals still above zero
574
575
  lede balance Ledes left on this org
575
576
 
576
577
  Landings (a link + context; auto-mentioned in articles by collections you enable):
@@ -64,6 +64,10 @@ export const ARGS = {
64
64
  endpoint_id: "endpoint",
65
65
  limit: { flag: "limit", type: "num" },
66
66
  },
67
+ // The state of the quality exercise: which evals still count above zero.
68
+ lede_eval_briefing: {
69
+ sweep: { value: (flags) => (flags.sweep === true ? true : undefined) },
70
+ },
67
71
  // What has already been said to an account, so the next send does not repeat it.
68
72
  lede_account_history: {
69
73
  domain: { positional: 0, label: "domain" },
@@ -71,6 +75,22 @@ export const ARGS = {
71
75
  days: { flag: "days", type: "num" },
72
76
  limit: { flag: "limit", type: "num" },
73
77
  },
78
+ // What actually happened to a lede after you sent it. The engine can measure
79
+ // everything up to handing the line over and nothing after, so this is the only
80
+ // path by which a send, a reply or a bad observation ever reaches it.
81
+ report_lede_outcome: {
82
+ run_id: { positional: 0, label: "run-id", required: true },
83
+ shipped_template_id: { flag: "shipped-template" },
84
+ sent: { value: (flags) => (flags.sent === true ? true : undefined) },
85
+ replied: { value: (flags) => (flags.replied === true ? true : undefined) },
86
+ reply_sentiment: { flag: "sentiment", enum: ["positive", "neutral", "negative"] },
87
+ flagged_wrong: { value: (flags) => (flags["flag-wrong"] === true ? true : undefined) },
88
+ flagged_reason: { flag: "reason" },
89
+ },
90
+ // Per line: picked, sent, replied, positive, flagged wrong.
91
+ lede_line_funnel: {
92
+ window_days: { flag: "days", type: "num" },
93
+ },
74
94
  list_lede_endpoints: {},
75
95
  get_lede_balance: {},
76
96
  create_lede_endpoint: {
@@ -113,15 +133,39 @@ export async function cmdLede(ctx) {
113
133
  case "history":
114
134
  case "sent":
115
135
  return ledeHistory(rest);
136
+ case "evals":
137
+ case "briefing":
138
+ return ledeEvals(rest);
116
139
  case "balance":
117
140
  return ledeBalance(rest);
141
+ case "outcome":
142
+ case "report":
143
+ return ledeOutcome(rest);
144
+ case "funnel":
145
+ return ledeFunnel(rest);
118
146
  default:
119
147
  throw new CliError(
120
- `Unknown lede subcommand: ${sub ?? "(none)"}. Try: list, create, delete, endpoint, run, runs, history, balance`
148
+ `Unknown lede subcommand: ${sub ?? "(none)"}. Try: list, create, delete, endpoint, run, runs, history, evals, balance, outcome, funnel`
121
149
  );
122
150
  }
123
151
  }
124
152
 
153
+ async function ledeOutcome(ctx) {
154
+ const { client, flags, positionals, io } = ctx;
155
+ const args = argsFromFlags(ARGS.report_lede_outcome, flags, positionals);
156
+ const result = await client.callTool("report_lede_outcome", args);
157
+ ok(ctx, `Recorded the outcome for run ${args.run_id}.`);
158
+ printResult(io, flags, result);
159
+ return 0;
160
+ }
161
+
162
+ async function ledeFunnel(ctx) {
163
+ const { client, flags, io } = ctx;
164
+ const result = await client.callTool("lede_line_funnel", argsFromFlags(ARGS.lede_line_funnel, flags));
165
+ printResult(io, flags, result);
166
+ return 0;
167
+ }
168
+
125
169
  async function ledeList(ctx) {
126
170
  const { client, flags, io } = ctx;
127
171
  const result = await client.callTool("list_lede_endpoints", argsFromFlags(ARGS.list_lede_endpoints, flags));
@@ -241,6 +285,15 @@ async function ledeHistory(ctx) {
241
285
  return 0;
242
286
  }
243
287
 
288
+ // `lede evals [--sweep]` — which categories of false positive still count above zero.
289
+ // The exercise is finished when total_hits reads zero and no new flags are arriving.
290
+ async function ledeEvals(ctx) {
291
+ const { client, flags, io } = ctx;
292
+ const result = await client.callTool("lede_eval_briefing", argsFromFlags(ARGS.lede_eval_briefing, flags));
293
+ printResult(io, flags, result);
294
+ return 0;
295
+ }
296
+
244
297
  async function ledeBalance(ctx) {
245
298
  const { client, flags, io } = ctx;
246
299
  const result = await client.callTool("get_lede_balance", argsFromFlags(ARGS.get_lede_balance, flags));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.30.1",
3
+ "version": "0.31.1",
4
4
  "description": "Spin up and manage Letterstory phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",