frontpage-host 0.3.12 → 0.3.14
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/AGENTS.md +17 -1
- package/MAIL.md +4 -2
- package/PEOPLE.md +1 -1
- package/README.md +16 -0
- package/dist/commands/prompt-attach.d.ts +1 -0
- package/dist/commands/prompt-attach.js +3 -2
- package/dist/media/upload.d.ts +2 -0
- package/dist/media/upload.js +22 -2
- package/dist/registry.js +4 -1
- package/llms.txt +3 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -298,4 +298,20 @@ For a manual group, `groups.people` accepts `availability: "all" | "available" |
|
|
|
298
298
|
|
|
299
299
|
Complete Store edits: use existing items update --file with changed fields and variantUpdates. stock requires expectedStock from a fresh items get. One transaction saves all changes or none. On 409 review current stock; never silently substitute it. firstVariant plus optionNames enables versions. Keep explicit stock/variant commands for single operations. Routines add accepts --request-id UUID; reuse that ID and exact schedule after a lost response. Ordinary form edits live only in the active task; Cancel keeps input, Discard loses unfinished input. Submitted payments, imports, builds, and API-key status are separate operations.
|
|
300
300
|
|
|
301
|
-
Template history (frontpage-host 0.3.11+): read `mail template get ID` before editing. `mail template history ID --limit 20 --cursor CURSOR` pages saved copies; `mail template history-get ID --history-id COPY_ID` fetches full content. Edit any copy, then `mail template set ID --file content.json` with the stable template ID and content fields only to make a new latest copy. Last template save wins; past copies remain. Campaign and series conflict checks remain. Retry uncertain saves through `mail save` with the same requestKey and exact payload. History begins with content retained at launch; earlier overwritten edits are unavailable. See MAIL.md.
|
|
301
|
+
Template history (frontpage-host 0.3.11+): read `mail template get ID` before editing. `mail template history ID --limit 20 --cursor CURSOR` pages saved copies; `mail template history-get ID --history-id COPY_ID` fetches full content. Edit any copy, then `mail template set ID --file content.json` with the stable template ID and content fields only to make a new latest copy. Last template save wins; past copies remain. Campaign and series conflict checks remain. Retry uncertain saves through `mail save` with the same requestKey and exact payload. History begins with content retained at launch; earlier overwritten edits are unavailable. History reads use the plan’s Rewind window and always include Latest, even when older. Older copies stay stored; lists and direct reads apply the same limit. Window metadata explains the limit and whether older copies exist. See MAIL.md.
|
|
302
|
+
|
|
303
|
+
## Uploaded video preparation
|
|
304
|
+
|
|
305
|
+
The current CLI attempts browser-compatible H.264 MP4 preparation after a local video
|
|
306
|
+
upload. This applies to `frontpage media upload` and `frontpage prompt --attach ./clip.mov`.
|
|
307
|
+
Use the returned `sitePath`; do not reconstruct a path from the original filename.
|
|
308
|
+
A successful conversion returns `prepared:true` and the MP4's actual filename, size and
|
|
309
|
+
URL. If preparation fails, the original remains usable as an upload with `prepared:false`
|
|
310
|
+
and a compatibility warning. Warnings print on stderr and appear in JSON success data.
|
|
311
|
+
An original's MP4/MOV extension does not establish browser compatibility.
|
|
312
|
+
|
|
313
|
+
`frontpage media list` and the website agent's `list_site_assets` prefer a completed
|
|
314
|
+
prepared copy over its exact original. Different uploads with the same display name
|
|
315
|
+
remain distinct. Existing URLs and published videos are not converted automatically.
|
|
316
|
+
Upgrade the CLI to receive upload-time preparation. Source path and access denials
|
|
317
|
+
remain errors; they do not become original-file fallback successes.
|
package/MAIL.md
CHANGED
|
@@ -44,9 +44,11 @@ frontpage mail template history TEMPLATE_ID --cursor NEXT_CURSOR --site YOUR_SIT
|
|
|
44
44
|
frontpage mail template history-get TEMPLATE_ID --history-id SAVED_COPY_ID --site YOUR_SITE --json
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
History returns `items` (ID, savedAt, name, subject), `currentId` and `
|
|
47
|
+
History returns `items` (ID, savedAt, name, subject), `currentId`, `nextCursor`, `windowDays`, `unlimited`, `canUpgrade` and `moreBeyondWindow`. The last field reports hidden older copies when the final page is reached. Fetch the next page until `nextCursor` is null. The default page size is 20, with a maximum of 100. `history-get` returns `copy` with full content and `templateId`, the stable ID. The workspace shows the same history under Sender; scrolling loads the next 20 copies.
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
Template history reads follow the site plan’s Rewind window: Starter 7 days, Growth 30 days, Scale 90 days; Enterprise and Internal use the existing uncapped history rule. Latest remains readable at any age. Older copies stay stored and become readable again within a larger window after an upgrade. Both history lists and history-get enforce the window; direct saved-copy IDs do not bypass it. Existing feature and CLI plan gates still apply.
|
|
50
|
+
|
|
51
|
+
To use an available old copy, fetch it, edit it if needed, then save normally. Put only `name`, `subject`, `preheader`, `blocks` and `variables` in a JSON file, then run `frontpage mail template set TEMPLATE_ID --file content.json --site YOUR_SITE --json`. Use the stable TEMPLATE_ID, never the saved-copy ID. This creates a new latest copy; it does not change the old one. There is no separate restore command. Read `template get` before each edit so you start with current work. For response-loss retries use `mail save` with one unchanged `requestKey` and payload; replaying that save creates no duplicate copy.
|
|
50
52
|
|
|
51
53
|
Public API reads: `GET /api/v1/sites/SLUG/mail/templates/TEMPLATE_ID/history?limit=20&cursor=…` and `GET /api/v1/sites/SLUG/mail/templates/TEMPLATE_ID/history/SAVED_COPY_ID`. Viewers may read; editors and owners may save. Site access and plan checks still apply.
|
|
52
54
|
|
package/PEOPLE.md
CHANGED
|
@@ -788,4 +788,4 @@ Writes are not universally idempotent. Preserve documented request keys, receipt
|
|
|
788
788
|
|
|
789
789
|
For MCP CSV exports, continue `contacts.export` with `textOffset` set to `textPage.nextOffset` and `expectedTextVersion` set to `textPage.version`. The tool returns bounded `csv` text and a version hash; a changed export returns a conflict instead of combining different snapshots. `textLength` defaults to 4,000 UTF-16 units and accepts up to 8,000.
|
|
790
790
|
|
|
791
|
-
Template history uses the existing Email tools. Read get_mail_template before editing. list_mail_template_history({id,cursor?,limit?}) pages copies; get_mail_template_history({id,historyId}) reads full content. Edit any copy and save through update_mail_template with the stable ID to make it latest. Both simultaneous saves remain; last template save wins. Group, rule and series checks remain. CLI equivalents and full instructions: MAIL.md, Template history.
|
|
791
|
+
Template history uses the existing Email tools. Read get_mail_template before editing. list_mail_template_history({id,cursor?,limit?}) pages copies; get_mail_template_history({id,historyId}) reads full content. Edit any copy and save through update_mail_template with the stable ID to make it latest. Both simultaneous saves remain; last template save wins. Group, rule and series checks remain. History lists and direct reads follow the plan’s Rewind window, plus Latest at any age. Older copies stay stored. CLI equivalents and full instructions: MAIL.md, Template history.
|
package/README.md
CHANGED
|
@@ -122,3 +122,19 @@ GPT 6 Luna is the default for new website runs. Explicit site model preferences
|
|
|
122
122
|
### Template history
|
|
123
123
|
|
|
124
124
|
Template history (0.3.11+): `frontpage mail template history ID` lists saved copies; `history-get ID --history-id COPY_ID` reads full content. Edit any copy and save with `template set ID --file content.json` to make it latest. Use the stable template ID, read current content before editing, and see [MAIL.md](./MAIL.md#template-history) for paging, access and retry-safe saves.
|
|
125
|
+
|
|
126
|
+
## Uploaded video preparation
|
|
127
|
+
|
|
128
|
+
The current CLI attempts browser-compatible H.264 MP4 preparation after a local video
|
|
129
|
+
upload. This applies to `frontpage media upload` and `frontpage prompt --attach ./clip.mov`.
|
|
130
|
+
Use the returned `sitePath`; do not reconstruct a path from the original filename.
|
|
131
|
+
A successful conversion returns `prepared:true` and the MP4's actual filename, size and
|
|
132
|
+
URL. If preparation fails, the original remains usable as an upload with `prepared:false`
|
|
133
|
+
and a compatibility warning. Warnings print on stderr and appear in JSON success data.
|
|
134
|
+
An original's MP4/MOV extension does not establish browser compatibility.
|
|
135
|
+
|
|
136
|
+
`frontpage media list` and the website agent's `list_site_assets` prefer a completed
|
|
137
|
+
prepared copy over its exact original. Different uploads with the same display name
|
|
138
|
+
remain distinct. Existing URLs and published videos are not converted automatically.
|
|
139
|
+
Upgrade the CLI to receive upload-time preparation. Source path and access denials
|
|
140
|
+
remain errors; they do not become original-file fallback successes.
|
|
@@ -101,8 +101,9 @@ export function addUploadResult(out, data) {
|
|
|
101
101
|
if (!out.videos.some((x) => x.url === data.url)) {
|
|
102
102
|
out.videos.push({
|
|
103
103
|
url: data.url,
|
|
104
|
-
name,
|
|
104
|
+
name: data.prepared ? data.filename ?? name : name,
|
|
105
105
|
sizeBytes: data.sizeBytes,
|
|
106
|
+
...(data.warning ? { warning: data.warning } : {}),
|
|
106
107
|
});
|
|
107
108
|
}
|
|
108
109
|
return;
|
|
@@ -122,7 +123,7 @@ export async function uploadLocalForAttach(slug, filePath) {
|
|
|
122
123
|
return uploadLocalMedia({ slug, filePath });
|
|
123
124
|
}
|
|
124
125
|
export async function resolveSitePathUrl(slug, sitePath) {
|
|
125
|
-
const data = await v1Get(`/api/v1/sites/${encodeURIComponent(slug)}/media`);
|
|
126
|
+
const data = await v1Get(`/api/v1/sites/${encodeURIComponent(slug)}/media?path=${encodeURIComponent(sitePath.replace(/\/+/g, "/").replace(/\/$/, ""))}`);
|
|
126
127
|
const norm = (p) => p.replace(/\/+/g, "/").replace(/\/$/, "") || p;
|
|
127
128
|
const want = norm(sitePath);
|
|
128
129
|
const hit = data.assets.find((a) => a.sitePath === sitePath || norm(a.sitePath) === want);
|
package/dist/media/upload.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export type UploadedMedia = {
|
|
|
8
8
|
contentType?: string;
|
|
9
9
|
content?: string;
|
|
10
10
|
transport?: "proxy" | "client";
|
|
11
|
+
prepared?: boolean;
|
|
12
|
+
warning?: string;
|
|
11
13
|
};
|
|
12
14
|
/** Upload a local file using the Phase E transport matrix. */
|
|
13
15
|
export declare function uploadLocalMedia(args: {
|
package/dist/media/upload.js
CHANGED
|
@@ -5,7 +5,7 @@ import { randomUUID } from "node:crypto";
|
|
|
5
5
|
import { readFile } from "node:fs/promises";
|
|
6
6
|
import { basename } from "node:path";
|
|
7
7
|
import { put } from "@vercel/blob/client";
|
|
8
|
-
import { apiBase, CliHttpError, EXIT_AUTH, EXIT_UNEXPECTED, EXIT_USAGE, getBearerAuthHeader, httpErrorFromV1, v1PostMultipart, } from "../http/client.js";
|
|
8
|
+
import { apiBase, CliHttpError, EXIT_AUTH, EXIT_UNEXPECTED, EXIT_USAGE, getBearerAuthHeader, httpErrorFromV1, v1PostMultipart, v1Post, } from "../http/client.js";
|
|
9
9
|
import { contentTypeForExt, sitePathFromKey } from "./limits.js";
|
|
10
10
|
import { selectMediaTransport } from "./select-transport.js";
|
|
11
11
|
async function requestClientToken(args) {
|
|
@@ -81,7 +81,7 @@ async function uploadViaClient(args) {
|
|
|
81
81
|
multipart,
|
|
82
82
|
});
|
|
83
83
|
const key = blob.pathname.replace(/^\//, "");
|
|
84
|
-
|
|
84
|
+
const original = {
|
|
85
85
|
kind: args.kind,
|
|
86
86
|
url: blob.url,
|
|
87
87
|
key,
|
|
@@ -91,8 +91,28 @@ async function uploadViaClient(args) {
|
|
|
91
91
|
contentType: args.contentType || contentTypeForExt(args.ext),
|
|
92
92
|
transport: "client",
|
|
93
93
|
};
|
|
94
|
+
if (args.kind !== "video")
|
|
95
|
+
return original;
|
|
96
|
+
try {
|
|
97
|
+
const prepared = await v1Post(`/api/v1/sites/${encodeURIComponent(args.slug)}/media/prepare`, { key, filename: args.filename }, { timeoutMs: 110000 });
|
|
98
|
+
if (typeof prepared.url !== "string" || typeof prepared.sitePath !== "string" || typeof prepared.filename !== "string" || typeof prepared.prepared !== "boolean")
|
|
99
|
+
throw new Error("Invalid video preparation response");
|
|
100
|
+
const result = { ...prepared, transport: "client" };
|
|
101
|
+
if (result.warning)
|
|
102
|
+
console.error(result.warning);
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (error instanceof CliHttpError && error.status >= 400 && error.status < 500 && ![408, 429].includes(error.status))
|
|
107
|
+
throw error;
|
|
108
|
+
const warning = "Uploaded original video. Some browsers may not play this format.";
|
|
109
|
+
console.error(warning);
|
|
110
|
+
return { ...original, prepared: false, warning };
|
|
111
|
+
}
|
|
94
112
|
}
|
|
95
113
|
catch (err) {
|
|
114
|
+
if (err instanceof CliHttpError)
|
|
115
|
+
throw err;
|
|
96
116
|
const msg = err instanceof Error ? err.message : String(err);
|
|
97
117
|
throw new CliHttpError(`Upload failed: ${msg}`, EXIT_UNEXPECTED, 500);
|
|
98
118
|
}
|
package/dist/registry.js
CHANGED
|
@@ -407,6 +407,9 @@ export const COMMANDS = [
|
|
|
407
407
|
],
|
|
408
408
|
flags: [
|
|
409
409
|
"Auto-selects proxy (≤4 MB) vs direct-to-Blob for large rasters/PDFs and all video",
|
|
410
|
+
"Video uploads then attempt browser-compatible MP4 preparation; use the returned sitePath",
|
|
411
|
+
"Preparation failure keeps the original with a stderr warning and prepared:false in JSON",
|
|
412
|
+
"media list prefers an exact completed prepared video over its original",
|
|
410
413
|
"Human success: sitePath first (markup-safe), then url: (blob URL for debugging)",
|
|
411
414
|
"Use sitePath (/__media/uploads/<slug>/…) in markup — never raw blob hosts in pages",
|
|
412
415
|
"Text/CSV upload is inline only — not a media-library asset (no /__media link); --json omits full content",
|
|
@@ -593,7 +596,7 @@ export const COMMANDS = [
|
|
|
593
596
|
"sends list --q --status --type campaign|series|confirmation|template|test|inline --page 1 --limit 20.",
|
|
594
597
|
"Series status active means On; paused/draft mean Off. Enrollment while Off waits at step 1, without sending. Existing people resume their next unsent step.",
|
|
595
598
|
"campaign preview|audience|send|get. --id DRAFT_ID, --file audience.json ({audience:{groupIds|stageIds|personIds|filters}}). send requires --request-key; reuse it after a network error. Templates/series are for automation; campaigns have separate drafts. See PEOPLE.md.",
|
|
596
|
-
"template history <id> pages saved copies with --limit (20 by default, max 100) and --cursor. history-get <id> --history-id reads full content. Use template set with the stable template ID to save edited content as latest; past copies stay unchanged. Read template get before editing. History begins with content retained when history shipped, not lost earlier edits.",
|
|
599
|
+
"template history <id> pages saved copies with --limit (20 by default, max 100) and --cursor. history-get <id> --history-id reads full content. Both reads follow the plan Rewind window, plus Latest at any age; older copies stay stored. Lists report windowDays, unlimited, canUpgrade and moreBeyondWindow. Use template set with the stable template ID to save edited content as latest; past copies stay unchanged. Read template get before editing. History begins with content retained when history shipped, not lost earlier edits.",
|
|
597
600
|
"email list is unsent drafts only. Sent one-offs are mail sends list",
|
|
598
601
|
"send --file is an inline one-off (no saved document)",
|
|
599
602
|
"Blocks and series steps are JSON (--file). Unknown leftover flags fail closed (exit 2)",
|
package/llms.txt
CHANGED
|
@@ -58,4 +58,6 @@ The workspace validates and saves unfinished group settings before opening email
|
|
|
58
58
|
|
|
59
59
|
Complete Store edits: use existing items update --file with changed fields and variantUpdates. stock requires expectedStock from a fresh items get. One transaction saves all changes or none. On 409 review current stock; never silently substitute it. firstVariant plus optionNames enables versions. Keep explicit stock/variant commands for single operations. Routines add accepts --request-id UUID; reuse that ID and exact schedule after a lost response. Ordinary form edits live only in the active task; Cancel keeps input, Discard loses unfinished input. Submitted payments, imports, builds, and API-key status are separate operations.
|
|
60
60
|
|
|
61
|
-
Template history (frontpage-host 0.3.11+): read `mail template get ID` before editing. `mail template history ID --limit 20 --cursor CURSOR` pages saved copies; `mail template history-get ID --history-id COPY_ID` fetches full content. Edit any copy, then `mail template set ID --file content.json` with the stable template ID and content fields only to make a new latest copy. Last template save wins; past copies remain. Campaign and series conflict checks remain. Retry uncertain saves through `mail save` with the same requestKey and exact payload. History begins with content retained at launch; earlier overwritten edits are unavailable. See MAIL.md.
|
|
61
|
+
Template history (frontpage-host 0.3.11+): read `mail template get ID` before editing. `mail template history ID --limit 20 --cursor CURSOR` pages saved copies; `mail template history-get ID --history-id COPY_ID` fetches full content. Edit any copy, then `mail template set ID --file content.json` with the stable template ID and content fields only to make a new latest copy. Last template save wins; past copies remain. Campaign and series conflict checks remain. Retry uncertain saves through `mail save` with the same requestKey and exact payload. History begins with content retained at launch; earlier overwritten edits are unavailable. History reads use the plan’s Rewind window and always include Latest, even when older. Older copies stay stored; lists and direct reads apply the same limit. Window metadata explains the limit and whether older copies exist. See MAIL.md.
|
|
62
|
+
|
|
63
|
+
Video uploads: the current CLI prepares a browser-compatible MP4 after uploading a local video, including prompt --attach. Use the returned sitePath and actual filename. prepared:false plus warning means the original was retained and playback compatibility is not assured. media list prefers an exact completed prepared copy. Existing video URLs are unchanged. See AGENTS.md for the upload and fallback contract.
|