@letterstory/cli 0.177.28 → 0.177.30

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.28";
91
+ export const VERSION = "0.177.30";
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;
@@ -242,6 +242,7 @@ export const BOOLEAN_FLAGS = new Set([
242
242
  "more",
243
243
  "preview",
244
244
  "keep-preview",
245
+ "sample-banner",
245
246
  "with-preview",
246
247
  // repo …: the repo is a GitLab project (--repo group/subgroup/project).
247
248
  "gitlab",
@@ -2098,7 +2099,9 @@ Models (your own writing models, each trained on writing you give it so it write
2098
2099
  models remove <id> <link-id>… Take links out of the next version
2099
2100
  models train <id> [--retry] Train the next version, or try a stopped one again
2100
2101
  models stop <id> Stop what is training; what it spent is charged
2101
- models write <id> "<what to write>" [--words <n>] Write with its trained version
2102
+ models rewrite <id> "<source text>" Rewrite supplied prose in its trained voice
2103
+ models compare <id> "<source text>" Compare the model with Claude and GPT using examples
2104
+ models write <id> "<what to write>" [--words <n>] Legacy ask-based generation
2102
2105
  models update <id> [--name <n>] [--budget <usd>] [--description <d>]
2103
2106
  models archive <id> | models restore <id>
2104
2107
 
@@ -2120,13 +2123,13 @@ Bench (Benches: open-source benchmarks on their own domains, kept running; @lett
2120
2123
  bench replicate <id> REPLICATE.md: how an agent reproduces the results
2121
2124
 
2122
2125
  Replicate (the Replicator: a website rebuilt as a native Next.js repo, page for page; free, within fair-use limits):
2123
- replicate <https://site> [--max-pages <n>] [--path <p>]… [--refine-budget <usd>] [--repo-name <r>] [--repo-owner <o>]
2126
+ replicate <https://site> [--max-pages <n>] [--path <p>]… [--sample-banner] [--refine-budget <usd>] [--repo-name <r>] [--repo-owner <o>]
2124
2127
  Capture every page, rebuild it, compare it pixel by pixel
2125
2128
  replicate [list] Your replications: stage, how closely each matches, preview link;
2126
2129
  the limits (in progress, pages this month, preview days)
2127
2130
  replicate show <id> [--failing] Pages with their routes and pixel match; collections; events
2128
2131
  replicate attach <id> <repo-name> [--repo-owner <o>] The repo to commit it into (yours; Letter never creates it)
2129
- replicate advance <id> [--retry] [--again] [--preview] [--extend-preview <days>] [--keep-preview]
2132
+ replicate advance <id> [--retry] [--again] [--preview] [--extend-preview <days>] [--keep-preview] [--sample-banner]
2130
2133
  Move it on now; --retry once blocked_on is done (checks the tag or TXT record);
2131
2134
  --again replicates from the start; --preview deploys its staging link again;
2132
2135
  --extend-preview keeps the preview up longer (Letter's team only)
@@ -46,6 +46,14 @@ export const ARGS = {
46
46
  urls: { value: rest(1) },
47
47
  train: { flag: "train", type: "bool" },
48
48
  },
49
+ add_writing_model_texts: {
50
+ model_id: modelId,
51
+ documents: {
52
+ value: (flags, positionals) => [
53
+ { title: flagStr(flags.title) ?? "Supplied writing", text: positionals.slice(1).join(" ") },
54
+ ],
55
+ },
56
+ },
49
57
  find_writing_model_links: {
50
58
  model_id: modelId,
51
59
  prompt: { value: (flags, positionals) => positionals.slice(1).join(" ").trim() || undefined },
@@ -60,6 +68,14 @@ export const ARGS = {
60
68
  remove_writing_model_links: { model_id: modelId, source_ids: { value: rest(1) } },
61
69
  train_writing_model: { model_id: modelId, retry: { flag: "retry", type: "bool" } },
62
70
  cancel_writing_model_run: { model_id: modelId },
71
+ rewrite_with_writing_model: {
72
+ model_id: modelId,
73
+ text: { value: (flags, positionals) => positionals.slice(1).join(" ").trim() || undefined },
74
+ },
75
+ compare_writing_model: {
76
+ model_id: modelId,
77
+ text: { value: (flags, positionals) => positionals.slice(1).join(" ").trim() || undefined },
78
+ },
63
79
  write_with_writing_model: {
64
80
  model_id: modelId,
65
81
  ask: { value: (flags, positionals) => positionals.slice(1).join(" ").trim() || undefined },
@@ -109,6 +125,11 @@ export async function cmdModels(ctx) {
109
125
  }
110
126
  case "show":
111
127
  return modelShow(next, await call(next, "get_writing_model"));
128
+ case "add-text": {
129
+ refuseUnknownFlags(next, ARGS.add_writing_model_texts, ["title"]);
130
+ const result = await call(next, "add_writing_model_texts");
131
+ return modelShow(next, result);
132
+ }
112
133
  case "add": {
113
134
  refuseUnknownFlags(next, ARGS.add_writing_model_links, []);
114
135
  const args = argsFromFlags(ARGS.add_writing_model_links, next.flags, next.positionals);
@@ -160,6 +181,23 @@ export async function cmdModels(ctx) {
160
181
  printResult(next.io, next.flags, result, (r) => runLine(r.run));
161
182
  return 0;
162
183
  }
184
+ case "rewrite":
185
+ case "compare": {
186
+ const tool = sub === "rewrite" ? "rewrite_with_writing_model" : "compare_writing_model";
187
+ refuseUnknownFlags(next, ARGS[tool], []);
188
+ const args = argsFromFlags(ARGS[tool], next.flags, next.positionals);
189
+ if (!args.text) throw new CliError(`Supply source text: models ${sub} <id> "<text>"`);
190
+ const result = await next.client.callTool(tool, args);
191
+ printResult(next.io, next.flags, result, (r) =>
192
+ sub === "rewrite"
193
+ ? r.text
194
+ : Object.entries(r.outputs)
195
+ .map(([name, out]) => `${name}:\n${out.text ?? out.error}`)
196
+ .join("\n\n")
197
+ );
198
+ return 0;
199
+ }
200
+
163
201
  case "write": {
164
202
  refuseUnknownFlags(next, ARGS.write_with_writing_model, []);
165
203
  const args = argsFromFlags(ARGS.write_with_writing_model, next.flags, next.positionals);
@@ -176,7 +214,7 @@ export async function cmdModels(ctx) {
176
214
  return modelShow(next, await call(next, "update_writing_model", { archived: sub === "archive" }));
177
215
  default:
178
216
  throw new CliError(
179
- "Usage: models [list|create|show|add|find|confirm|remove|train|stop|write|update|archive|restore]"
217
+ "Usage: models [list|create|show|add|find|confirm|remove|train|stop|rewrite|compare|write|update|archive|restore]"
180
218
  );
181
219
  }
182
220
  }
@@ -25,6 +25,7 @@ export const ARGS = {
25
25
  url: { positional: 0, label: "url", required: true },
26
26
  max_pages: { flag: "max-pages", type: "num" },
27
27
  paths: { flag: "path", type: "list" },
28
+ sample_banner: { flag: "sample-banner", type: "bool" },
28
29
  refine_budget_usd: { flag: "refine-budget", type: "num" },
29
30
  repo_name: "repo-name",
30
31
  repo_owner: "repo-owner",
@@ -46,6 +47,7 @@ export const ARGS = {
46
47
  preview: { flag: "preview", type: "bool" },
47
48
  extend_preview_days: { flag: "extend-preview", type: "num" },
48
49
  keep_preview: { flag: "keep-preview", type: "bool" },
50
+ sample_banner: { flag: "sample-banner", type: "bool" },
49
51
  },
50
52
  archive_replication: { replication_id: replicationId },
51
53
  get_replication_forms_key: { replication_id: replicationId },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.177.28",
3
+ "version": "0.177.30",
4
4
  "description": "Spin up and manage Letter phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",