@se-studio/contentful-cms 3.14.0 → 3.15.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 +20 -0
- package/README.md +6 -2
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +15 -101
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/asset.d.ts.map +1 -1
- package/dist/commands/asset.js +310 -3
- package/dist/commands/asset.js.map +1 -1
- package/dist/commands/create-taxonomy.d.ts +11 -0
- package/dist/commands/create-taxonomy.d.ts.map +1 -1
- package/dist/commands/create-taxonomy.js +45 -4
- package/dist/commands/create-taxonomy.js.map +1 -1
- package/dist/contentful/asset-concepts.d.ts +53 -0
- package/dist/contentful/asset-concepts.d.ts.map +1 -0
- package/dist/contentful/asset-concepts.js +137 -0
- package/dist/contentful/asset-concepts.js.map +1 -0
- package/dist/contentful/asset-replace.d.ts +29 -0
- package/dist/contentful/asset-replace.d.ts.map +1 -0
- package/dist/contentful/asset-replace.js +57 -0
- package/dist/contentful/asset-replace.js.map +1 -0
- package/dist/contentful/assets.d.ts +11 -0
- package/dist/contentful/assets.d.ts.map +1 -1
- package/dist/contentful/assets.js +48 -2
- package/dist/contentful/assets.js.map +1 -1
- package/dist/contentful/client.d.ts +9 -0
- package/dist/contentful/client.d.ts.map +1 -1
- package/dist/contentful/client.js +27 -0
- package/dist/contentful/client.js.map +1 -1
- package/dist/contentful/cma-user-agent.d.ts +1 -1
- package/dist/contentful/entry-fields.d.ts +10 -0
- package/dist/contentful/entry-fields.d.ts.map +1 -1
- package/dist/contentful/entry-fields.js +23 -1
- package/dist/contentful/entry-fields.js.map +1 -1
- package/dist/contentful/linkedEntryFields.d.ts.map +1 -1
- package/dist/contentful/linkedEntryFields.js +1 -0
- package/dist/contentful/linkedEntryFields.js.map +1 -1
- package/dist/contentful/media-dimensions.d.ts +7 -0
- package/dist/contentful/media-dimensions.d.ts.map +1 -0
- package/dist/contentful/media-dimensions.js +169 -0
- package/dist/contentful/media-dimensions.js.map +1 -0
- package/dist/contentful/upload-limits.d.ts +10 -4
- package/dist/contentful/upload-limits.d.ts.map +1 -1
- package/dist/contentful/upload-limits.js +14 -7
- package/dist/contentful/upload-limits.js.map +1 -1
- package/dist/editor-pack/generate.js +2 -2
- package/dist/editor-pack/generate.js.map +1 -1
- package/dist/generated/help-topics.d.ts.map +1 -1
- package/dist/generated/help-topics.js +1 -1
- package/dist/generated/help-topics.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.js +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 +1 -1
- package/dist/mcp/tools/media.d.ts.map +1 -1
- package/dist/mcp/tools/media.js +3 -3
- 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 +4 -3
- package/dist/mcp/tools/staged-upload.js.map +1 -1
- package/dist/session/refs.d.ts.map +1 -1
- package/dist/session/refs.js +2 -0
- package/dist/session/refs.js.map +1 -1
- package/dist/staged-upload/direct-intake.d.ts +23 -0
- package/dist/staged-upload/direct-intake.d.ts.map +1 -0
- package/dist/staged-upload/direct-intake.js +71 -0
- package/dist/staged-upload/direct-intake.js.map +1 -0
- package/dist/staged-upload/intake-policy.d.ts +13 -0
- package/dist/staged-upload/intake-policy.d.ts.map +1 -0
- package/dist/staged-upload/intake-policy.js +37 -0
- package/dist/staged-upload/intake-policy.js.map +1 -0
- package/dist/staged-upload/request.d.ts +5 -1
- package/dist/staged-upload/request.d.ts.map +1 -1
- package/dist/staged-upload/request.js +31 -2
- package/dist/staged-upload/request.js.map +1 -1
- package/dist/staged-upload/types.d.ts +4 -0
- package/dist/staged-upload/types.d.ts.map +1 -1
- package/dist/validation/allowed-types.d.ts.map +1 -1
- package/dist/validation/allowed-types.js +12 -1
- package/dist/validation/allowed-types.js.map +1 -1
- package/docs/FUNCTIONAL_SPEC.md +1 -1
- package/docs/editor-tasks/media-pipeline-prepare.md +12 -2
- package/docs/editor-tasks/media-reuse-and-upload.md +40 -8
- package/docs/editor-tasks/taxonomy.md +2 -0
- package/docs/help/index.md +1 -1
- package/docs/mcp/hosted-guide.md +8 -6
- package/package.json +2 -1
- package/skills/core/SKILL.md +11 -5
- package/skills/editor-tasks/SKILL.md +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type StagedUploadKind } from './mime.js';
|
|
2
|
+
/** `function` POSTs through the Vercel route. `direct` is a presigned blob PUT. */
|
|
3
|
+
export type IntakeRoute = 'function' | 'direct';
|
|
4
|
+
export declare function intakeRoute(params: {
|
|
5
|
+
kind: StagedUploadKind;
|
|
6
|
+
mimeType: string;
|
|
7
|
+
fileName: string;
|
|
8
|
+
byteLength?: number;
|
|
9
|
+
}): IntakeRoute;
|
|
10
|
+
export declare function intakeMaxBytes(route: IntakeRoute): number;
|
|
11
|
+
/** Refuse a declared size the chosen route cannot accept. Missing size is checked at upload time. */
|
|
12
|
+
export declare function assertIntakeByteLength(route: IntakeRoute, byteLength: number | undefined): void;
|
|
13
|
+
//# sourceMappingURL=intake-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intake-policy.d.ts","sourceRoot":"","sources":["../../src/staged-upload/intake-policy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAErE,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEhD,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,WAAW,CAed;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAEzD;AAED,qGAAqG;AACrG,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAc/F"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isVideoUpload, requiresPipelineEncode } from '../contentful/pipeline-encode-gate.js';
|
|
2
|
+
import { DIRECT_INTAKE_MAX_BYTES } from '../contentful/upload-limits.js';
|
|
3
|
+
import { HOSTED_STAGED_MAX_BYTES } from './limits.js';
|
|
4
|
+
import { normalizeMimeType } from './mime.js';
|
|
5
|
+
export function intakeRoute(params) {
|
|
6
|
+
if (params.kind !== 'asset') {
|
|
7
|
+
return 'function';
|
|
8
|
+
}
|
|
9
|
+
const mime = normalizeMimeType(params.mimeType);
|
|
10
|
+
if (isVideoUpload(mime, params.fileName)) {
|
|
11
|
+
return 'direct';
|
|
12
|
+
}
|
|
13
|
+
if (!requiresPipelineEncode(mime, params.fileName)) {
|
|
14
|
+
return 'function';
|
|
15
|
+
}
|
|
16
|
+
if (params.byteLength !== undefined && params.byteLength > HOSTED_STAGED_MAX_BYTES) {
|
|
17
|
+
return 'direct';
|
|
18
|
+
}
|
|
19
|
+
return 'function';
|
|
20
|
+
}
|
|
21
|
+
export function intakeMaxBytes(route) {
|
|
22
|
+
return route === 'direct' ? DIRECT_INTAKE_MAX_BYTES : HOSTED_STAGED_MAX_BYTES;
|
|
23
|
+
}
|
|
24
|
+
/** Refuse a declared size the chosen route cannot accept. Missing size is checked at upload time. */
|
|
25
|
+
export function assertIntakeByteLength(route, byteLength) {
|
|
26
|
+
if (byteLength === undefined) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const max = intakeMaxBytes(route);
|
|
30
|
+
if (byteLength > max) {
|
|
31
|
+
const label = route === 'direct'
|
|
32
|
+
? `${String(DIRECT_INTAKE_MAX_BYTES / (1024 * 1024))}MB direct intake`
|
|
33
|
+
: `${String(HOSTED_STAGED_MAX_BYTES / (1024 * 1024))}MB hosted staged upload`;
|
|
34
|
+
throw new Error(`Declared byteLength ${String(byteLength)} exceeds the ${label} limit (${String(max)} bytes).`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=intake-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intake-policy.js","sourceRoot":"","sources":["../../src/staged-upload/intake-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAyB,MAAM,WAAW,CAAC;AAKrE,MAAM,UAAU,WAAW,CAAC,MAK3B;IACC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzC,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnD,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,GAAG,uBAAuB,EAAE,CAAC;QACnF,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,uBAAuB,CAAC;AAChF,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,sBAAsB,CAAC,KAAkB,EAAE,UAA8B;IACvF,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;QACrB,MAAM,KAAK,GACT,KAAK,KAAK,QAAQ;YAChB,CAAC,CAAC,GAAG,MAAM,CAAC,uBAAuB,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,kBAAkB;YACtE,CAAC,CAAC,GAAG,MAAM,CAAC,uBAAuB,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,yBAAyB,CAAC;QAClF,MAAM,IAAI,KAAK,CACb,uBAAuB,MAAM,CAAC,UAAU,CAAC,gBAAgB,KAAK,WAAW,MAAM,CAAC,GAAG,CAAC,UAAU,CAC/F,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DirectIntakeParams, type DirectIntakeResult } from './direct-intake.js';
|
|
1
2
|
import { type StagedUploadKind } from './mime.js';
|
|
2
3
|
import type { StagedUploadStore } from './store.js';
|
|
3
4
|
import type { StagedUploadRequestResult } from './types.js';
|
|
@@ -9,5 +10,8 @@ export interface CreateStagedUploadRequestParams {
|
|
|
9
10
|
title?: string;
|
|
10
11
|
kind?: StagedUploadKind | string;
|
|
11
12
|
}
|
|
12
|
-
export
|
|
13
|
+
export interface StagedUploadDeps {
|
|
14
|
+
createDirectIntake?: (params: DirectIntakeParams) => Promise<DirectIntakeResult>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createStagedUploadRequest(store: StagedUploadStore, params: CreateStagedUploadRequestParams, deps?: StagedUploadDeps): Promise<StagedUploadRequestResult>;
|
|
13
17
|
//# sourceMappingURL=request.d.ts.map
|
|
@@ -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":"AAEA,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EAExB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAkD,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAClG,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;IACf,IAAI,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAAC;CAClC;AAMD,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClF;AA4BD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,+BAA+B,EACvC,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,yBAAyB,CAAC,CA0DpC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { requiresPipelineEncode } from '../contentful/pipeline-encode-gate.js';
|
|
2
2
|
import { getPublicOrigin } from '../hosted/oauth/config.js';
|
|
3
|
+
import { createDirectIntakeUpload, directIntakeCurl, } from './direct-intake.js';
|
|
3
4
|
import { buildStagedUploadUrl, getUploadHmacSecret } from './hmac.js';
|
|
5
|
+
import { assertIntakeByteLength, intakeRoute } from './intake-policy.js';
|
|
4
6
|
import { hostedStagedMaxBytes, STAGED_UPLOAD_TTL_SECONDS } from './limits.js';
|
|
5
|
-
import { parseStagedUploadKind } from './mime.js';
|
|
7
|
+
import { isAllowedStagedMimeType, parseStagedUploadKind } from './mime.js';
|
|
6
8
|
function shellQuote(value) {
|
|
7
9
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
8
10
|
}
|
|
@@ -27,8 +29,34 @@ function buildConsumeArgs(kind, uploadId, params) {
|
|
|
27
29
|
...(params.title ? ['--title', params.title] : []),
|
|
28
30
|
];
|
|
29
31
|
}
|
|
30
|
-
export async function createStagedUploadRequest(store, params) {
|
|
32
|
+
export async function createStagedUploadRequest(store, params, deps = {}) {
|
|
31
33
|
const kind = parseStagedUploadKind(typeof params.kind === 'string' ? params.kind : undefined);
|
|
34
|
+
if (!isAllowedStagedMimeType(params.mimeType, kind)) {
|
|
35
|
+
throw new Error(`MIME type not allowed for staged upload (${kind}): ${params.mimeType}`);
|
|
36
|
+
}
|
|
37
|
+
const route = intakeRoute({
|
|
38
|
+
kind,
|
|
39
|
+
mimeType: params.mimeType,
|
|
40
|
+
fileName: params.fileName,
|
|
41
|
+
byteLength: params.byteLength,
|
|
42
|
+
});
|
|
43
|
+
assertIntakeByteLength(route, params.byteLength);
|
|
44
|
+
if (route === 'direct') {
|
|
45
|
+
await store.assertRateLimit(params.userId);
|
|
46
|
+
const createDirect = deps.createDirectIntake ?? createDirectIntakeUpload;
|
|
47
|
+
const direct = await createDirect(params);
|
|
48
|
+
return {
|
|
49
|
+
uploadId: direct.uploadId,
|
|
50
|
+
uploadUrl: direct.presignedUrl,
|
|
51
|
+
expiresIn: STAGED_UPLOAD_TTL_SECONDS,
|
|
52
|
+
expiresAt: direct.expiresAt,
|
|
53
|
+
maxBytes: direct.maxBytes,
|
|
54
|
+
curlCommand: directIntakeCurl(direct.presignedUrl, params.mimeType, params.fileName),
|
|
55
|
+
consumeArgs: ['media', 'prepare', '--https-urls', direct.publicUrl],
|
|
56
|
+
intake: 'direct',
|
|
57
|
+
publicUrl: direct.publicUrl,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
32
60
|
const uploadId = await store.createPending({
|
|
33
61
|
userId: params.userId,
|
|
34
62
|
fileName: params.fileName,
|
|
@@ -50,6 +78,7 @@ export async function createStagedUploadRequest(store, params) {
|
|
|
50
78
|
maxBytes: hostedStagedMaxBytes(),
|
|
51
79
|
curlCommand,
|
|
52
80
|
consumeArgs,
|
|
81
|
+
intake: 'function',
|
|
53
82
|
};
|
|
54
83
|
}
|
|
55
84
|
//# sourceMappingURL=request.js.map
|
|
@@ -1 +1 @@
|
|
|
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;AAC9E,OAAO,EAAE,qBAAqB,EAAyB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/staged-upload/request.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,10 @@ export interface StagedUploadRequestResult {
|
|
|
20
20
|
maxBytes: number;
|
|
21
21
|
curlCommand: string;
|
|
22
22
|
consumeArgs: string[];
|
|
23
|
+
/** `function` POSTs to the cms-edit route. `direct` PUTs to blob storage. */
|
|
24
|
+
intake: 'function' | 'direct';
|
|
25
|
+
/** Set when intake is `direct`. Pass this URL to media prepare after the PUT. */
|
|
26
|
+
publicUrl?: string;
|
|
23
27
|
}
|
|
24
28
|
export interface StagedUploadConsumeResult {
|
|
25
29
|
buffer: Buffer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/staged-upload/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/staged-upload/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,6EAA6E;IAC7E,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC9B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,CAAC;CACxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"allowed-types.d.ts","sourceRoot":"","sources":["../../src/validation/allowed-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sCAAsC,YACjD,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,OAAO,EACP,QAAQ,CACA,CAAC;AAEX,wBAAgB,0BAA0B,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAEzE;
|
|
1
|
+
{"version":3,"file":"allowed-types.d.ts","sourceRoot":"","sources":["../../src/validation/allowed-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sCAAsC,YACjD,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,OAAO,EACP,QAAQ,CACA,CAAC;AAEX,wBAAgB,0BAA0B,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAEzE;AAYD,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,mBAAmB,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CAoBf;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,mBAAmB,EAAE,MAAM,EAC3B,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,IAAI,EAAE,QAAQ,GAAG,MAAM,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAiF9D"}
|
|
@@ -21,6 +21,7 @@ export function isAllowedContentTypeForAdd(contentTypeId) {
|
|
|
21
21
|
const PAGE_CONTENT_FIELDS = ['topContent', 'content', 'bottomContent'];
|
|
22
22
|
const TEMPLATE_CONTENT_FIELDS = ['preContent', 'postContent'];
|
|
23
23
|
const CUSTOM_TYPE_CONTENT_FIELDS = ['topContent', 'indexPageTopContent'];
|
|
24
|
+
const PERSON_TYPE_CONTENT_FIELDS = ['indexPageTopContent', 'personPageTopContent'];
|
|
24
25
|
const PAGE_LIKE_PARENTS = ['page', 'article', 'articleType', 'tag'];
|
|
25
26
|
export function addContentTypeError(contentTypeId, parentContentTypeId) {
|
|
26
27
|
if (parentContentTypeId === 'pageVariant') {
|
|
@@ -66,6 +67,16 @@ export function resolveAddTargetField(parentContentTypeId, requestedTarget, mode
|
|
|
66
67
|
}
|
|
67
68
|
return { ok: true, field: requestedTarget ?? 'topContent' };
|
|
68
69
|
}
|
|
70
|
+
if (parentContentTypeId === 'personType') {
|
|
71
|
+
if (requestedTarget &&
|
|
72
|
+
!PERSON_TYPE_CONTENT_FIELDS.includes(requestedTarget)) {
|
|
73
|
+
return {
|
|
74
|
+
ok: false,
|
|
75
|
+
message: `--target must be one of: ${PERSON_TYPE_CONTENT_FIELDS.join(', ')}. Got: ${requestedTarget}`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return { ok: true, field: requestedTarget ?? 'indexPageTopContent' };
|
|
79
|
+
}
|
|
69
80
|
if (parentContentTypeId === 'template') {
|
|
70
81
|
if (!requestedTarget ||
|
|
71
82
|
!TEMPLATE_CONTENT_FIELDS.includes(requestedTarget)) {
|
|
@@ -92,7 +103,7 @@ export function resolveAddTargetField(parentContentTypeId, requestedTarget, mode
|
|
|
92
103
|
return {
|
|
93
104
|
ok: false,
|
|
94
105
|
message: `--target is only supported when the session root is a page, article, articleType, tag, ` +
|
|
95
|
-
`pageVariant, customType, or template. Current root is ${parentContentTypeId}.`,
|
|
106
|
+
`pageVariant, customType, personType, or template. Current root is ${parentContentTypeId}.`,
|
|
96
107
|
};
|
|
97
108
|
}
|
|
98
109
|
return { ok: true, field: 'content' };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"allowed-types.js","sourceRoot":"","sources":["../../src/validation/allowed-types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"allowed-types.js","sourceRoot":"","sources":["../../src/validation/allowed-types.ts"],"names":[],"mappings":"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"}
|
package/docs/FUNCTIONAL_SPEC.md
CHANGED
|
@@ -149,7 +149,7 @@ Each resolved entry is assigned a stable `@ref` label (`@c0` = the root, `@c1`,
|
|
|
149
149
|
| `create taxonomy-from-json --file <path>` | Batch-create tagType, articleType, and tag entries from JSON |
|
|
150
150
|
| `create tag-type --slug <slug> --name "X"` | Create a tagType entry (draft) |
|
|
151
151
|
| `create article-type --slug <slug> --name "X"` | Create an articleType entry (draft) |
|
|
152
|
-
| `create person-type --slug <slug> --name "X" [--person-template-id <id>] [--indexed true\|false] [--hidden true\|false]` | Create a personType entry (draft). Indexed defaults on, Hidden off. |
|
|
152
|
+
| `create person-type --slug <slug> --name "X" [--person-page-template-id <id>] [--indexed true\|false] [--hidden true\|false]` | Create a personType entry (draft). Indexed defaults on, Hidden off. `--person-page-indexed` and `--person-page-hidden` stay unset when omitted. |
|
|
153
153
|
| `create tag --slug <slug> --name "X" --tag-type <slug>` | Create a tag entry (draft); `--tag-type-slug`, `--tag-type-name`; `--description`, `--featured-image`; cmsLabel auto `"<tagType> — <name>"` |
|
|
154
154
|
| `create tag-type\|tag\|article-type … --if-not-exists` | Idempotent taxonomy create (returns existing entry when slug matches) |
|
|
155
155
|
| `add <entry-type> --content-type <ct>` | Create a new child entry of a given content type, link it into the current open entry's content array, and assign it a @ref |
|
|
@@ -34,7 +34,7 @@ Normalize a **folder of designer masters** into short-lived **public HTTPS URLs*
|
|
|
34
34
|
| Situation | Action |
|
|
35
35
|
|-----------|--------|
|
|
36
36
|
| Drive folder of masters | This task with `driveFolderUrl` |
|
|
37
|
-
| Staged files (curl after `cms_edit_request_staged_upload`) | This task with `stagedUploadIds`
|
|
37
|
+
| Staged files (curl after `cms_edit_request_staged_upload`) | This task with `stagedUploadIds` when `intake` is `function`, or `httpsUrls` / `--https-urls` when `intake` is `direct` |
|
|
38
38
|
| Public HTTPS on allowed hosts | This task with `httpsUrls` |
|
|
39
39
|
| Single SVG/PDF/Lottie | `task-media-reuse-and-upload` asset upload --staged |
|
|
40
40
|
| Prior prepare already reached `succeeded` + catalog | **Reuse that jobId** — do not re-prepare |
|
|
@@ -61,7 +61,7 @@ Drive:
|
|
|
61
61
|
}
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
Function POST (image at or under 4MB, after curl POST to `uploadUrl`):
|
|
65
65
|
|
|
66
66
|
```json
|
|
67
67
|
{
|
|
@@ -70,6 +70,15 @@ Staged (after curl POST to each `uploadUrl`):
|
|
|
70
70
|
}
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
Direct (video, or an image over 4MB, after the presigned PUT). Do not POST that file through the function:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"action": "prepare",
|
|
78
|
+
"httpsUrls": ["https://….public.blob.vercel-storage.com/intake/…/file.mp4"]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
73
82
|
CLI:
|
|
74
83
|
|
|
75
84
|
```bash
|
|
@@ -77,6 +86,7 @@ cms-edit media prepare --drive-folder "https://drive.google.com/drive/folders/
|
|
|
77
86
|
--source-names "BusinessCards copy.jpg,ADB_Macbook_HomeLoop.mp4"
|
|
78
87
|
|
|
79
88
|
cms-edit media prepare --staged-ids "id1,id2"
|
|
89
|
+
cms-edit media prepare --https-urls "https://….public.blob.vercel-storage.com/intake/…/file.mp4"
|
|
80
90
|
```
|
|
81
91
|
|
|
82
92
|
Expect `{ ok: true, jobId, status: "queued", pollHint }`.
|
|
@@ -37,10 +37,42 @@
|
|
|
37
37
|
Encode via **`task-media-pipeline-prepare`**. Intake can be:
|
|
38
38
|
|
|
39
39
|
1. A **Drive folder**, or
|
|
40
|
-
2. **Staged upload
|
|
40
|
+
2. **Staged upload**: `cms_edit_request_staged_upload` → curl → follow `consumeArgs`, or
|
|
41
41
|
3. **httpsUrls** on pipeline-allowed hosts
|
|
42
42
|
|
|
43
|
-
Then wait → catalog → **import** with `overrides[].alt
|
|
43
|
+
Then wait → catalog → **import** with `overrides[].alt` for a **new** asset. 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.
|
|
44
|
+
|
|
45
|
+
**Search before upload still applies.** `asset search` (title or file name) first. **Search by concept** is how an editor finds a subject and a tone, including files no page uses yet:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
cms_edit ["asset", "search", "--concept", "<subject-concept-id>", "--concept-all", "<tone-concept-id>"]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`--concept` matches any listed id. Repeat `--concept-all` when several concepts are required. The result is id, title, file name, description, concepts. Concept search reads Contentful. It does not use the local index.
|
|
52
|
+
|
|
53
|
+
**Size.** Video source intake is **100MB** via direct-to-storage. An image master over **4MB** uses the same path. JSON, text, SVG, PDF, and Lottie stay on the **4MB** function POST. Pass `byteLength` for an image that might be over 4MB so the tool returns a presigned PUT (`intake: "direct"`) instead of the function URL. Run the curl, then `consumeArgs` (`media prepare --https-urls` of the public intake URL). The asset stored in Contentful is the **processed** file from the pack (`…/packs/…/ready/…`), not the 100MB source. Do not re-encode every asset. Size targets come from the site sizing standard. `asset review` still flags a stored video over **8MB**.
|
|
54
|
+
|
|
55
|
+
**Replace the file on an existing id** when pages already point at it. A second upload leaves those links on the old id.
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
cms_edit ["asset", "replace", "<asset-id>", "--url", "<processed-ready-url>", "--dry-run"]
|
|
59
|
+
cms_edit ["asset", "replace", "<asset-id>", "--url", "<processed-ready-url>"]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Replace keeps the id and the current file name. Dry-run returns id, file name, old dimensions, new dimensions, and writes nothing. The write is a draft. There is no publish flag. It refuses a replace that would turn an image into a non-image, or the reverse. SVG, PDF, and Lottie may use `--staged` or `--url`. Raster and video must use the processed pack URL.
|
|
63
|
+
|
|
64
|
+
**Title.** `asset set-title <asset-id> "<title>"` sets the asset title. Draft. It does not change the file name. Description stays `asset set-description`, written from the picture.
|
|
65
|
+
|
|
66
|
+
**Concepts are not blog tags.** `taxonomy-from-json` stays the blog importer (`tag` / `tagType`). Do not turn `taxonomyImport` on. Asset concepts are Contentful `metadata.concepts`, assigned by concept id after a person creates the scheme in the Taxonomy manager. The same organisation concepts show in every space. Files do not cross spaces. cms-edit does not create the scheme.
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
cms_edit ["asset", "concept", "assign", "<asset-id>", "<concept-id>"]
|
|
70
|
+
cms_edit ["asset", "concept", "unassign", "<asset-id>", "<concept-id>"]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
A missing concept fails with the id. Do not invent one.
|
|
74
|
+
|
|
75
|
+
**Do not emotion-score headshots, logos, icons, or illustrations.** Tone concepts are for lifestyle photos only. Alt text is still the asset description, one sentence from looking at the picture, not a keyword list and not the file name.
|
|
44
76
|
|
|
45
77
|
Animated GIFs become **MP4** (`gif-converted`) — attach as mute-loop Media / video visual, not `featuredImage`. **Do not** convert the GIF (or PNG) with local ffmpeg first; prepare the original file. If prepare gaps say `staged GET failed 405`, stop and report a cms-edit host bump — do not retry and do not use the Contentful web UI. If they say `staged GET failed 404`, re-stage (POST) and prepare once — the GET route exists.
|
|
46
78
|
|
|
@@ -48,19 +80,19 @@ Animated GIFs become **MP4** (`gif-converted`) — attach as mute-loop Media / v
|
|
|
48
80
|
|
|
49
81
|
These may skip the pipeline. On hosted MCP use staged upload then `asset upload --staged`.
|
|
50
82
|
|
|
51
|
-
### Hosted MCP
|
|
83
|
+
### Hosted MCP
|
|
52
84
|
|
|
53
85
|
**Always use staged upload** for ad-hoc binaries. Do not pass base64 in `cms_edit` args — hosted MCP rejects `asset upload --base64`.
|
|
54
86
|
|
|
55
|
-
1. `cms_edit_request_staged_upload` with `fileName`, `mimeType`,
|
|
56
|
-
2. Run the returned `curlCommand`
|
|
57
|
-
3. Follow `consumeArgs
|
|
87
|
+
1. `cms_edit_request_staged_upload` with `fileName`, `mimeType`, `byteLength` when the file may be over 4MB, optional `title`
|
|
88
|
+
2. Run the returned `curlCommand`. `intake: "direct"` (video, or an image over 4MB) is a PUT of the file. `intake: "function"` is a POST to `uploadUrl`. Do not POST a video through the function.
|
|
89
|
+
3. Follow `consumeArgs`. Direct intake: **media prepare** with `--https-urls` / `httpsUrls`. Function intake of an image at or under 4MB: **media prepare** with `stagedUploadIds`. SVG/PDF/Lottie: **asset upload --staged**.
|
|
58
90
|
|
|
59
91
|
Rules:
|
|
60
92
|
|
|
61
93
|
- Staged upload keeps binary **out of MCP args**
|
|
62
|
-
-
|
|
63
|
-
-
|
|
94
|
+
- Function POST (JSON, text, SVG, PDF, Lottie, and an image at or under 4MB): **4 MB**. Video, and an image master over 4MB: **100MB** presigned PUT to storage, then the media pipeline. **1000 upload URLs per user per hour**; TTL **60 minutes**
|
|
95
|
+
- Direct intake bytes are not stored in Redis. An image at or under 4MB stays in Redis until the pipeline fetches it (GET). Neither path writes the source to CMA
|
|
64
96
|
- Upload/import alone does **not** attach the asset — follow with **link + save** (below)
|
|
65
97
|
- Use `--if-exists-by-filename` (with `--file-name`) to avoid duplicate assets when re-running
|
|
66
98
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Capability: Taxonomy setup
|
|
2
2
|
|
|
3
|
+
Blog `tag` / `tagType` / `articleType` entries. This is not Contentful asset concepts (`metadata.concepts`). Do not use `taxonomy-from-json` to label assets. Asset concepts are assigned with `asset concept assign` after a person creates the scheme in the Taxonomy manager.
|
|
4
|
+
|
|
3
5
|
## Intent phrases
|
|
4
6
|
|
|
5
7
|
- create tags
|
package/docs/help/index.md
CHANGED
|
@@ -136,7 +136,7 @@ cms-edit batch run --json '[...]'
|
|
|
136
136
|
| `create taxonomy-from-json` | Batch-create tagType, articleType, and tag entries |
|
|
137
137
|
| `create person-from-json` | Batch-create person entries from JSON |
|
|
138
138
|
| `create person` | Create a person entry (draft). `--person-type-id` / `--person-type-slug` link a person type. `--indexed` and `--hidden` take `true` or `false`. |
|
|
139
|
-
| `create person-type` | Create a personType entry (draft). `--person-template-id` links the profile template. |
|
|
139
|
+
| `create person-type` | Create a personType entry (draft). `--person-page-template-id` links the profile template. |
|
|
140
140
|
| `article-tags-from-json` | Set tags on articles from JSON |
|
|
141
141
|
| `bulk-rtf-replace` | Find-replace in Rich Text across entry trees |
|
|
142
142
|
| `create tag-type` | Create a tagType entry (draft) |
|
package/docs/mcp/hosted-guide.md
CHANGED
|
@@ -13,7 +13,7 @@ cms-edit **cannot and will not**:
|
|
|
13
13
|
|
|
14
14
|
All `save` operations create **drafts only**. A human must review and publish in Contentful.
|
|
15
15
|
|
|
16
|
-
**Assets:** Always **search and reuse** first (`index sync`, then `asset search`). Raster/video go through **`cms_edit_media`** (
|
|
16
|
+
**Assets:** Always **search and reuse** first (`index sync`, then `asset search`). Raster/video go through **`cms_edit_media`** (Drive, or intake then prepare → import). Video, and an image master over 4MB, is a presigned PUT (`intake: direct`) then prepare with `httpsUrls`. An image at or under 4MB uses a function POST then `stagedUploadIds`. Never `asset upload` jpeg/png/webp/gif/mp4, and never convert those files with local ffmpeg. SVG/PDF/Lottie: staged upload then `asset upload --staged`. **`--base64` is not supported on hosted MCP.**
|
|
17
17
|
|
|
18
18
|
## MCP tools
|
|
19
19
|
|
|
@@ -138,11 +138,12 @@ 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`**. Raster/video:
|
|
141
|
+
Hosted connectors have **no server filesystem** and **reject `asset upload --base64`**. Raster/video: intake then the **media pipeline**. SVG/PDF/Lottie: staged then `asset upload --staged`.
|
|
142
142
|
|
|
143
143
|
| Source | When | Example |
|
|
144
144
|
|--------|------|---------|
|
|
145
|
-
| **
|
|
145
|
+
| **Direct + pipeline** | video, or an image over 4MB | Presigned PUT, then `cms_edit_media` prepare `httpsUrls` → import (required for video) |
|
|
146
|
+
| **Staged + pipeline** | image at or under 4MB | Function POST, then prepare `stagedUploadIds` → import |
|
|
146
147
|
| **`--url`** | Pipeline-ready **images** only, or SVG/PDF | `["asset", "upload", "--url", "https://….blob.vercel-storage.com/ready.jpg"]` |
|
|
147
148
|
| **Staged consume** | SVG/PDF/Lottie | `asset upload --staged` |
|
|
148
149
|
|
|
@@ -168,14 +169,15 @@ Full workflow: `cms-edit://customer/task-media-reuse-and-upload`.
|
|
|
168
169
|
Keeps binary **and large text/JSON** out of MCP tool args. The agent uploads via `curl`, then passes only a short `uploadId`.
|
|
169
170
|
|
|
170
171
|
1. `cms_edit_request_staged_upload` with `fileName`, `mimeType`, optional `kind` (`asset` \| `text` \| `json`), optional `byteLength`, optional `title`. If the wrapper schema has no `kind`, use `cms_edit` `["staged-upload", "request", "--kind", "json", "--file-name", "...", "--mime", "application/json"]` (or `--kind text` for HtmlComponent fields).
|
|
171
|
-
2. Run the returned `curlCommand` in a shell (POST multipart to `uploadUrl`)
|
|
172
|
+
2. Run the returned `curlCommand` in a shell (function route: POST multipart to `uploadUrl`; direct intake: PUT `--data-binary`)
|
|
172
173
|
3. Follow `consumeArgs`:
|
|
173
|
-
- **asset
|
|
174
|
+
- **asset, intake direct** (video, or an image over 4MB): media prepare with the public intake URL
|
|
175
|
+
- **asset, intake function:** media prepare for jpeg/png/webp/gif at or under 4MB; **asset upload --staged** for SVG/PDF/Lottie
|
|
174
176
|
- **text:** `set @ref field --staged <id>` (insert ref and field id)
|
|
175
177
|
- **json:** `create from-json --staged <id>` (add `--dry-run --strict` first). Dry-run does not consume the slot.
|
|
176
178
|
4. For pipeline jobs: wait → catalog → **import** (required for video). Then link and save
|
|
177
179
|
|
|
178
|
-
Hosted **inline** `--json` / `--content` / `--*-base64` is capped at **8192 bytes**.
|
|
180
|
+
Hosted **inline** `--json` / `--content` / `--*-base64` is capped at **8192 bytes**. Function POST (JSON, text, SVG, PDF, Lottie, image ≤ 4MB): **4 MB**. Video and an image master over 4MB: **100MB** presigned PUT (`BLOB_READ_WRITE_TOKEN` on the host), then the media pipeline. Rate limit: **1000 upload URLs per user per hour**. TTL: **60 minutes**.
|
|
179
181
|
|
|
180
182
|
## Featured images (articles)
|
|
181
183
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@se-studio/contentful-cms",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.0",
|
|
4
4
|
"description": "CLI tool for AI agents to edit Contentful drafts and, when the user's role allows it, publish after an explicit yes",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@contentful/rich-text-types": "^17.2.7",
|
|
64
64
|
"@modelcontextprotocol/sdk": "^1.31.0",
|
|
65
|
+
"@vercel/blob": "^2.8.0",
|
|
65
66
|
"commander": "^15.0.0",
|
|
66
67
|
"contentful": "^11.12.10",
|
|
67
68
|
"contentful-management": "^12.19.0",
|
package/skills/core/SKILL.md
CHANGED
|
@@ -32,9 +32,11 @@ Use this skill when you need to read or edit content in Contentful using **hoste
|
|
|
32
32
|
|
|
33
33
|
All `save` operations create **draft** versions. A human must review and publish in Contentful.
|
|
34
34
|
|
|
35
|
-
**Assets:** Upload **is** supported (`asset upload`). Default workflow: **search and reuse** existing assets first (`index sync` → `asset search`). When uploading:
|
|
36
|
-
- **Raster/video:** `cms_edit_request_staged_upload` → curl → `cms_edit_media` prepare
|
|
37
|
-
- **
|
|
35
|
+
**Assets:** Upload **is** supported (`asset upload`). Default workflow: **search and reuse** existing assets first (`index sync` → `asset search`). Search by concept (`asset search --concept` / `--concept-all`) finds a subject and a tone, including files no page uses yet. Concepts are not blog tags. When uploading:
|
|
36
|
+
- **Raster/video:** `cms_edit_request_staged_upload` → curl → `cms_edit_media` prepare → wait → catalog → import with real alt. Video, and an image master over 4MB, is a presigned direct PUT (100MB, `intake: direct`) then prepare with that URL. Smaller images still use `stagedUploadIds`. Never `asset upload --staged/--url/--base64` for jpeg/png/webp/gif/mp4. The stored asset is the processed file.
|
|
37
|
+
- **Replace** an existing id with `asset replace --url` of the processed `…/packs/…/ready/…` file (`--dry-run` first). The id and the file name stay. Draft. No publish flag.
|
|
38
|
+
- **SVG/PDF/Lottie:** `cms_edit_request_staged_upload` → curl → `asset upload --staged` (never `--base64`). 4MB function cap.
|
|
39
|
+
- **Title:** `asset set-title`. **Alt:** `asset set-description`, written from the picture. Do not emotion-score headshots, logos, icons, or illustrations.
|
|
38
40
|
- **HtmlComponent / large JSON:** `cms_edit_request_staged_upload` with `kind=text` or `kind=json` → curl → `set --staged`, `rtf --staged`, `create from-json --staged`, or `apply from-json --staged`. Hosted MCP rejects inline `--json`/`--content` over 8192 bytes. If the wrapper schema has no `kind`, use `cms_edit` `["staged-upload", "request", "--kind", "json", "--file-name", "...", "--mime", "application/json"]` (or `--kind text`), then curl, then `--staged`.
|
|
39
41
|
- Use a **sensible fileName** and **descriptive title** (and alt text where the site uses it)
|
|
40
42
|
- Avoid oversized images — width over **2000px** is usually wasteful for web (exact limits vary by project; check `asset audit` / media review guidance)
|
|
@@ -376,9 +378,13 @@ cms-edit asset search --filename istockphoto-123.jpg
|
|
|
376
378
|
cms-edit asset search --filename-match 'istockphoto-.*'
|
|
377
379
|
|
|
378
380
|
# Raster/video: cms_edit_media prepare → wait → catalog → import (video: import only).
|
|
381
|
+
# Video and image masters over 4MB: direct intake (100MB), then prepare --https-urls.
|
|
379
382
|
# Do not `asset upload` jpeg/png/webp/gif/mp4. Do not convert GIF/MP4 with local ffmpeg.
|
|
380
383
|
# Animated GIF: leave as GIF; pipeline emits gif-converted MP4 for Media mute-loop, not featuredImage.
|
|
381
|
-
# SVG/PDF/Lottie: cms_edit_request_staged_upload → curl → asset upload --staged
|
|
384
|
+
# SVG/PDF/Lottie: cms_edit_request_staged_upload → curl → asset upload --staged (4MB)
|
|
385
|
+
# Replace in place: asset replace <id> --url <processed ready url> --dry-run
|
|
386
|
+
# Title: asset set-title. Alt: asset set-description. Concepts: asset concept assign (not taxonomy-from-json)
|
|
387
|
+
# Concept search: asset search --concept <id> --concept-all <id>
|
|
382
388
|
|
|
383
389
|
# Create a Media wrapper for an existing asset (name defaults to asset title)
|
|
384
390
|
cms-edit create media --asset-id <asset-id>
|
|
@@ -394,7 +400,7 @@ cms-edit asset info 5xKj2abcDef
|
|
|
394
400
|
cms-edit asset set @c0 visual 5xKj2abcDef
|
|
395
401
|
```
|
|
396
402
|
|
|
397
|
-
JSON output for upload (`CMS_EDIT_JSON=1`): `{ ok, id, fileName, url, mediaId?, mediaIds? }`.
|
|
403
|
+
JSON output for upload (`CMS_EDIT_JSON=1`): `{ ok, id, fileName, url, mediaId?, mediaIds? }`. Bytes through the process are **10MB**. Hosted function POST is **4MB**. Video and large image masters are **100MB** direct-to-storage, then the pipeline.
|
|
398
404
|
|
|
399
405
|
**Idempotent upload:** `--if-exists-by-filename` is check-then-create. Do not upload the same `fileName` in parallel — serialize per fileName or re-run to converge.
|
|
400
406
|
|
|
@@ -64,7 +64,7 @@ Capability playbooks require:
|
|
|
64
64
|
|
|
65
65
|
## Media default
|
|
66
66
|
|
|
67
|
-
**Search and reuse assets first** (`index sync` → `asset search`). Upload only when no match; use `--if-exists-by-filename` when uploading.
|
|
67
|
+
**Search and reuse assets first** (`index sync` → `asset search`). Search by concept (`--concept`, `--concept-all`) finds a subject and a tone. Concepts are not blog tags. Upload only when no match; use `--if-exists-by-filename` when uploading. Replace an in-use file with `asset replace` so the id and the file name stay. Alt is `asset set-description`, written from the picture. Do not emotion-score headshots, logos, icons, or illustrations.
|
|
68
68
|
|
|
69
69
|
**Space-wide media audit** (filename, alt, size, dimensions, usage) → read **`task-media-review`**, then skill **`contentful-cms-media-review`** for the spreadsheet.
|
|
70
70
|
|