@se-studio/contentful-cms 3.9.3 → 3.10.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/CHANGELOG.md +12 -0
- package/README.md +3 -3
- package/dist/commands/asset.d.ts.map +1 -1
- package/dist/commands/asset.js +20 -5
- package/dist/commands/asset.js.map +1 -1
- package/dist/commands/host-scaffold.js +1 -1
- package/dist/commands/media.d.ts.map +1 -1
- package/dist/commands/media.js +10 -5
- package/dist/commands/media.js.map +1 -1
- package/dist/contentful/assets.d.ts +4 -0
- package/dist/contentful/assets.d.ts.map +1 -1
- package/dist/contentful/assets.js +9 -0
- package/dist/contentful/assets.js.map +1 -1
- package/dist/contentful/cma-user-agent.d.ts +1 -1
- package/dist/contentful/cma-user-agent.d.ts.map +1 -1
- package/dist/contentful/hosted-asset-upload.d.ts +1 -1
- package/dist/contentful/hosted-asset-upload.d.ts.map +1 -1
- package/dist/contentful/hosted-asset-upload.js +1 -1
- package/dist/contentful/hosted-asset-upload.js.map +1 -1
- package/dist/contentful/pipeline-encode-gate.d.ts +27 -0
- package/dist/contentful/pipeline-encode-gate.d.ts.map +1 -0
- package/dist/contentful/pipeline-encode-gate.js +102 -0
- package/dist/contentful/pipeline-encode-gate.js.map +1 -0
- package/dist/editor-pack/generate.js +1 -1
- package/dist/editor-pack/generate.js.map +1 -1
- package/dist/generated/hosted-guide.d.ts +1 -1
- package/dist/generated/hosted-guide.d.ts.map +1 -1
- package/dist/generated/hosted-guide.js +1 -1
- package/dist/generated/hosted-guide.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/generated/version.js.map +1 -1
- package/dist/hosted/next/routes/staged-upload.d.ts +1 -0
- package/dist/hosted/next/routes/staged-upload.d.ts.map +1 -1
- package/dist/hosted/next/routes/staged-upload.js +38 -1
- package/dist/hosted/next/routes/staged-upload.js.map +1 -1
- package/dist/mcp/prompts/onboarding.d.ts.map +1 -1
- package/dist/mcp/prompts/onboarding.js +5 -5
- package/dist/mcp/prompts/onboarding.js.map +1 -1
- package/dist/mcp/tools/cms-edit.d.ts +1 -1
- package/dist/mcp/tools/cms-edit.d.ts.map +1 -1
- package/dist/mcp/tools/cms-edit.js +3 -2
- package/dist/mcp/tools/cms-edit.js.map +1 -1
- package/dist/mcp/tools/media.d.ts.map +1 -1
- package/dist/mcp/tools/media.js +18 -11
- package/dist/mcp/tools/media.js.map +1 -1
- package/dist/mcp/tools/staged-upload.d.ts.map +1 -1
- package/dist/mcp/tools/staged-upload.js +6 -4
- package/dist/mcp/tools/staged-upload.js.map +1 -1
- package/dist/media-pipeline/actions.d.ts +6 -8
- package/dist/media-pipeline/actions.d.ts.map +1 -1
- package/dist/media-pipeline/actions.js +10 -8
- package/dist/media-pipeline/actions.js.map +1 -1
- package/dist/media-pipeline/client.d.ts +11 -3
- package/dist/media-pipeline/client.d.ts.map +1 -1
- package/dist/media-pipeline/client.js +1 -4
- package/dist/media-pipeline/client.js.map +1 -1
- package/dist/media-pipeline/import-alt.d.ts +8 -0
- package/dist/media-pipeline/import-alt.d.ts.map +1 -0
- package/dist/media-pipeline/import-alt.js +23 -0
- package/dist/media-pipeline/import-alt.js.map +1 -0
- package/dist/media-pipeline/import.d.ts.map +1 -1
- package/dist/media-pipeline/import.js +45 -0
- package/dist/media-pipeline/import.js.map +1 -1
- package/dist/media-pipeline/limits.d.ts +2 -2
- package/dist/media-pipeline/limits.d.ts.map +1 -1
- package/dist/media-pipeline/limits.js +2 -2
- package/dist/media-pipeline/limits.js.map +1 -1
- package/dist/media-pipeline/prepare-source.d.ts +32 -0
- package/dist/media-pipeline/prepare-source.d.ts.map +1 -0
- package/dist/media-pipeline/prepare-source.js +132 -0
- package/dist/media-pipeline/prepare-source.js.map +1 -0
- package/dist/staged-upload/hmac.d.ts +4 -0
- package/dist/staged-upload/hmac.d.ts.map +1 -1
- package/dist/staged-upload/hmac.js +35 -0
- package/dist/staged-upload/hmac.js.map +1 -1
- package/dist/staged-upload/request.d.ts.map +1 -1
- package/dist/staged-upload/request.js +14 -11
- package/dist/staged-upload/request.js.map +1 -1
- package/dist/staged-upload/store.d.ts +2 -0
- package/dist/staged-upload/store.d.ts.map +1 -1
- package/dist/staged-upload/store.js +18 -0
- package/dist/staged-upload/store.js.map +1 -1
- package/docs/editor-tasks/create-from-document.md +10 -3
- package/docs/editor-tasks/media-pipeline-prepare.md +29 -18
- package/docs/editor-tasks/media-reuse-and-upload.md +23 -20
- package/docs/editor-tasks/source-readiness-review.md +4 -3
- package/docs/mcp/hosted-guide.md +9 -8
- package/package.json +1 -1
- package/skills/core/SKILL.md +4 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-source.d.ts","sourceRoot":"","sources":["../../src/media-pipeline/prepare-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzF,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,MAAM,qBAAqB,GAAG,UAAU,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAmD5F,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,oBAAoB,EACzB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CACR;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAC7F,CA6FA"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { getPublicOrigin } from '../hosted/oauth/config.js';
|
|
2
|
+
import { getRuntimeContext } from '../runtime/context.js';
|
|
3
|
+
import { buildStagedDownloadUrl, getUploadHmacSecret } from '../staged-upload/hmac.js';
|
|
4
|
+
import { STAGED_UPLOAD_TTL_SECONDS } from '../staged-upload/limits.js';
|
|
5
|
+
import { parseDriveFolderUrl } from './validate.js';
|
|
6
|
+
function sanitizeIds(ids) {
|
|
7
|
+
const out = [];
|
|
8
|
+
const seen = new Set();
|
|
9
|
+
for (const raw of ids ?? []) {
|
|
10
|
+
const t = typeof raw === 'string' ? raw.trim() : '';
|
|
11
|
+
if (!t || seen.has(t)) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
seen.add(t);
|
|
15
|
+
out.push(t);
|
|
16
|
+
}
|
|
17
|
+
return out;
|
|
18
|
+
}
|
|
19
|
+
function normalizeHttpsUrls(urls) {
|
|
20
|
+
const files = [];
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
for (const raw of urls ?? []) {
|
|
23
|
+
const url = typeof raw === 'string' ? raw.trim() : raw.url?.trim();
|
|
24
|
+
if (!url || seen.has(url)) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
seen.add(url);
|
|
28
|
+
let sourceName;
|
|
29
|
+
if (typeof raw !== 'string' && raw.sourceName?.trim()) {
|
|
30
|
+
sourceName = raw.sourceName.trim();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
try {
|
|
34
|
+
const base = decodeURIComponent(new URL(url).pathname.split('/').pop() ?? '');
|
|
35
|
+
sourceName = base || `file-${String(files.length + 1)}`;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
sourceName = `file-${String(files.length + 1)}`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const mime = typeof raw === 'string' ? undefined : raw.mime?.trim() || undefined;
|
|
42
|
+
files.push(mime ? { sourceName, url, mime } : { sourceName, url });
|
|
43
|
+
}
|
|
44
|
+
return files;
|
|
45
|
+
}
|
|
46
|
+
function remainingTtlSeconds(createdAt) {
|
|
47
|
+
const elapsed = Math.floor((Date.now() - createdAt) / 1000);
|
|
48
|
+
return Math.max(60, STAGED_UPLOAD_TTL_SECONDS - elapsed);
|
|
49
|
+
}
|
|
50
|
+
export async function resolvePrepareSource(ctx, params) {
|
|
51
|
+
const driveUrl = params.driveFolderUrl?.trim();
|
|
52
|
+
const stagedIds = sanitizeIds(params.stagedUploadIds);
|
|
53
|
+
const httpsFiles = normalizeHttpsUrls(params.httpsUrls);
|
|
54
|
+
const hasDrive = Boolean(driveUrl);
|
|
55
|
+
const hasStaged = stagedIds.length > 0;
|
|
56
|
+
const hasHttps = httpsFiles.length > 0;
|
|
57
|
+
if (hasDrive && (hasStaged || hasHttps)) {
|
|
58
|
+
return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: 'Provide either driveFolderUrl or stagedUploadIds/httpsUrls, not both. Raster/video intake uses staged or HTTPS files in one prepare job.',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (!hasDrive && !hasStaged && !hasHttps) {
|
|
64
|
+
return {
|
|
65
|
+
ok: false,
|
|
66
|
+
error: 'prepare requires driveFolderUrl, stagedUploadIds, or httpsUrls. Raster and video must go through the media pipeline — do not use asset upload --staged/--url/--base64.',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (hasDrive && driveUrl) {
|
|
70
|
+
const folder = parseDriveFolderUrl(driveUrl);
|
|
71
|
+
if (!folder.ok) {
|
|
72
|
+
return { ok: false, error: folder.error };
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
ok: true,
|
|
76
|
+
source: { type: 'google_drive_folder', url: folder.url },
|
|
77
|
+
folderId: folder.folderId,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const files = [...httpsFiles];
|
|
81
|
+
if (hasStaged) {
|
|
82
|
+
const store = ctx.stagedUploadStore ?? getRuntimeContext()?.stagedUploadStore ?? null;
|
|
83
|
+
if (!store) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
error: 'stagedUploadIds require hosted Redis staged upload store.',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
let origin;
|
|
90
|
+
let secret;
|
|
91
|
+
try {
|
|
92
|
+
origin = ctx.publicOrigin ?? getPublicOrigin();
|
|
93
|
+
secret = getUploadHmacSecret();
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
return {
|
|
97
|
+
ok: false,
|
|
98
|
+
error: err instanceof Error ? err.message : String(err),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
for (const uploadId of stagedIds) {
|
|
102
|
+
try {
|
|
103
|
+
const peeked = await store.peekFile(ctx.userId, uploadId);
|
|
104
|
+
const record = await store.getRecord(ctx.userId, uploadId);
|
|
105
|
+
const exp = Math.floor(Date.now() / 1000) + remainingTtlSeconds(record?.createdAt ?? Date.now());
|
|
106
|
+
const url = buildStagedDownloadUrl(origin, uploadId, ctx.userId, exp, secret);
|
|
107
|
+
files.push({
|
|
108
|
+
sourceName: peeked.fileName,
|
|
109
|
+
url,
|
|
110
|
+
mime: peeked.mimeType,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
return {
|
|
115
|
+
ok: false,
|
|
116
|
+
error: err instanceof Error
|
|
117
|
+
? `Staged upload ${uploadId}: ${err.message}`
|
|
118
|
+
: `Staged upload ${uploadId} is not ready.`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (files.length === 0) {
|
|
124
|
+
return { ok: false, error: 'No files to prepare.' };
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
ok: true,
|
|
128
|
+
source: { type: 'https_urls', files },
|
|
129
|
+
folderId: hasStaged ? `staged:${String(stagedIds.length)}` : 'https',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=prepare-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-source.js","sourceRoot":"","sources":["../../src/media-pipeline/prepare-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export declare function getUploadHmacSecret(): string;
|
|
2
2
|
export declare function buildUploadSignaturePayload(uploadId: string, userId: string, exp: number): string;
|
|
3
|
+
export declare function buildDownloadSignaturePayload(uploadId: string, userId: string, exp: number): string;
|
|
3
4
|
export declare function signUploadUrl(uploadId: string, userId: string, exp: number, secret: string): string;
|
|
4
5
|
export declare function verifyUploadSignature(uploadId: string, userId: string, exp: number, sig: string, secret: string): boolean;
|
|
5
6
|
export declare function buildStagedUploadUrl(origin: string, uploadId: string, userId: string, exp: number, secret: string): string;
|
|
7
|
+
export declare function signDownloadUrl(uploadId: string, userId: string, exp: number, secret: string): string;
|
|
8
|
+
export declare function verifyDownloadSignature(uploadId: string, userId: string, exp: number, sig: string, secret: string): boolean;
|
|
9
|
+
export declare function buildStagedDownloadUrl(origin: string, uploadId: string, userId: string, exp: number, secret: string): string;
|
|
6
10
|
//# sourceMappingURL=hmac.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hmac.d.ts","sourceRoot":"","sources":["../../src/staged-upload/hmac.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjG;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CAGR;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,OAAO,CAeT;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CASR"}
|
|
1
|
+
{"version":3,"file":"hmac.d.ts","sourceRoot":"","sources":["../../src/staged-upload/hmac.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjG;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,MAAM,CAER;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CAGR;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,OAAO,CAeT;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CASR;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CAGR;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,OAAO,CAeT;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,MAAM,CAUR"}
|
|
@@ -9,6 +9,9 @@ export function getUploadHmacSecret() {
|
|
|
9
9
|
export function buildUploadSignaturePayload(uploadId, userId, exp) {
|
|
10
10
|
return `${uploadId}:${userId}:${String(exp)}`;
|
|
11
11
|
}
|
|
12
|
+
export function buildDownloadSignaturePayload(uploadId, userId, exp) {
|
|
13
|
+
return `get:${uploadId}:${userId}:${String(exp)}`;
|
|
14
|
+
}
|
|
12
15
|
export function signUploadUrl(uploadId, userId, exp, secret) {
|
|
13
16
|
const payload = buildUploadSignaturePayload(uploadId, userId, exp);
|
|
14
17
|
return crypto.createHmac('sha256', secret).update(payload).digest('hex');
|
|
@@ -40,4 +43,36 @@ export function buildStagedUploadUrl(origin, uploadId, userId, exp, secret) {
|
|
|
40
43
|
});
|
|
41
44
|
return `${origin.replace(/\/$/, '')}/api/staged-upload?${params.toString()}`;
|
|
42
45
|
}
|
|
46
|
+
export function signDownloadUrl(uploadId, userId, exp, secret) {
|
|
47
|
+
const payload = buildDownloadSignaturePayload(uploadId, userId, exp);
|
|
48
|
+
return crypto.createHmac('sha256', secret).update(payload).digest('hex');
|
|
49
|
+
}
|
|
50
|
+
export function verifyDownloadSignature(uploadId, userId, exp, sig, secret) {
|
|
51
|
+
if (!sig || !uploadId || !userId) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const expected = signDownloadUrl(uploadId, userId, exp, secret);
|
|
55
|
+
try {
|
|
56
|
+
const expectedBuf = Buffer.from(expected, 'hex');
|
|
57
|
+
const actualBuf = Buffer.from(sig, 'hex');
|
|
58
|
+
if (expectedBuf.length !== actualBuf.length) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return crypto.timingSafeEqual(expectedBuf, actualBuf);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function buildStagedDownloadUrl(origin, uploadId, userId, exp, secret) {
|
|
68
|
+
const sig = signDownloadUrl(uploadId, userId, exp, secret);
|
|
69
|
+
const params = new URLSearchParams({
|
|
70
|
+
id: uploadId,
|
|
71
|
+
uid: userId,
|
|
72
|
+
exp: String(exp),
|
|
73
|
+
sig,
|
|
74
|
+
op: 'get',
|
|
75
|
+
});
|
|
76
|
+
return `${origin.replace(/\/$/, '')}/api/staged-upload?${params.toString()}`;
|
|
77
|
+
}
|
|
43
78
|
//# sourceMappingURL=hmac.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hmac.js","sourceRoot":"","sources":["../../src/staged-upload/hmac.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAEtC,MAAM,UAAU,mBAAmB;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,EAAE,IAAI,EAAE,CAAC;IACjE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,QAAgB,EAAE,MAAc,EAAE,GAAW;IACvF,OAAO,GAAG,QAAQ,IAAI,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,MAAc,EACd,GAAW,EACX,MAAc;IAEd,MAAM,OAAO,GAAG,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,QAAgB,EAChB,MAAc,EACd,GAAW,EACX,GAAW,EACX,MAAc;IAEd,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1C,IAAI,WAAW,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,QAAgB,EAChB,MAAc,EACd,GAAW,EACX,MAAc;IAEd,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,EAAE,EAAE,QAAQ;QACZ,GAAG,EAAE,MAAM;QACX,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC;QAChB,GAAG;KACJ,CAAC,CAAC;IACH,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,sBAAsB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC/E,CAAC"}
|
|
1
|
+
{"version":3,"file":"hmac.js","sourceRoot":"","sources":["../../src/staged-upload/hmac.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/staged-upload/request.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/staged-upload/request.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,yBAAyB,CAAC,CAsCpC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { requiresPipelineEncode } from '../contentful/pipeline-encode-gate.js';
|
|
1
2
|
import { getPublicOrigin } from '../hosted/oauth/config.js';
|
|
2
3
|
import { buildStagedUploadUrl, getUploadHmacSecret } from './hmac.js';
|
|
3
4
|
import { hostedStagedMaxBytes, STAGED_UPLOAD_TTL_SECONDS } from './limits.js';
|
|
@@ -15,17 +16,19 @@ export async function createStagedUploadRequest(store, params) {
|
|
|
15
16
|
const origin = getPublicOrigin();
|
|
16
17
|
const exp = Math.floor(Date.now() / 1000) + STAGED_UPLOAD_TTL_SECONDS;
|
|
17
18
|
const uploadUrl = buildStagedUploadUrl(origin, uploadId, params.userId, exp, secret);
|
|
18
|
-
const consumeArgs =
|
|
19
|
-
'
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
const consumeArgs = requiresPipelineEncode(params.mimeType, params.fileName)
|
|
20
|
+
? ['media', 'prepare', '--staged-ids', uploadId]
|
|
21
|
+
: [
|
|
22
|
+
'asset',
|
|
23
|
+
'upload',
|
|
24
|
+
'--staged',
|
|
25
|
+
uploadId,
|
|
26
|
+
'--mime',
|
|
27
|
+
params.mimeType,
|
|
28
|
+
'--file-name',
|
|
29
|
+
params.fileName,
|
|
30
|
+
...(params.title ? ['--title', params.title] : []),
|
|
31
|
+
];
|
|
29
32
|
const curlCommand = `curl -f -X POST -F ${shellQuote(`file=@/path/to/${params.fileName}`)} ${shellQuote(uploadUrl)}`;
|
|
30
33
|
return {
|
|
31
34
|
uploadId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/staged-upload/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAY9E,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAAwB,EACxB,MAAuC;IAEvC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC;QACzC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,yBAAyB,CAAC;IACtE,MAAM,SAAS,GAAG,oBAAoB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAErF,MAAM,WAAW,GAAG;
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/staged-upload/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAY9E,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAAwB,EACxB,MAAuC;IAEvC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC;QACzC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,yBAAyB,CAAC;IACtE,MAAM,SAAS,GAAG,oBAAoB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAErF,MAAM,WAAW,GAAG,sBAAsB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;QAC1E,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,CAAC;QAChD,CAAC,CAAC;YACE,OAAO;YACP,QAAQ;YACR,UAAU;YACV,QAAQ;YACR,QAAQ;YACR,MAAM,CAAC,QAAQ;YACf,aAAa;YACb,MAAM,CAAC,QAAQ;YACf,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC;IAEN,MAAM,WAAW,GAAG,sBAAsB,UAAU,CAAC,kBAAkB,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;IAErH,OAAO;QACL,QAAQ;QACR,SAAS;QACT,SAAS,EAAE,yBAAyB;QACpC,SAAS,EAAE,GAAG;QACd,QAAQ,EAAE,oBAAoB,EAAE;QAChC,WAAW;QACX,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -14,6 +14,8 @@ export declare class StagedUploadStore {
|
|
|
14
14
|
}): Promise<string>;
|
|
15
15
|
storeFile(userId: string, uploadId: string, buffer: Buffer, mimeType: string): Promise<StagedUploadRecord>;
|
|
16
16
|
consume(userId: string, uploadId: string): Promise<StagedUploadConsumeResult>;
|
|
17
|
+
/** Read staged bytes without deleting (pipeline fetch). */
|
|
18
|
+
peekFile(userId: string, uploadId: string): Promise<StagedUploadConsumeResult>;
|
|
17
19
|
getRecord(userId: string, uploadId: string): Promise<StagedUploadRecord | null>;
|
|
18
20
|
}
|
|
19
21
|
//# sourceMappingURL=store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/staged-upload/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAO/D,OAAO,KAAK,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA0BhF,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF5B,YACmB,KAAK,EAAE,WAAW,EAClB,SAAS,SAAa,EACrC;IAEJ,OAAO,CAAC,OAAO;IAIT,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnD;IAEK,aAAa,CAAC,MAAM,EAAE;QAC1B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClB;IAEK,SAAS,CACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CA8B7B;IAEK,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAqBlF;IAEK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEpF;CACF"}
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/staged-upload/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAO/D,OAAO,KAAK,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA0BhF,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF5B,YACmB,KAAK,EAAE,WAAW,EAClB,SAAS,SAAa,EACrC;IAEJ,OAAO,CAAC,OAAO;IAIT,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnD;IAEK,aAAa,CAAC,MAAM,EAAE;QAC1B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClB;IAEK,SAAS,CACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CA8B7B;IAEK,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAqBlF;IAED,2DAA2D;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAgBnF;IAEK,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEpF;CACF"}
|
|
@@ -117,6 +117,24 @@ export class StagedUploadStore {
|
|
|
117
117
|
byteLength: buffer.length,
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
|
+
/** Read staged bytes without deleting (pipeline fetch). */
|
|
121
|
+
async peekFile(userId, uploadId) {
|
|
122
|
+
const existing = parseRecord(await this.redis.get(this.fullKey(userId, uploadId)));
|
|
123
|
+
if (!existing || existing.userId !== userId || existing.uploadId !== uploadId) {
|
|
124
|
+
throw new Error('Staged upload not found or expired.');
|
|
125
|
+
}
|
|
126
|
+
if (existing.status !== 'ready' || !existing.dataBase64) {
|
|
127
|
+
throw new Error('Staged upload has no file data yet. POST the file to uploadUrl first.');
|
|
128
|
+
}
|
|
129
|
+
const buffer = Buffer.from(existing.dataBase64, 'base64');
|
|
130
|
+
assertUploadBufferSize(buffer);
|
|
131
|
+
return {
|
|
132
|
+
buffer,
|
|
133
|
+
fileName: existing.fileName,
|
|
134
|
+
mimeType: existing.mimeType,
|
|
135
|
+
byteLength: buffer.length,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
120
138
|
async getRecord(userId, uploadId) {
|
|
121
139
|
return parseRecord(await this.redis.get(this.fullKey(userId, uploadId)));
|
|
122
140
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/staged-upload/store.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/staged-upload/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
## Prerequisites
|
|
16
16
|
|
|
17
|
-
- Fetch package materials (Google Drive MCP, paste, Figma link, zip, production ref, or
|
|
17
|
+
- Fetch package materials (Google Drive MCP, paste, Figma link, zip, production ref, **or designer HTML**)
|
|
18
18
|
- Read `cms-edit://customer/components-index`, `routing`, and for articles **`articles`**
|
|
19
|
+
- **Designer HTML / interactive prototype:** if `cms-edit://customer/task-create-html-component` (or another site HtmlComponent playbook) exists, **switch to that playbook** and stop this one. Otherwise follow the HtmlComponent fork in Phase 2 — do not flatten custom CSS/JS/scroll into registered cards.
|
|
19
20
|
- **Non-trivial packages:** complete **`task-source-readiness-review`** first (inventory → beat sheet → verdict → light human yes)
|
|
20
21
|
|
|
21
22
|
## Steps
|
|
@@ -38,8 +39,12 @@
|
|
|
38
39
|
### Phase 2 — Plan and create
|
|
39
40
|
|
|
40
41
|
1. Read `cms-edit://customer/tasks-index` and relevant playbooks (`articles` / `pages`).
|
|
41
|
-
2.
|
|
42
|
-
|
|
42
|
+
2. **Per-section mapping:**
|
|
43
|
+
- If **layout and interaction** match a registered type (e.g. FAQ accordion → FAQs), use that type.
|
|
44
|
+
- If the source is custom HTML/JS, sticky/scroll, diagrams, or a private layout shell, and this space has `htmlComponent`, map that beat to **`htmlComponent`** — not cards/lists that only match the copy.
|
|
45
|
+
- Mixed pages are expected. Merge consecutive custom sections that share CSS/JS/sticky into **one** HtmlComponent. Do not emit one HtmlComponent per `<section>`.
|
|
46
|
+
- Prefer **source order** over CMS convenience (do not invent side-by-side pairs unless the source is a true pair).
|
|
47
|
+
3. **Propose plan** (can reuse the soft-proof): slug, title, template/article type, ordered component list (registered **and** `htmlComponent` where needed), gap/placeholder list, **asset map** — **ask user to confirm** with a light **yes** if not already confirmed. For HtmlComponent beats: extract `data:` media first; run `schema htmlComponent` for this space’s field IDs (`html` vs `htmlContent`).
|
|
43
48
|
4. For pages: `list --type template` — pick template; check template `preContent` / `postContent` so heroes are not duplicated.
|
|
44
49
|
5. For articles: resolve `articleType`; apply site SEO and lab rules from `articles` playbook.
|
|
45
50
|
6. Build `create from-json` payload **or** prefer incremental `open` → `add` / `set` / `rtf` for large multi-block work. Link visuals using the pack map from Phase 1.
|
|
@@ -64,6 +69,7 @@ Use MCP prompts `cms_edit_create_from_doc` or `cms_edit_create_article_from_doc`
|
|
|
64
69
|
- Asset upload without reuse check (see **Media** capability)
|
|
65
70
|
- Mid-article ffmpeg / Drive size thrash — use **`task-media-pipeline-prepare`** first
|
|
66
71
|
- Inventing layout, section titles, or pair collections absent from the source
|
|
72
|
+
- Flattening designer HTML / custom interaction into registered cards because the copy looks like a card grid
|
|
67
73
|
|
|
68
74
|
## Related resources
|
|
69
75
|
|
|
@@ -75,3 +81,4 @@ Use MCP prompts `cms_edit_create_from_doc` or `cms_edit_create_article_from_doc`
|
|
|
75
81
|
- `task-create-page`
|
|
76
82
|
- `task-media-reuse-and-upload`
|
|
77
83
|
- `task-preview-verify`
|
|
84
|
+
- Site HtmlComponent playbook when present (`cms-edit://customer/task-create-html-component`)
|
|
@@ -33,10 +33,13 @@ Normalize a **folder of designer masters** into short-lived **public HTTPS URLs*
|
|
|
33
33
|
|
|
34
34
|
| Situation | Action |
|
|
35
35
|
|-----------|--------|
|
|
36
|
-
| Drive
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
36
|
+
| Drive folder of masters | This task with `driveFolderUrl` |
|
|
37
|
+
| Staged files (curl after `cms_edit_request_staged_upload`) | This task with `stagedUploadIds` — one prepare for the batch |
|
|
38
|
+
| Public HTTPS on allowed hosts | This task with `httpsUrls` |
|
|
39
|
+
| Single SVG/PDF/Lottie | `task-media-reuse-and-upload` asset upload --staged |
|
|
40
|
+
| Prior prepare already reached `succeeded` + catalog | **Reuse that jobId** — do not re-prepare |
|
|
41
|
+
|
|
42
|
+
Do **not** use `asset upload --staged/--base64` for jpeg/png/webp/gif/mp4. **Video** must use **import** (not `asset upload --url`, even on a Blob ready host). Raster `--url` is allowed only for pipeline ready image hosts.
|
|
40
43
|
|
|
41
44
|
## Steps (agent — single auth)
|
|
42
45
|
|
|
@@ -44,6 +47,8 @@ Normalize a **folder of designer masters** into short-lived **public HTTPS URLs*
|
|
|
44
47
|
|
|
45
48
|
Call MCP tool **`cms_edit_media`**:
|
|
46
49
|
|
|
50
|
+
Drive:
|
|
51
|
+
|
|
47
52
|
```json
|
|
48
53
|
{
|
|
49
54
|
"action": "prepare",
|
|
@@ -51,23 +56,27 @@ Call MCP tool **`cms_edit_media`**:
|
|
|
51
56
|
"profile": "case-study-v1",
|
|
52
57
|
"sourceNames": [
|
|
53
58
|
"BusinessCards copy.jpg",
|
|
54
|
-
"ArcticDB x3 Screens Tablet-1920.mp4"
|
|
55
|
-
"ADB_Macbook_HomeLoop.mp4"
|
|
59
|
+
"ArcticDB x3 Screens Tablet-1920.mp4"
|
|
56
60
|
]
|
|
57
61
|
}
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
Staged (after curl PUT/POST to each `uploadUrl`):
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"action": "prepare",
|
|
69
|
+
"stagedUploadIds": ["<uploadId1>", "<uploadId2>"]
|
|
70
|
+
}
|
|
71
|
+
```
|
|
65
72
|
|
|
66
73
|
CLI:
|
|
67
74
|
|
|
68
75
|
```bash
|
|
69
76
|
cms-edit media prepare --drive-folder "https://drive.google.com/drive/folders/…" \
|
|
70
77
|
--source-names "BusinessCards copy.jpg,ADB_Macbook_HomeLoop.mp4"
|
|
78
|
+
|
|
79
|
+
cms-edit media prepare --staged-ids "id1,id2"
|
|
71
80
|
```
|
|
72
81
|
|
|
73
82
|
Expect `{ ok: true, jobId, status: "queued", pollHint }`.
|
|
@@ -103,7 +112,7 @@ or
|
|
|
103
112
|
|
|
104
113
|
- Do **not** invent assets for gaps.
|
|
105
114
|
- Do **not** wait 5–10+ minutes on `provisioning`.
|
|
106
|
-
- Do **not** thrash prepares (rate limit
|
|
115
|
+
- Do **not** thrash prepares (rate limit **100**/hour, concurrent max typically **4** per user).
|
|
107
116
|
- On `429` / too many concurrent: call `status` once on any stuck old `jobId` (to free slots if past grace), then prepare again **once**.
|
|
108
117
|
- Prefer **reusing** a job that already reached `succeeded` + catalog over preparing again for the same Drive folder.
|
|
109
118
|
|
|
@@ -117,9 +126,10 @@ Each asset includes:
|
|
|
117
126
|
|
|
118
127
|
| Field | Use |
|
|
119
128
|
|-------|-----|
|
|
120
|
-
| `readyUrl` |
|
|
129
|
+
| `readyUrl` | Import via `cms_edit_media` import only (CMA gate: pipeline ready hosts) |
|
|
121
130
|
| `previewUrl` / `posterUrl` | Agent vision for **title / fileName / alt** (when present) |
|
|
122
|
-
| `altDraft` / `titleDraft` | Filename seeds only — improve before
|
|
131
|
+
| `altDraft` / `titleDraft` | Filename seeds only — improve before import |
|
|
132
|
+
| `role` `gif-converted` | Animated GIF became MP4 — Media mute-loop, not `featuredImage` |
|
|
123
133
|
|
|
124
134
|
### 4. Import into Contentful (reuse-first)
|
|
125
135
|
|
|
@@ -146,9 +156,10 @@ After drafting titles/alts from **previewUrl** / **posterUrl**:
|
|
|
146
156
|
}
|
|
147
157
|
```
|
|
148
158
|
|
|
149
|
-
1. Always **`dryRun: true` first** — check `existing: true/false` per asset (reuse is by **fileName**).
|
|
150
|
-
2.
|
|
151
|
-
3.
|
|
159
|
+
1. Always **`dryRun: true` first** — check `existing: true/false` per asset (reuse is by **fileName**). Missing alt on new files is reported as `altFailures` / per-row `alt_required`; dryRun still returns `ok: true`.
|
|
160
|
+
2. New uploads **fail** without review-quality `overrides[].alt` when you import for real (not empty, not the filename).
|
|
161
|
+
3. When you need **new** assets instead of reusing prior runs, set `overrides[].fileName` to unique names.
|
|
162
|
+
4. Then import without `dryRun`.
|
|
152
163
|
|
|
153
164
|
CLI:
|
|
154
165
|
`cms-edit media import --job <id> [--dry-run] [--with-media] [--only-with-overrides] [--source-names a.jpg,b.jpg] [--exclude-source-names x.jpg] [--overrides-json '[…]']`
|
|
@@ -164,7 +175,7 @@ Import:
|
|
|
164
175
|
`cms_edit ["set", "@cN", "visual", "<mediaId>", "--link"]`
|
|
165
176
|
— **never** `add … --target visual` (`add` only supports content **arrays**).
|
|
166
177
|
|
|
167
|
-
Manual `asset upload --url`
|
|
178
|
+
Manual `asset upload --url` is allowed only for **pipeline-ready images** (Vercel Blob / `MEDIA_PIPELINE_READY_HOSTS`, https in production). **Video** must use **import**. Always prefer import for new masters.
|
|
168
179
|
|
|
169
180
|
### Hardening notes (for agents)
|
|
170
181
|
|
|
@@ -32,30 +32,39 @@
|
|
|
32
32
|
|
|
33
33
|
## Upload only when no match
|
|
34
34
|
|
|
35
|
-
###
|
|
35
|
+
### Raster images and video (required)
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Encode via **`task-media-pipeline-prepare`**. Intake can be:
|
|
38
38
|
|
|
39
|
-
1.
|
|
40
|
-
2.
|
|
39
|
+
1. A **Drive folder**, or
|
|
40
|
+
2. **Staged upload** (4 MB): `cms_edit_request_staged_upload` → curl → `cms_edit_media` prepare with `stagedUploadIds` (see returned `consumeArgs`), or
|
|
41
|
+
3. **httpsUrls** on pipeline-allowed hosts
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
Then wait → catalog → **import** with `overrides[].alt`. Do **not** `asset upload --staged/--base64` for jpeg/png/webp/gif/mp4. Do **not** `asset upload --url` for **video** (import only). Raster `--url` only for pipeline ready image hosts.
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
Animated GIFs become **MP4** (`gif-converted`) — attach as mute-loop Media / video visual, not `featuredImage`.
|
|
46
|
+
|
|
47
|
+
### SVG, PDF, Lottie
|
|
48
|
+
|
|
49
|
+
These may skip the pipeline. On hosted MCP use staged upload then `asset upload --staged`.
|
|
50
|
+
|
|
51
|
+
### Hosted MCP (SVG/PDF/Lottie only)
|
|
52
|
+
|
|
53
|
+
**Always use staged upload** for ad-hoc binaries. Do not pass base64 in `cms_edit` args — hosted MCP rejects `asset upload --base64`.
|
|
45
54
|
|
|
46
55
|
1. `cms_edit_request_staged_upload` with `fileName`, `mimeType`, optional `byteLength`, optional `title`
|
|
47
56
|
2. Run the returned `curlCommand` in a shell (POST file to `uploadUrl`)
|
|
48
|
-
3. `
|
|
57
|
+
3. Follow `consumeArgs`: **media prepare** for photos/video; **asset upload --staged** for SVG/PDF/Lottie
|
|
49
58
|
|
|
50
59
|
Rules:
|
|
51
60
|
|
|
52
|
-
- Staged upload keeps binary **out of MCP args**
|
|
53
|
-
- Hosted limit: **4 MB** per file; **1000 upload URLs per user per hour**; TTL **60 minutes
|
|
54
|
-
-
|
|
55
|
-
- Upload alone does **not** attach the asset — follow with **link + save** (below)
|
|
61
|
+
- Staged upload keeps binary **out of MCP args**
|
|
62
|
+
- Hosted limit: **4 MB** per file; **1000 upload URLs per user per hour**; TTL **60 minutes**
|
|
63
|
+
- Raster/video staged files stay in Redis until pipeline fetches them (GET); they are not written to CMA
|
|
64
|
+
- Upload/import alone does **not** attach the asset — follow with **link + save** (below)
|
|
56
65
|
- Use `--if-exists-by-filename` (with `--file-name`) to avoid duplicate assets when re-running
|
|
57
66
|
|
|
58
|
-
After
|
|
67
|
+
After import, create a Media wrapper **only when none exists** for that asset:
|
|
59
68
|
|
|
60
69
|
```
|
|
61
70
|
cms_edit ["list", "--type", "media", "--asset-id", "<newPortraitAssetId>"]
|
|
@@ -68,17 +77,11 @@ To rename an existing Media wrapper: `cms_edit ["batch", "set", "<media-entry-id
|
|
|
68
77
|
|
|
69
78
|
Avoid `asset upload --with-media` when multiple entries will share the same image (e.g. news composites) — it creates duplicate Media entries. Upload the asset only, then one shared `create media`, then link the media ID on each entry.
|
|
70
79
|
|
|
71
|
-
**Prefer
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
cms_edit ["asset", "upload", "--url", "https://<public-https-url>/file.png", "--mime", "image/png", "--file-name", "headshot-name-1200.png", "--title", "…", "--if-exists-by-filename"]
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
The URL must be fetchable by the hosted MCP server. Do not use local-only URLs.
|
|
80
|
+
**Prefer pipeline import** for encoded masters. **Video** must use import. `asset upload --url` is only for **pipeline ready images** (or SVG/PDF/Lottie). A random PNG or Contentful CDN master is rejected.
|
|
78
81
|
|
|
79
82
|
### Local CLI (only when user approves)
|
|
80
83
|
|
|
81
|
-
Hosted MCP uses `cms_edit_request_staged_upload` then `asset upload --staged
|
|
84
|
+
Hosted MCP uses `cms_edit_request_staged_upload` then **media prepare** for raster/video (or `asset upload --staged` for SVG/PDF/Lottie). Do not use the local `cms-edit` CLI for uploads.
|
|
82
85
|
|
|
83
86
|
## Link uploaded asset to an entry
|
|
84
87
|
|
|
@@ -45,11 +45,11 @@ If title, order, or hero asset **conflict** and the user has not decided → **N
|
|
|
45
45
|
|---|------|-------------------|-----------------------------------|----------------------|
|
|
46
46
|
| 1 | … | … | … | … |
|
|
47
47
|
|
|
48
|
-
3. **Build beat sheet** — ordered narrative + visual beats
|
|
48
|
+
3. **Build beat sheet** — ordered narrative + visual beats. For each beat: use a **registered** component/collection type when **layout and interaction** match (`components-index` / site playbook). If the source is designer HTML, custom CSS/JS, sticky/scroll, or a diagram that no registered type can reproduce, map to **`htmlComponent`** when that type exists in the space (and follow a site `task-create-html-component` playbook if present). Mixed stacks are valid. Merge consecutive custom HTML beats that share CSS/JS. Prefer **source order** over CMS convenience.
|
|
49
49
|
4. **Score verdict** using the threshold below.
|
|
50
50
|
5. **Post one-screen soft-proof** — numbered final `content` (or page stack) order + gap list + verdict.
|
|
51
51
|
6. **Ask for a light human confirm** — accept **yes** / **go** / **proceed** (or equivalent). Do not build on silence if the package is non-trivial.
|
|
52
|
-
7. On **GO** or **GO-WITH-GAPS** + yes → hand off to `task-create-from-document` / `task-create-article` / `task-create-page` with the soft-proof as the plan.
|
|
52
|
+
7. On **GO** or **GO-WITH-GAPS** + yes → hand off to `task-create-html-component` (if the site has it and the source is designer HTML), otherwise `task-create-from-document` / `task-create-article` / `task-create-page` with the soft-proof as the plan.
|
|
53
53
|
8. On **NO-GO** → stop; list what is blocking (do not invent structure to unblock).
|
|
54
54
|
|
|
55
55
|
## Gap threshold
|
|
@@ -75,7 +75,7 @@ If title, order, or hero asset **conflict** and the user has not decided → **N
|
|
|
75
75
|
## Faithful structure rules
|
|
76
76
|
|
|
77
77
|
1. **Do not rewrite copy** — structure and place only; flag issues for the human.
|
|
78
|
-
2. **Design sequence beats CMS convenience** — do not invent pair/side-by-side collections unless the source is a true pair.
|
|
78
|
+
2. **Design sequence beats CMS convenience** — do not invent pair/side-by-side collections unless the source is a true pair. If a beat is custom HTML/JS/scroll/diagram and `htmlComponent` exists, **remap that beat to `htmlComponent` and continue** (GO / GO-WITH-GAPS) — do not NO-GO the package and do not flatten it onto cards.
|
|
79
79
|
3. **Placeholders beat reordering** — keep the slot; label the gap (do not drop missing beats and renumber silently).
|
|
80
80
|
4. **Merge continuous prose** — do not split body-only blocks without a layout reason (art, quote, or design break between).
|
|
81
81
|
5. **Hero / template owns page H1** when the site template provides it — body headings only when the source has section titles.
|
|
@@ -114,3 +114,4 @@ Copy: unchanged from source (list any human decisions only)
|
|
|
114
114
|
- `task-media-pipeline-prepare`
|
|
115
115
|
- `task-media-reuse-and-upload`
|
|
116
116
|
- `task-preview-verify`
|
|
117
|
+
- Site `task-create-html-component` when present
|