@letterstory/cli 0.177.5 → 0.177.7

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
@@ -87,7 +87,7 @@ import {
87
87
  import { fetchParkedSections, withoutParked } from "./parked.mjs";
88
88
 
89
89
  // Matches cli/package.json; publish-cli.yml rewrites both to the published version.
90
- export const VERSION = "0.177.5";
90
+ export const VERSION = "0.177.7";
91
91
 
92
92
  /** The exit code for a gate refusal (CARD_REQUIRED, PAYMENT_FAILED, OUT_OF_TOKENS): 1 is a plain error. */
93
93
  export const EXIT_PAYMENT_REQUIRED = 3;
@@ -1881,6 +1881,8 @@ The Site (one model of your whole marketing site, keyed by host and path):
1881
1881
  site highlight <domain> [--off] Highlight a competitor; its changes lead the top changes
1882
1882
  site prospect <url> [--pages <n>] [--max-pages <n>] [--depth <n>]
1883
1883
  Staff: any company's site, no account: what Fix would list, each PR
1884
+ site suggest <host> --idea <id> | --draft-id <id>... | --pattern <folder> | --item <id> --path <path>
1885
+ Open PR on a suggestion the Site stores, as one job
1884
1886
 
1885
1887
  Repo changes (Claude Code edits your repo in a sandbox; the Letter GitHub App opens a PR):
1886
1888
  repo repos [--gitlab [--search <text>] [--page n]] Repos the Letter GitHub App can reach (--gitlab: the GitLab
@@ -71,6 +71,8 @@ const ARGS = {
71
71
  recipe: "recipe",
72
72
  // Preserve the account-specific task selected by the Plan.
73
73
  fit_run: "fit-run",
74
+ // --plan-action <id>: a Plan row's account action started as an Idea (blog:post, outbound:campaign, …).
75
+ action: "plan-action",
74
76
  // --accepted-quote '<json>': the price the Ideas row showed, echoed to accept what it buys.
75
77
  accepted_quote: {
76
78
  value: (flags) => {
@@ -256,6 +258,7 @@ async function buildStart(ctx) {
256
258
  "subject",
257
259
  "recipe",
258
260
  "fit-run",
261
+ "plan-action",
259
262
  "accepted-quote",
260
263
  "action",
261
264
  "notify-slack",
@@ -15,12 +15,14 @@
15
15
  // site competitors → list_competitor_sites site watch-competitors [d] → watch_competitor_sites
16
16
  // site highlight <domain> [--off] → set_competitor_highlight
17
17
  // site prospect <url> → read_prospect_site (staff: any company's site, no account, nothing stored)
18
+ // site suggest <host> --idea <id> | --draft-id <id>… | --pattern <folder> | --item <id> --path <p> → start_suggestion
18
19
 
19
20
  import { writeFileSync } from "node:fs";
20
21
 
21
22
  import { CliError } from "../client.mjs";
22
23
  import {
23
24
  argsFromFlags,
25
+ flagCsv,
24
26
  flagList,
25
27
  flagNum,
26
28
  flagStr,
@@ -193,6 +195,14 @@ const ARGS = {
193
195
  decision: { flag: "decision", required: true, enum: ["accept", "dismiss"] },
194
196
  reason: "reason",
195
197
  },
198
+ start_suggestion: {
199
+ domain: { positional: 0, required: true, label: "host" },
200
+ idea_id: "idea",
201
+ draft_ids: { value: (flags) => (flagCsv(flags["draft-id"]).length ? flagCsv(flags["draft-id"]) : undefined) },
202
+ pattern_folder: "pattern",
203
+ observation_id: "item",
204
+ path: "path",
205
+ },
196
206
  fix_site_observations: {
197
207
  host: { positional: 0, required: true, label: "host" },
198
208
  // Every positional after the host, plus --observation <id> (repeatable).
@@ -264,9 +274,11 @@ export async function cmdSite(ctx) {
264
274
  return siteHighlight(rest);
265
275
  case "prospect":
266
276
  return siteProspect(rest);
277
+ case "suggest":
278
+ return siteSuggest(rest);
267
279
  default:
268
280
  throw new CliError(
269
- `Unknown site subcommand: ${sub ?? "(none)"}. Try: list, map, refresh, unmap, tree, builds, metrics, page, observations, observe, dismiss, families, decide-family, proposals, propose, decide, fix, competitors, watch-competitors, highlight, prospect`
281
+ `Unknown site subcommand: ${sub ?? "(none)"}. Try: list, map, refresh, unmap, tree, builds, metrics, page, observations, observe, dismiss, families, decide-family, proposals, propose, decide, fix, competitors, watch-competitors, highlight, prospect, suggest`
270
282
  );
271
283
  }
272
284
  }
@@ -396,6 +408,24 @@ async function siteMap(ctx) {
396
408
  return 0;
397
409
  }
398
410
 
411
+ /** A suggestion the Site stores, started as the Site's Open PR does: one job, its words read from what Letter stores. */
412
+ async function siteSuggest(ctx) {
413
+ const { client, flags, io } = ctx;
414
+ refuseUnknownFlags(ctx, ARGS.start_suggestion, ["idea", "draft-id", "pattern", "item", "path"]);
415
+ const args = argsFromFlags(ARGS.start_suggestion, flags, ctx.positionals);
416
+ const named = [args.idea_id, args.draft_ids, args.pattern_folder, args.observation_id].filter(Boolean).length;
417
+ if (named !== 1 || (args.observation_id && !args.path))
418
+ throw new CliError(
419
+ "Name one suggestion: site suggest <host> --idea <id> | --draft-id <id>… | --pattern <folder> | --item <id> --path <path>"
420
+ );
421
+ const result = await client.callTool("start_suggestion", args);
422
+ printResult(io, flags, result, (r) => {
423
+ if (r.status !== "started") return r.message ?? r.status;
424
+ return `Started: ${r.build.title} (${r.build.id})`;
425
+ });
426
+ return 0;
427
+ }
428
+
399
429
  /** Any company's site read as the Site and Fix read a customer's: what Fix would list, and each pull request. */
400
430
  async function siteProspect(ctx) {
401
431
  const { client, flags, io } = ctx;
@@ -78,6 +78,9 @@ export const ARGS = {
78
78
  },
79
79
  launch_variational_test: {
80
80
  brief: "brief",
81
+ // --block "<its words>" --after "<the challenger's>": test exactly these, with no model choosing.
82
+ block: "block",
83
+ after: "after",
81
84
  page_url: "page",
82
85
  site_id: "site",
83
86
  name: "name",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.177.5",
3
+ "version": "0.177.7",
4
4
  "description": "Spin up and manage Letter phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",