@se-studio/contentful-cms 3.9.4 → 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 +6 -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/media-pipeline-prepare.md +29 -18
- package/docs/editor-tasks/media-reuse-and-upload.md +23 -20
- 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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"}
|
|
@@ -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
|
|
package/docs/mcp/hosted-guide.md
CHANGED
|
@@ -20,7 +20,7 @@ All `save` operations create **drafts only**. A human must review and publish in
|
|
|
20
20
|
| Tool | Purpose |
|
|
21
21
|
|------|---------|
|
|
22
22
|
| `cms_edit` | Run any cms-edit command via an `args` array |
|
|
23
|
-
| `cms_edit_request_staged_upload` |
|
|
23
|
+
| `cms_edit_request_staged_upload` | Presigned URL for binaries. Raster/video: then `cms_edit_media` prepare. SVG/PDF/Lottie: then `asset upload --staged` |
|
|
24
24
|
| `cms_edit_version` | Check the installed cms-edit version (no session required) |
|
|
25
25
|
| `cms_edit_help` | Guide topics (`overview`, `workflow`, `commands`, `troubleshooting`, `hosted`) **or** playbooks (`create-from-json`, `fields-component`, …) |
|
|
26
26
|
|
|
@@ -130,7 +130,7 @@ Always run `diff` before `save`. To abandon changes: `["discard"]`.
|
|
|
130
130
|
| Task | Where |
|
|
131
131
|
|------|-------|
|
|
132
132
|
| Edit copy, add sections, create pages/articles | **Agent + cms-edit** (drafts) |
|
|
133
|
-
| Upload new images and files | **Agent + cms-edit**
|
|
133
|
+
| Upload new images and files | **Agent + cms-edit** — search/reuse first; raster/video via `cms_edit_media` import |
|
|
134
134
|
| Publish approved drafts | **Contentful UI** |
|
|
135
135
|
| Edit copy directly in Contentful | **Avoid** — use cms-edit instead |
|
|
136
136
|
|
|
@@ -138,12 +138,13 @@ cms-edit saves **drafts only**. A colleague must **publish in Contentful** for c
|
|
|
138
138
|
|
|
139
139
|
## Asset upload (hosted MCP)
|
|
140
140
|
|
|
141
|
-
Hosted connectors have **no server filesystem** and **reject `asset upload --base64`**.
|
|
141
|
+
Hosted connectors have **no server filesystem** and **reject `asset upload --base64`**. Raster/video: staged intake then **media pipeline**. SVG/PDF/Lottie: staged then `asset upload --staged`.
|
|
142
142
|
|
|
143
143
|
| Source | When | Example |
|
|
144
144
|
|--------|------|---------|
|
|
145
|
-
| **Staged
|
|
146
|
-
| **`--url`**
|
|
145
|
+
| **Staged + pipeline** | jpeg/png/webp/gif/mp4 | `cms_edit_media` prepare `stagedUploadIds` → import (required for video) |
|
|
146
|
+
| **`--url`** | Pipeline-ready **images** only, or SVG/PDF | `["asset", "upload", "--url", "https://….blob.vercel-storage.com/ready.jpg"]` |
|
|
147
|
+
| **Staged consume** | SVG/PDF/Lottie | `asset upload --staged` |
|
|
147
148
|
|
|
148
149
|
**After upload:** note the returned asset `id`, attach to the entry (`asset set @root media <id>` for person portraits), then `diff` → `save`. Upload alone does not update entries.
|
|
149
150
|
|
|
@@ -168,10 +169,10 @@ Keeps binary **out of MCP tool args**. The agent uploads via `curl`, then passes
|
|
|
168
169
|
|
|
169
170
|
1. `cms_edit_request_staged_upload` with `fileName`, `mimeType`, optional `byteLength`, optional `title`
|
|
170
171
|
2. Run the returned `curlCommand` in a shell (POST multipart to `uploadUrl`)
|
|
171
|
-
3. `
|
|
172
|
-
4.
|
|
172
|
+
3. Follow `consumeArgs`: **media prepare** (`cms_edit_media` / `media prepare --staged-ids`) for jpeg/png/webp/gif/mp4; **asset upload --staged** for SVG/PDF/Lottie
|
|
173
|
+
4. For pipeline jobs: wait → catalog → **import** (required for video). Then link and save
|
|
173
174
|
|
|
174
|
-
Hosted limit: **4 MB** per staged file (Vercel body limit). Rate limit: **1000 upload URLs per user per hour**. TTL: **60 minutes
|
|
175
|
+
Hosted limit: **4 MB** per staged file (Vercel body limit). Rate limit: **1000 upload URLs per user per hour**. TTL: **60 minutes**. Raster/video staged files are intake (GET by the pipeline); they are not consumed into CMA.
|
|
175
176
|
|
|
176
177
|
## Featured images (articles)
|
|
177
178
|
|
package/package.json
CHANGED
package/skills/core/SKILL.md
CHANGED
|
@@ -31,7 +31,8 @@ Use this skill when you need to read or edit content in Contentful using **hoste
|
|
|
31
31
|
All `save` operations create **draft** versions. A human must review and publish in Contentful.
|
|
32
32
|
|
|
33
33
|
**Assets:** Upload **is** supported (`asset upload`). Default workflow: **search and reuse** existing assets first (`index sync` → `asset search`). When uploading:
|
|
34
|
-
- **
|
|
34
|
+
- **Raster/video:** `cms_edit_request_staged_upload` → curl → `cms_edit_media` prepare (`stagedUploadIds`) → wait → catalog → import with real alt. Never `asset upload --staged/--url/--base64` for jpeg/png/webp/gif/mp4.
|
|
35
|
+
- **SVG/PDF/Lottie:** `cms_edit_request_staged_upload` → curl → `asset upload --staged` (never `--base64`)
|
|
35
36
|
- Use a **sensible fileName** and **descriptive title** (and alt text where the site uses it)
|
|
36
37
|
- Avoid oversized images — width over **2000px** is usually wasteful for web (exact limits vary by project; check `asset audit` / media review guidance)
|
|
37
38
|
- Prefer `--if-exists-by-filename` to avoid duplicates
|
|
@@ -371,13 +372,8 @@ cms-edit asset search "hero background"
|
|
|
371
372
|
cms-edit asset search --filename istockphoto-123.jpg
|
|
372
373
|
cms-edit asset search --filename-match 'istockphoto-.*'
|
|
373
374
|
|
|
374
|
-
#
|
|
375
|
-
|
|
376
|
-
cms-edit asset upload --base64 "$B64" --mime image/png --file-name poster.png
|
|
377
|
-
|
|
378
|
-
# Hosted MCP — always staged upload for binary files
|
|
379
|
-
# cms_edit_request_staged_upload → curl uploadUrl → consumeArgs
|
|
380
|
-
# cms_edit ["asset", "upload", "--staged", "<uploadId>", "--mime", "image/png", "--file-name", "photo.png"]
|
|
375
|
+
# Raster/video: cms_edit_media prepare → wait → catalog → import (video: import only).
|
|
376
|
+
# SVG/PDF/Lottie: cms_edit_request_staged_upload → curl → asset upload --staged
|
|
381
377
|
|
|
382
378
|
# Upload and create a Media wrapper in one step (--media-name defaults to asset title)
|
|
383
379
|
cms-edit asset upload ./figure.png --with-media --media-position Middle
|