@letterstory/cli 0.177.18 → 0.177.20

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
@@ -88,7 +88,7 @@ import {
88
88
  import { fetchParkedSections, withoutParked } from "./parked.mjs";
89
89
 
90
90
  // Matches cli/package.json; publish-cli.yml rewrites both to the published version.
91
- export const VERSION = "0.177.18";
91
+ export const VERSION = "0.177.20";
92
92
 
93
93
  /** The exit code for a gate refusal (CARD_REQUIRED, PAYMENT_FAILED, OUT_OF_TOKENS): 1 is a plain error. */
94
94
  export const EXIT_PAYMENT_REQUIRED = 3;
@@ -1926,13 +1926,14 @@ Repo changes (Claude Code edits your repo in a sandbox; the Letter GitHub App op
1926
1926
  repo settings [--action build|build_pr|build_merge|slack|linear] [--branch <name>|none] [--slack-agent <name|U…>|none]
1927
1927
  [--slack-channel <C…>|none] [--autopilot-channel <C…>|none] [--listen <C…,C…>|none] [--autopilot on|off] [--autopilot-weekly <1-20>]
1928
1928
  [--autopilot-severity critical|warning] [--autopilot-scope all|new]
1929
- [--auto-merge 1h|12h|24h|3d|off] [--editor-auto-merge on|off]
1929
+ [--auto-merge 1h|12h|24h|3d|off] [--editor-auto-merge on|off] [--address-reviews on|off]
1930
1930
  [--agent letterpress-1|claude-code|default]
1931
1931
  The org's defaults for every fix: build (preview first),
1932
1932
  build_pr, or slack (post it to --slack-channel for your
1933
1933
  own agent, tagging --slack-agent), and the branch changes go to;
1934
1934
  --auto-merge merges Letter's PRs once open that long;
1935
1935
  --editor-auto-merge merges Letter Edit's (⌘L) changes once ready;
1936
+ --address-reviews answers review comments on Letter's PRs;
1936
1937
  --agent is who builds every change, on every door.
1937
1938
  What Letter posts to Slack on its own is an automation:
1938
1939
  automate add --template … --slack-channel <C…>
@@ -1987,6 +1988,7 @@ Repo changes (Claude Code edits your repo in a sandbox; the Letter GitHub App op
1987
1988
  Ask for more on a preview (it takes over the preview's link) or an
1988
1989
  open PR (one more commit); copy edits: JSON [{ path, before, after }];
1989
1990
  files as repo start takes them (--attach-ref: read, never committed)
1991
+ repo address-reviews <run-id> Answer the review comments on its open PR, once: fix, reply, resolve
1990
1992
  repo cancel <run-id> [--force] Stop it and delete the sandbox; no PR (Discard a preview)
1991
1993
 
1992
1994
  Feedback (tell us what's broken, missing, unclear, or wanted):
@@ -8,6 +8,7 @@
8
8
  // repo merge → merge_repo_change (merge its open PR, as a squash)
9
9
  // repo retry → retry_repo_change (try a failed change again: same ask, fresh run)
10
10
  // repo revise → revise_repo_change (ask for more on a preview or an open PR; --copy-edits-file for exact copy)
11
+ // repo address-reviews → address_pr_review (answer the review comments on its open PR: fix, reply, resolve)
11
12
  // repo say → send_repo_change_message (steer a build while its agent works)
12
13
  // repo repos → list_github_app_repos repo branches → list_repo_branches
13
14
  // repo connect → connect_github (the link a person opens to connect GitHub)
@@ -258,6 +259,13 @@ const ARGS = {
258
259
  ? undefined
259
260
  : ["on", "true", "1"].includes(String(flags["editor-auto-merge"])),
260
261
  },
262
+ // --address-reviews on|off: Letter answers the review comments on the PRs it opens
263
+ address_reviews: {
264
+ value: (flags) =>
265
+ flags["address-reviews"] === undefined
266
+ ? undefined
267
+ : ["on", "true", "1"].includes(String(flags["address-reviews"])),
268
+ },
261
269
  },
262
270
  get_repo_change: { run_id: { positional: 0, required: true, label: "run-id" } },
263
271
  get_repo_change_activity: {
@@ -285,6 +293,7 @@ const ARGS = {
285
293
  copy_edits: { value: (flags) => copyEdits(flags) },
286
294
  files: { value: (_flags, _positionals, extra) => (extra.files?.length ? extra.files : undefined) },
287
295
  },
296
+ address_pr_review: { run_id: { positional: 0, required: true, label: "run-id" } },
288
297
  list_repo_changes: {
289
298
  status: { flag: "status", enum: ["running", "succeeded", "no_changes", "failed", "cancelled", "sent"] },
290
299
  limit: { flag: "limit", type: "num" },
@@ -402,6 +411,8 @@ export async function cmdRepo(ctx) {
402
411
  return repoRetry(rest);
403
412
  case "revise":
404
413
  return repoRevise(rest);
414
+ case "address-reviews":
415
+ return repoAddressReviews(rest);
405
416
  case "say":
406
417
  return repoSay(rest);
407
418
  case "repos":
@@ -424,7 +435,7 @@ export async function cmdRepo(ctx) {
424
435
  return repoSlackTest(rest);
425
436
  default:
426
437
  throw new CliError(
427
- `Unknown repo subcommand: ${sub ?? "(none)"}. Try: start, fix-audit, install-letterprove, install-visitors, sites, set-site, reset-site, secrets, set-secret, delete-secret, status, list, publish, merge, retry, revise, say, cancel, repos, branches, prs, settings, suggestions, slack-targets, slack-test, connect, disconnect`
438
+ `Unknown repo subcommand: ${sub ?? "(none)"}. Try: start, fix-audit, install-letterprove, install-visitors, sites, set-site, reset-site, secrets, set-secret, delete-secret, status, list, publish, merge, retry, revise, address-reviews, say, cancel, repos, branches, prs, settings, suggestions, slack-targets, slack-test, connect, disconnect`
428
439
  );
429
440
  }
430
441
  }
@@ -848,6 +859,18 @@ async function repoRevise(ctx) {
848
859
  return 0;
849
860
  }
850
861
 
862
+ /** `repo address-reviews <run-id>`: answer the unresolved review comments on the change's open PR, once, now. */
863
+ async function repoAddressReviews(ctx) {
864
+ const { client, flags, io } = ctx;
865
+ const result = await client.callTool(
866
+ "address_pr_review",
867
+ argsFromFlags(ARGS.address_pr_review, flags, ctx.positionals)
868
+ );
869
+ ok(ctx, result.message);
870
+ printResult(io, flags, result.run ?? result, result.run ? describe : undefined);
871
+ return 0;
872
+ }
873
+
851
874
  async function repoRepos(ctx) {
852
875
  const { client, flags, io } = ctx;
853
876
  if (flags.gitlab) {
@@ -940,6 +963,7 @@ async function repoSettings(ctx) {
940
963
  "autopilot-scope",
941
964
  "auto-merge",
942
965
  "editor-auto-merge",
966
+ "address-reviews",
943
967
  "agent",
944
968
  ];
945
969
  refuseUnknownFlags(ctx, {}, settingFlags);
@@ -15,7 +15,8 @@
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
+ // site suggest <host> --idea <id> | --draft-id <id>… | --pattern <folder> | --item <id> --path <p>
19
+ // | --new-page <folder> --words "<what the page is>" → start_suggestion
19
20
 
20
21
  import { writeFileSync } from "node:fs";
21
22
 
@@ -202,6 +203,13 @@ const ARGS = {
202
203
  pattern_folder: "pattern",
203
204
  observation_id: "item",
204
205
  path: "path",
206
+ new_page: {
207
+ value: (flags) => {
208
+ const folder = flags["new-page"];
209
+ const words = flags.words;
210
+ return folder ? { folder: String(folder), words: String(words ?? "") } : undefined;
211
+ },
212
+ },
205
213
  },
206
214
  fix_site_observations: {
207
215
  host: { positional: 0, required: true, label: "host" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.177.18",
3
+ "version": "0.177.20",
4
4
  "description": "Spin up and manage Letter phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",