@letterstory/cli 0.176.84 → 0.176.86
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 -1
- package/lib/commands/deploy.mjs +18 -2
- package/lib/commands/site.mjs +33 -1
- package/package.json +1 -1
package/lib/cli.mjs
CHANGED
|
@@ -85,7 +85,7 @@ import {
|
|
|
85
85
|
import { fetchParkedSections, withoutParked } from "./parked.mjs";
|
|
86
86
|
|
|
87
87
|
// Matches cli/package.json; publish-cli.yml rewrites both to the published version.
|
|
88
|
-
export const VERSION = "0.176.
|
|
88
|
+
export const VERSION = "0.176.86";
|
|
89
89
|
|
|
90
90
|
/** The exit code for a gate refusal (CARD_REQUIRED, PAYMENT_FAILED, OUT_OF_TOKENS): 1 is a plain error. */
|
|
91
91
|
export const EXIT_PAYMENT_REQUIRED = 3;
|
|
@@ -1841,6 +1841,8 @@ The Site (one model of your whole marketing site, keyed by host and path):
|
|
|
1841
1841
|
site competitors [--since <iso> | --days <n>] [--limit <n>] Tracked competitors' sites: new and removed pages, by folder
|
|
1842
1842
|
site watch-competitors [domain] [--limit <n>] Map competitors' sitemaps (the next few unmapped, or one now)
|
|
1843
1843
|
site highlight <domain> [--off] Highlight a competitor; its changes lead the top changes
|
|
1844
|
+
site prospect <url> [--pages <n>] [--max-pages <n>] [--depth <n>]
|
|
1845
|
+
Staff: any company's site, no account: what Fix would list, each PR
|
|
1844
1846
|
|
|
1845
1847
|
Repo changes (Claude Code edits your repo in a sandbox; the Letter GitHub App opens a PR):
|
|
1846
1848
|
repo repos [--gitlab [--search <text>] [--page n]] Repos the Letter GitHub App can reach (--gitlab: the GitLab
|
|
@@ -1981,6 +1983,7 @@ Deploy (websites and apps Letter builds from your words and hosts on their own d
|
|
|
1981
1983
|
deploy update <id> [--name <n>] [--domain <d>] The domain only before it is built
|
|
1982
1984
|
deploy pause <id> | deploy resume <id> | deploy archive <id>
|
|
1983
1985
|
deploy advance <id> [--retry] Move it on now; --retry once blocked_on is done
|
|
1986
|
+
deploy page <id> Add a landing page to it now (Letter adds one a week)
|
|
1984
1987
|
deploy source <id> A link to download its source, as Letter keeps it
|
|
1985
1988
|
deploy connect <id> <owner/name> Move its source to your GitHub repo (empty); it's
|
|
1986
1989
|
pushed once the Letter GitHub App can reach it
|
package/lib/commands/deploy.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// `deploy` — Deployments from a terminal (docs/architecture/deployments.md): websites and apps Letter
|
|
2
2
|
// builds from your words and hosts on their own domains, with your phantoms and benches in the list.
|
|
3
3
|
// Thin wrappers over the deployment tools (create_deployment, list_deployments, get_deployment,
|
|
4
|
-
// update_deployment, advance_deployment), the same lib functions the app calls.
|
|
4
|
+
// update_deployment, advance_deployment, add_deployment_page), the same lib functions the app calls.
|
|
5
5
|
//
|
|
6
6
|
// letterstory deploy create "Build me a website for HVAC contractors to collect leads" [--name <n>] [--domain <d>] [--ref <visual-ref-id>] [--wait]
|
|
7
7
|
// letterstory deploy list [--kind app|phantom|bench]
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// letterstory deploy update <id> [--name <n>] [--domain <d>]
|
|
10
10
|
// letterstory deploy pause <id> | resume <id> | archive <id>
|
|
11
11
|
// letterstory deploy advance <id> [--retry]
|
|
12
|
+
// letterstory deploy page <id>
|
|
12
13
|
|
|
13
14
|
import { CliError } from "../client.mjs";
|
|
14
15
|
import { argsFromFlags, flagStr, printResult, refuseUnknownFlags } from "./shared.mjs";
|
|
@@ -41,6 +42,7 @@ export const ARGS = {
|
|
|
41
42
|
status: { flag: "status", enum: ["live", "paused", "archived"] },
|
|
42
43
|
},
|
|
43
44
|
advance_deployment: { id: appId, retry: { flag: "retry", type: "bool" } },
|
|
45
|
+
add_deployment_page: { id: appId },
|
|
44
46
|
connect_deployment_repo: {
|
|
45
47
|
id: appId,
|
|
46
48
|
repo_owner: { value: (_flags, positionals) => repoPart(positionals[1], 0) },
|
|
@@ -83,6 +85,9 @@ export async function cmdDeploy(ctx) {
|
|
|
83
85
|
case "advance":
|
|
84
86
|
refuseUnknownFlags(rest, ARGS.advance_deployment, []);
|
|
85
87
|
return deployShow(rest, await call(rest, "advance_deployment"));
|
|
88
|
+
case "page":
|
|
89
|
+
refuseUnknownFlags(rest, ARGS.add_deployment_page, []);
|
|
90
|
+
return deployShow(rest, await call(rest, "add_deployment_page"));
|
|
86
91
|
case "connect":
|
|
87
92
|
return deployShow(rest, await call(rest, "connect_deployment_repo"));
|
|
88
93
|
case "source": {
|
|
@@ -96,7 +101,9 @@ export async function cmdDeploy(ctx) {
|
|
|
96
101
|
return 0;
|
|
97
102
|
}
|
|
98
103
|
default:
|
|
99
|
-
throw new CliError(
|
|
104
|
+
throw new CliError(
|
|
105
|
+
"Usage: deploy [list|create|show|update|pause|resume|archive|advance|page|connect|source]"
|
|
106
|
+
);
|
|
100
107
|
}
|
|
101
108
|
}
|
|
102
109
|
|
|
@@ -135,6 +142,15 @@ function deployShow(ctx, result) {
|
|
|
135
142
|
...(a.source?.pending
|
|
136
143
|
? [` Moving to ${a.source.pending.repo}: ${a.source.pending.note ?? "trying now"}`]
|
|
137
144
|
: []),
|
|
145
|
+
...(a.writing?.state === "on"
|
|
146
|
+
? [
|
|
147
|
+
` Writing posts at /blog from letterbase ${a.writing.collection_id} (automations list --collection ${a.writing.collection_id}), a landing page a week (deploy page ${a.id} adds one now)`,
|
|
148
|
+
]
|
|
149
|
+
: a.writing?.state === "failed"
|
|
150
|
+
? [` Writing not set up: ${a.writing.note ?? "no reason given"} (deploy advance ${a.id} --retry)`]
|
|
151
|
+
: a.writing?.state === "pending"
|
|
152
|
+
? [" Writing starts once the site is live: posts at /blog and a landing page a week"]
|
|
153
|
+
: []),
|
|
138
154
|
];
|
|
139
155
|
if (a.dns?.to_set?.length) {
|
|
140
156
|
lines.push("", `Set these where ${a.domain}'s DNS is:`);
|
package/lib/commands/site.mjs
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// site decide <proposal> → decide_site_proposal site fix <host> <id>… → fix_site_observations
|
|
15
15
|
// site competitors → list_competitor_sites site watch-competitors [d] → watch_competitor_sites
|
|
16
16
|
// site highlight <domain> [--off] → set_competitor_highlight
|
|
17
|
+
// site prospect <url> → read_prospect_site (staff: any company's site, no account, nothing stored)
|
|
17
18
|
|
|
18
19
|
import { writeFileSync } from "node:fs";
|
|
19
20
|
|
|
@@ -69,6 +70,12 @@ const ARGS = {
|
|
|
69
70
|
skip_suggest: { flag: "skip-suggest", type: "bool" },
|
|
70
71
|
},
|
|
71
72
|
unmap_site: { host: { positional: 0, required: true, label: "host" } },
|
|
73
|
+
read_prospect_site: {
|
|
74
|
+
url: { positional: 0, required: true, label: "url" },
|
|
75
|
+
pages: { flag: "pages", type: "num" },
|
|
76
|
+
max_pages: { flag: "max-pages", type: "num" },
|
|
77
|
+
depth: { flag: "depth", type: "num" },
|
|
78
|
+
},
|
|
72
79
|
get_llms_txt: { host: { positional: 0, required: true, label: "host" } },
|
|
73
80
|
get_site_tree: {
|
|
74
81
|
host: { positional: 0, required: true, label: "host" },
|
|
@@ -255,9 +262,11 @@ export async function cmdSite(ctx) {
|
|
|
255
262
|
return siteWatchCompetitors(rest);
|
|
256
263
|
case "highlight":
|
|
257
264
|
return siteHighlight(rest);
|
|
265
|
+
case "prospect":
|
|
266
|
+
return siteProspect(rest);
|
|
258
267
|
default:
|
|
259
268
|
throw new CliError(
|
|
260
|
-
`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`
|
|
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`
|
|
261
270
|
);
|
|
262
271
|
}
|
|
263
272
|
}
|
|
@@ -387,6 +396,29 @@ async function siteMap(ctx) {
|
|
|
387
396
|
return 0;
|
|
388
397
|
}
|
|
389
398
|
|
|
399
|
+
/** Any company's site read as the Site and Fix read a customer's: what Fix would list, and each pull request. */
|
|
400
|
+
async function siteProspect(ctx) {
|
|
401
|
+
const { client, flags, io } = ctx;
|
|
402
|
+
refuseUnknownFlags(ctx, ARGS.read_prospect_site);
|
|
403
|
+
const read = await client.callTool(
|
|
404
|
+
"read_prospect_site",
|
|
405
|
+
argsFromFlags(ARGS.read_prospect_site, flags, ctx.positionals)
|
|
406
|
+
);
|
|
407
|
+
printResult(io, flags, read, (r) => {
|
|
408
|
+
const fixFor = new Map(r.fixes.map((f) => [f.itemId, f]));
|
|
409
|
+
const head = [
|
|
410
|
+
`${r.host}${r.platform ? ` (built with ${r.platform.name})` : ""}: ${r.map.pages} pages mapped${r.map.truncated ? ` of ${r.map.listed} listed` : ""}, ${r.read.answered} of ${r.read.pages} read, ${r.open.total} open issues`,
|
|
411
|
+
...(r.note ? [r.note] : []),
|
|
412
|
+
];
|
|
413
|
+
const rows = r.issues.map((i) => {
|
|
414
|
+
const fix = fixFor.get(i.id);
|
|
415
|
+
return ` ${GLYPH[i.tone] ?? "·"} ${i.summary} ${i.path}${fix ? `\n PR: ${fix.title} (${fix.branch})` : ""}`;
|
|
416
|
+
});
|
|
417
|
+
return [...head, ...rows].join("\n");
|
|
418
|
+
});
|
|
419
|
+
return 0;
|
|
420
|
+
}
|
|
421
|
+
|
|
390
422
|
async function siteRefresh(ctx) {
|
|
391
423
|
const { client, flags, io } = ctx;
|
|
392
424
|
refuseUnknownFlags(ctx, ARGS.refresh_site);
|