frontpage-host 0.3.13 → 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 +16 -0
- 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 +3 -0
- package/llms.txt +2 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -299,3 +299,19 @@ For a manual group, `groups.people` accepts `availability: "all" | "available" |
|
|
|
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
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/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",
|
package/llms.txt
CHANGED
|
@@ -59,3 +59,5 @@ The workspace validates and saves unfinished group settings before opening email
|
|
|
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
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.
|