@letterstory/cli 0.131.0 → 0.132.0
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 +4 -2
- package/lib/commands/enclosures.mjs +29 -0
- package/lib/commands/repo.mjs +10 -3
- package/package.json +1 -1
package/lib/cli.mjs
CHANGED
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
} from "./commands.mjs";
|
|
63
63
|
|
|
64
64
|
// Keep in sync with cli/package.json.
|
|
65
|
-
export const VERSION = "0.
|
|
65
|
+
export const VERSION = "0.132.0";
|
|
66
66
|
|
|
67
67
|
// Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
|
|
68
68
|
// can't accidentally swallow the id as --json's value. Every `type: "bool"` flag (and its
|
|
@@ -1364,8 +1364,10 @@ Repo changes (Claude Code edits your repo in a sandbox; the Letterstory GitHub A
|
|
|
1364
1364
|
repo slack-test Post a test into the Send to Slack channel
|
|
1365
1365
|
repo start --repo <owner/name> --instructions <text>|--instructions-file <path|->
|
|
1366
1366
|
[--branch <base>] [--attach <path>]... [--attach-url <name>=<https url>]...
|
|
1367
|
+
[--attach-ref <path>]... [--attach-url-ref <name>=<https url>]...
|
|
1367
1368
|
[--action build|build_pr|build_merge|slack|linear] [--with-preview] [--wait]
|
|
1368
|
-
Start a change (attached files go to the sandbox
|
|
1369
|
+
Start a change (attached files go to the sandbox;
|
|
1370
|
+
-ref ones are context, never put in the repo);
|
|
1369
1371
|
--with-preview keeps a preview up next to the PR;
|
|
1370
1372
|
--wait follows it to the PR
|
|
1371
1373
|
repo fix-audit --issue <issue-type>... [--audit <id>] [--branch <base>] [--action build|build_pr|build_merge|slack|linear] [--wait]
|
|
@@ -110,6 +110,10 @@ export const ARGS = {
|
|
|
110
110
|
...fields,
|
|
111
111
|
},
|
|
112
112
|
list_generator_starters: {},
|
|
113
|
+
get_generator_version: {
|
|
114
|
+
generator_id: { positional: 0, label: "enclosure-id", required: true },
|
|
115
|
+
version: { value: (_flags, positionals) => Number(requirePositional(positionals, 1, "version")) },
|
|
116
|
+
},
|
|
113
117
|
add_generator_version: {
|
|
114
118
|
generator_id: { positional: 0, label: "enclosure-id", required: true },
|
|
115
119
|
script: { value: (flags) => readTextInput(flags, "script", "script-file") },
|
|
@@ -173,6 +177,7 @@ const USAGE = `Usage: enclosures <list|show|create|update|prints>
|
|
|
173
177
|
enclosures prints <enclosure-id> [--status done|failed|no_fit|…] [--limit <n>]
|
|
174
178
|
enclosures starters
|
|
175
179
|
enclosures create --starter site_audit --login <app-id> Begin from a starter (its version 1 included)
|
|
180
|
+
enclosures version <enclosure-id> <n> One version in full: its steps and the script prints replay
|
|
176
181
|
enclosures add-version <enclosure-id> (--script <code>|--script-file <path>) --step <text>… [--host <h>…] [--summary <s>]
|
|
177
182
|
enclosures approve <enclosure-id> --version <n>
|
|
178
183
|
enclosures print <enclosure-id> (--prospect <id>…|--list <list-id>) [--version <n>] [--redo] [--dry-run]
|
|
@@ -201,6 +206,8 @@ export async function cmdEnclosures(ctx) {
|
|
|
201
206
|
return enclosuresApps(rest);
|
|
202
207
|
case "starters":
|
|
203
208
|
return enclosuresStarters(rest);
|
|
209
|
+
case "version":
|
|
210
|
+
return enclosuresVersion(rest);
|
|
204
211
|
case "add-version":
|
|
205
212
|
return enclosuresAddVersion(rest);
|
|
206
213
|
case "approve":
|
|
@@ -346,6 +353,28 @@ async function enclosuresStarters(ctx) {
|
|
|
346
353
|
return 0;
|
|
347
354
|
}
|
|
348
355
|
|
|
356
|
+
async function enclosuresVersion(ctx) {
|
|
357
|
+
const { client, flags, positionals, io } = ctx;
|
|
358
|
+
refuseUnknownFlags(ctx, ARGS.get_generator_version, []);
|
|
359
|
+
const result = await client.callTool(
|
|
360
|
+
"get_generator_version",
|
|
361
|
+
argsFromFlags(ARGS.get_generator_version, flags, positionals)
|
|
362
|
+
);
|
|
363
|
+
printResult(io, flags, result, ({ version: v }) =>
|
|
364
|
+
[
|
|
365
|
+
`version ${v.version} (${v.author})${v.current ? ", prints run this one" : ""}${v.change_summary ? `: ${v.change_summary}` : ""}`,
|
|
366
|
+
...v.steps.map((s) => ` ${s.n}. ${s.text}${s.screenshot_url ? ` ${s.screenshot_url}` : ""}`),
|
|
367
|
+
v.allowed_hosts.length ? ` hosts: ${v.allowed_hosts.join(", ")}` : null,
|
|
368
|
+
v.region ? ` region: ${v.region.selectors.join(", ")}` : null,
|
|
369
|
+
"",
|
|
370
|
+
v.script,
|
|
371
|
+
]
|
|
372
|
+
.filter((l) => l !== null)
|
|
373
|
+
.join("\n")
|
|
374
|
+
);
|
|
375
|
+
return 0;
|
|
376
|
+
}
|
|
377
|
+
|
|
349
378
|
async function enclosuresAddVersion(ctx) {
|
|
350
379
|
const { client, flags, positionals, io } = ctx;
|
|
351
380
|
refuseUnknownFlags(ctx, ARGS.add_generator_version, ["script", "script-file", "step", "region-selector"]);
|
package/lib/commands/repo.mjs
CHANGED
|
@@ -59,7 +59,8 @@ const ARGS = {
|
|
|
59
59
|
base_branch: "branch",
|
|
60
60
|
// --instructions, or a longer brief from --instructions-file <path> / - (stdin).
|
|
61
61
|
instructions: { value: (flags) => readTextInput(flags, "instructions", "instructions-file") },
|
|
62
|
-
// --attach <path> (uploaded first) and --attach-url <name>=<https url>, both repeatable
|
|
62
|
+
// --attach <path> (uploaded first) and --attach-url <name>=<https url>, both repeatable;
|
|
63
|
+
// --attach-ref / --attach-url-ref the same for context the agent reads, never puts in the repo.
|
|
63
64
|
files: { value: (_flags, _positionals, extra) => (extra.files?.length ? extra.files : undefined) },
|
|
64
65
|
action: { flag: "action", enum: ["build", "build_pr", "build_merge", "slack", "linear"] },
|
|
65
66
|
preview: { flag: "preview", type: "bool" },
|
|
@@ -300,7 +301,7 @@ async function uploadAttachments(ctx, paths) {
|
|
|
300
301
|
.replace(/[^A-Za-z0-9._ -]/g, "-")
|
|
301
302
|
.replace(/^[^A-Za-z0-9]+/, "")
|
|
302
303
|
);
|
|
303
|
-
if (new Set(names).size !== names.length) throw new CliError("Two
|
|
304
|
+
if (new Set(names).size !== names.length) throw new CliError("Two attached files share a name; rename one.");
|
|
304
305
|
const bytes = paths.map((p) => {
|
|
305
306
|
try {
|
|
306
307
|
return readFileSync(p);
|
|
@@ -332,14 +333,20 @@ async function repoStart(ctx) {
|
|
|
332
333
|
"instructions-file",
|
|
333
334
|
"attach",
|
|
334
335
|
"attach-url",
|
|
336
|
+
"attach-ref",
|
|
337
|
+
"attach-url-ref",
|
|
335
338
|
"action",
|
|
336
339
|
"preview",
|
|
337
340
|
"with-preview",
|
|
338
341
|
"wait",
|
|
339
342
|
]);
|
|
343
|
+
// One upload for every file (names must be unique across both), then the references marked.
|
|
344
|
+
const place = flagList(flags.attach);
|
|
345
|
+
const uploaded = await uploadAttachments(ctx, [...place, ...flagList(flags["attach-ref"])]);
|
|
340
346
|
const files = [
|
|
341
|
-
...(
|
|
347
|
+
...uploaded.map((f, i) => (i < place.length ? f : { ...f, reference: true })),
|
|
342
348
|
...attachmentUrls(flagList(flags["attach-url"])),
|
|
349
|
+
...attachmentUrls(flagList(flags["attach-url-ref"])).map((f) => ({ ...f, reference: true })),
|
|
343
350
|
];
|
|
344
351
|
const args = argsFromFlags(ARGS.start_repo_change, flags, ctx.positionals, { files });
|
|
345
352
|
if (!args.repo_owner || !args.repo_name) throw new CliError("Missing --repo owner/name");
|