@cliangdev/conductor 0.21.0 → 0.22.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/assets/claude/skills/conductor-creative/SKILL.md +144 -0
- package/assets/claude/skills/conductor-publisher/SKILL.md +4 -0
- package/assets/cli-manifest.json +94 -0
- package/dist/commands/creative.d.ts +3 -0
- package/dist/commands/creative.d.ts.map +1 -0
- package/dist/commands/creative.js +60 -0
- package/dist/commands/creative.js.map +1 -0
- package/dist/creative/assertions.js +221 -0
- package/dist/creative/font.js +39 -0
- package/dist/creative/frame.css +126 -0
- package/dist/creative/frame.html +29 -0
- package/dist/creative/frame.js +76 -0
- package/dist/creative/job/render.mjs +203 -0
- package/dist/creative/job/server.mjs +72 -0
- package/dist/creative/job/transport.mjs +167 -0
- package/dist/creative/layouts/bleed/layout.css +47 -0
- package/dist/creative/layouts/bleed/layout.json +17 -0
- package/dist/creative/layouts/card/layout.css +24 -0
- package/dist/creative/layouts/card/layout.json +17 -0
- package/dist/creative/layouts/index.js +62 -0
- package/dist/creative/layouts/index.json +1 -0
- package/dist/creative/layouts/split/layout.css +22 -0
- package/dist/creative/layouts/split/layout.json +17 -0
- package/dist/creative/layouts/stacked/layout.css +40 -0
- package/dist/creative/layouts/stacked/layout.json +23 -0
- package/dist/creative/placements.js +200 -0
- package/dist/creative/placements.json +232 -0
- package/dist/creative/render.js +457 -0
- package/dist/creative/sheet.html +27 -0
- package/dist/creative/sheet.js +94 -0
- package/dist/creative/styles.css +314 -0
- package/dist/creative/tokens.css +33 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/creative-browser.d.ts +25 -0
- package/dist/lib/creative-browser.d.ts.map +1 -0
- package/dist/lib/creative-browser.js +36 -0
- package/dist/lib/creative-browser.js.map +1 -0
- package/dist/lib/creative-id.d.ts +8 -0
- package/dist/lib/creative-id.d.ts.map +1 -0
- package/dist/lib/creative-id.js +14 -0
- package/dist/lib/creative-id.js.map +1 -0
- package/dist/lib/creative-render.d.ts +32 -0
- package/dist/lib/creative-render.d.ts.map +1 -0
- package/dist/lib/creative-render.js +71 -0
- package/dist/lib/creative-render.js.map +1 -0
- package/dist/lib/image-dimensions.d.ts +20 -0
- package/dist/lib/image-dimensions.d.ts.map +1 -0
- package/dist/lib/image-dimensions.js +115 -0
- package/dist/lib/image-dimensions.js.map +1 -0
- package/dist/lib/plugin-assets.d.ts.map +1 -1
- package/dist/lib/plugin-assets.js +1 -0
- package/dist/lib/plugin-assets.js.map +1 -1
- package/dist/mcp/index.d.ts +18 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +284 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/tools/creatives.d.ts +93 -0
- package/dist/mcp/tools/creatives.d.ts.map +1 -0
- package/dist/mcp/tools/creatives.js +291 -0
- package/dist/mcp/tools/creatives.js.map +1 -0
- package/dist/mcp/tools/insights.d.ts.map +1 -1
- package/dist/mcp/tools/insights.js +14 -0
- package/dist/mcp/tools/insights.js.map +1 -1
- package/package.json +4 -3
- package/scripts/build-creative.mjs +93 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs a Creative render locally: loads the render core copied into `dist/creative/` at build time
|
|
3
|
+
* (see `scripts/build-creative.mjs`), drives it against the external v2 creatives API with this
|
|
4
|
+
* project's own API key, and reads back the stored result. Shared by the `conductor creative render`
|
|
5
|
+
* CLI command and the `render_creative` MCP tool so the two never drift.
|
|
6
|
+
*
|
|
7
|
+
* The render core itself (`conductor-creative/job/render.mjs`'s `run()`) knows nothing about how it's
|
|
8
|
+
* launched or what browser it gets — that's `job/transport.mjs`'s and this file's job respectively.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync } from 'node:fs';
|
|
11
|
+
import { dirname, join } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { apiGet } from '../mcp/api.js';
|
|
14
|
+
import { findBrowserFactory } from './creative-browser.js';
|
|
15
|
+
/** Where `npm run build` copies `conductor-creative/`'s runtime files, relative to this file's own
|
|
16
|
+
* compiled location (`dist/lib/creative-render.js` -> `dist/creative/job/`). */
|
|
17
|
+
function jobDir() {
|
|
18
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
return join(here, '..', 'creative', 'job');
|
|
20
|
+
}
|
|
21
|
+
async function loadRenderCore() {
|
|
22
|
+
const dir = jobDir();
|
|
23
|
+
const renderPath = join(dir, 'render.mjs');
|
|
24
|
+
const transportPath = join(dir, 'transport.mjs');
|
|
25
|
+
if (!existsSync(renderPath) || !existsSync(transportPath)) {
|
|
26
|
+
throw new Error(`Creative render core not found under ${dir}. This is a packaging bug in @cliangdev/conductor ` +
|
|
27
|
+
'(the build step that copies conductor-creative/ into dist/creative/ did not run) — ' +
|
|
28
|
+
'reinstall the CLI, or in this repo run `npm run build`.');
|
|
29
|
+
}
|
|
30
|
+
const [renderMod, transportMod] = await Promise.all([
|
|
31
|
+
import(renderPath),
|
|
32
|
+
import(transportPath),
|
|
33
|
+
]);
|
|
34
|
+
return { run: renderMod.run, createApiTransport: transportMod.createApiTransport };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Renders a Creative end to end: finds a local browser, runs the render core against the external
|
|
38
|
+
* API, and reads back the stored render (frames with signed URLs, final state) whether or not the
|
|
39
|
+
* render itself succeeded — a FAILED render still has an id and an error message worth returning.
|
|
40
|
+
*/
|
|
41
|
+
export async function renderCreative(params, config, log = () => { }) {
|
|
42
|
+
const { run, createApiTransport } = await loadRenderCore();
|
|
43
|
+
const transport = createApiTransport({
|
|
44
|
+
apiUrl: config.apiUrl,
|
|
45
|
+
apiKey: config.apiKey,
|
|
46
|
+
projectId: config.projectId,
|
|
47
|
+
creativeId: params.creativeId,
|
|
48
|
+
previewOnly: !!params.previewOnly,
|
|
49
|
+
renderer: params.renderer,
|
|
50
|
+
workflowRunId: params.workflowRunId,
|
|
51
|
+
});
|
|
52
|
+
const browserFactory = await findBrowserFactory(log);
|
|
53
|
+
const ok = await run({ transport, browserFactory, log });
|
|
54
|
+
const renderId = transport.getRenderId();
|
|
55
|
+
if (!renderId) {
|
|
56
|
+
return { ok: false, error: 'The render was never started — the API rejected the request before a render id was assigned.', frames: [] };
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
const detail = await apiGet(`/api/v2/projects/${config.projectId}/marketing/creatives/${params.creativeId}/renders/${renderId}`, config);
|
|
60
|
+
return { ok, renderId, state: detail.state, error: detail.error ?? null, frames: detail.frames ?? [] };
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
return {
|
|
64
|
+
ok,
|
|
65
|
+
renderId,
|
|
66
|
+
error: `Render finished (${ok ? 'succeeded' : 'failed'}) but reading the result back failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
67
|
+
frames: [],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=creative-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"creative-render.js","sourceRoot":"","sources":["../../src/lib/creative-render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads an image's format and pixel dimensions straight from its file header — no decode, no
|
|
3
|
+
* external image library. Used by `upload_creative_photo`, which needs width/height and content
|
|
4
|
+
* type before minting an upload (the backend's `CreateCreativePhotoRequest` requires both, since
|
|
5
|
+
* Conductor has no server-side image pipeline and WebP in particular cannot be probed there).
|
|
6
|
+
*
|
|
7
|
+
* Covers exactly the three formats the Creative photo API accepts (image/png, image/jpeg,
|
|
8
|
+
* image/webp). Returns `null` for anything else or a header that doesn't parse — callers should
|
|
9
|
+
* treat that as "not a usable photo" rather than guessing.
|
|
10
|
+
*/
|
|
11
|
+
export type CreativePhotoContentType = 'image/png' | 'image/jpeg' | 'image/webp';
|
|
12
|
+
export interface ImageInfo {
|
|
13
|
+
contentType: CreativePhotoContentType;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
}
|
|
17
|
+
/** Sniffs the format from magic bytes and parses width/height from the header. `null` when the
|
|
18
|
+
* bytes aren't a recognizable PNG, JPEG or WebP, or the header is truncated/malformed. */
|
|
19
|
+
export declare function readImageDimensions(bytes: Uint8Array): ImageInfo | null;
|
|
20
|
+
//# sourceMappingURL=image-dimensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-dimensions.d.ts","sourceRoot":"","sources":["../../src/lib/image-dimensions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,wBAAwB,GAAG,WAAW,GAAG,YAAY,GAAG,YAAY,CAAA;AAEhF,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,wBAAwB,CAAA;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAuGD;0FAC0F;AAC1F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,CAEvE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads an image's format and pixel dimensions straight from its file header — no decode, no
|
|
3
|
+
* external image library. Used by `upload_creative_photo`, which needs width/height and content
|
|
4
|
+
* type before minting an upload (the backend's `CreateCreativePhotoRequest` requires both, since
|
|
5
|
+
* Conductor has no server-side image pipeline and WebP in particular cannot be probed there).
|
|
6
|
+
*
|
|
7
|
+
* Covers exactly the three formats the Creative photo API accepts (image/png, image/jpeg,
|
|
8
|
+
* image/webp). Returns `null` for anything else or a header that doesn't parse — callers should
|
|
9
|
+
* treat that as "not a usable photo" rather than guessing.
|
|
10
|
+
*/
|
|
11
|
+
function readUInt32BE(bytes, offset) {
|
|
12
|
+
return ((bytes[offset] << 24) | (bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3]) >>> 0;
|
|
13
|
+
}
|
|
14
|
+
function readUInt16BE(bytes, offset) {
|
|
15
|
+
return ((bytes[offset] << 8) | bytes[offset + 1]) >>> 0;
|
|
16
|
+
}
|
|
17
|
+
function readUInt24LE(bytes, offset) {
|
|
18
|
+
return (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16)) >>> 0;
|
|
19
|
+
}
|
|
20
|
+
const PNG_SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
|
|
21
|
+
function readPng(bytes) {
|
|
22
|
+
if (bytes.length < 24)
|
|
23
|
+
return null;
|
|
24
|
+
if (!PNG_SIGNATURE.every((b, i) => bytes[i] === b))
|
|
25
|
+
return null;
|
|
26
|
+
// IHDR is always the first chunk: 4-byte length, 4-byte type "IHDR", then width/height (4 bytes
|
|
27
|
+
// each, big-endian) at offsets 16 and 20.
|
|
28
|
+
return { contentType: 'image/png', width: readUInt32BE(bytes, 16), height: readUInt32BE(bytes, 20) };
|
|
29
|
+
}
|
|
30
|
+
// SOFn (start-of-frame) markers that carry dimensions. Excludes 0xC4 (DHT), 0xC8 (JPG extension,
|
|
31
|
+
// unused in practice) and 0xCC (DAC) — those share the 0xC0-0xCF range but aren't SOF markers.
|
|
32
|
+
const JPEG_SOF_MARKERS = new Set([0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf]);
|
|
33
|
+
// Standalone markers with no length-prefixed payload following them.
|
|
34
|
+
const JPEG_NO_PAYLOAD_MARKERS = new Set([0x01, 0xd8, 0xd9]);
|
|
35
|
+
function readJpeg(bytes) {
|
|
36
|
+
if (bytes.length < 4 || bytes[0] !== 0xff || bytes[1] !== 0xd8)
|
|
37
|
+
return null;
|
|
38
|
+
let offset = 2;
|
|
39
|
+
while (offset + 4 <= bytes.length) {
|
|
40
|
+
if (bytes[offset] !== 0xff) {
|
|
41
|
+
offset += 1; // resync on a stray fill byte (0xFF00 stuffing, etc.)
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const marker = bytes[offset + 1];
|
|
45
|
+
if (marker === 0xd9)
|
|
46
|
+
break; // EOI, no dimensions found
|
|
47
|
+
if (JPEG_NO_PAYLOAD_MARKERS.has(marker) || (marker >= 0xd0 && marker <= 0xd7)) {
|
|
48
|
+
offset += 2;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const segmentLength = readUInt16BE(bytes, offset + 2);
|
|
52
|
+
if (JPEG_SOF_MARKERS.has(marker)) {
|
|
53
|
+
const payloadStart = offset + 4;
|
|
54
|
+
if (payloadStart + 5 > bytes.length)
|
|
55
|
+
return null;
|
|
56
|
+
const height = readUInt16BE(bytes, payloadStart + 1);
|
|
57
|
+
const width = readUInt16BE(bytes, payloadStart + 3);
|
|
58
|
+
return { contentType: 'image/jpeg', width, height };
|
|
59
|
+
}
|
|
60
|
+
if (segmentLength < 2)
|
|
61
|
+
return null; // malformed — refuse to loop forever
|
|
62
|
+
offset += 2 + segmentLength;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
function isRiffWebp(bytes) {
|
|
67
|
+
return (bytes.length >= 21 && // enough to read the fourCC at 12-15 and reach the chunk data at 20
|
|
68
|
+
bytes[0] === 0x52 &&
|
|
69
|
+
bytes[1] === 0x49 &&
|
|
70
|
+
bytes[2] === 0x46 &&
|
|
71
|
+
bytes[3] === 0x46 && // "RIFF"
|
|
72
|
+
bytes[8] === 0x57 &&
|
|
73
|
+
bytes[9] === 0x45 &&
|
|
74
|
+
bytes[10] === 0x42 &&
|
|
75
|
+
bytes[11] === 0x50 // "WEBP"
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
function readWebp(bytes) {
|
|
79
|
+
if (!isRiffWebp(bytes))
|
|
80
|
+
return null;
|
|
81
|
+
const fourCc = String.fromCharCode(bytes[12], bytes[13], bytes[14], bytes[15]);
|
|
82
|
+
const chunkStart = 20; // after the 8-byte RIFF header, "WEBP", fourCC and 4-byte chunk size
|
|
83
|
+
if (fourCc === 'VP8X') {
|
|
84
|
+
// flags (1 byte) + reserved (3 bytes), then 3-byte little-endian (width-1) and (height-1).
|
|
85
|
+
if (bytes.length < chunkStart + 10)
|
|
86
|
+
return null;
|
|
87
|
+
return {
|
|
88
|
+
contentType: 'image/webp',
|
|
89
|
+
width: readUInt24LE(bytes, chunkStart + 4) + 1,
|
|
90
|
+
height: readUInt24LE(bytes, chunkStart + 7) + 1,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (fourCc === 'VP8 ') {
|
|
94
|
+
// 3-byte frame tag + 3-byte start code (0x9d 0x01 0x2a), then 14-bit width/height, little-endian.
|
|
95
|
+
if (bytes.length < chunkStart + 10)
|
|
96
|
+
return null;
|
|
97
|
+
const widthRaw = bytes[chunkStart + 6] | (bytes[chunkStart + 7] << 8);
|
|
98
|
+
const heightRaw = bytes[chunkStart + 8] | (bytes[chunkStart + 9] << 8);
|
|
99
|
+
return { contentType: 'image/webp', width: widthRaw & 0x3fff, height: heightRaw & 0x3fff };
|
|
100
|
+
}
|
|
101
|
+
if (fourCc === 'VP8L') {
|
|
102
|
+
// 1-byte signature (0x2f), then a little-endian 32-bit field: 14-bit (width-1), 14-bit (height-1).
|
|
103
|
+
if (bytes.length < chunkStart + 5)
|
|
104
|
+
return null;
|
|
105
|
+
const bits = (bytes[chunkStart + 1] | (bytes[chunkStart + 2] << 8) | (bytes[chunkStart + 3] << 16) | (bytes[chunkStart + 4] << 24)) >>> 0;
|
|
106
|
+
return { contentType: 'image/webp', width: (bits & 0x3fff) + 1, height: ((bits >>> 14) & 0x3fff) + 1 };
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
/** Sniffs the format from magic bytes and parses width/height from the header. `null` when the
|
|
111
|
+
* bytes aren't a recognizable PNG, JPEG or WebP, or the header is truncated/malformed. */
|
|
112
|
+
export function readImageDimensions(bytes) {
|
|
113
|
+
return readPng(bytes) ?? readJpeg(bytes) ?? readWebp(bytes);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=image-dimensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-dimensions.js","sourceRoot":"","sources":["../../src/lib/image-dimensions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-assets.d.ts","sourceRoot":"","sources":["../../src/lib/plugin-assets.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin-assets.d.ts","sourceRoot":"","sources":["../../src/lib/plugin-assets.ts"],"names":[],"mappings":"AA4CA,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAmCD,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAA;AAE/D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,aAAa,CA4Cf;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,cAAc,EAAE,MAAM,GACrB;IAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CA0B9D"}
|
|
@@ -11,6 +11,7 @@ const PLUGIN_FILES = [
|
|
|
11
11
|
'skills/conductor-ux-ui-design/references/design-tokens.md',
|
|
12
12
|
'skills/conductor-coder/SKILL.md',
|
|
13
13
|
'skills/conductor-publisher/SKILL.md',
|
|
14
|
+
'skills/conductor-creative/SKILL.md',
|
|
14
15
|
];
|
|
15
16
|
// Paths removed in previous versions — deleted on `conductor init` to clean up stale installs.
|
|
16
17
|
const LEGACY_PATHS = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-assets.js","sourceRoot":"","sources":["../../src/lib/plugin-assets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,MAAM,YAAY,GAAG;IACnB,2BAA2B;IAC3B,iCAAiC;IACjC,2BAA2B;IAC3B,gCAAgC;IAChC,gCAAgC;IAChC,wCAAwC;IACxC,2DAA2D;IAC3D,iCAAiC;IACjC,qCAAqC;
|
|
1
|
+
{"version":3,"file":"plugin-assets.js","sourceRoot":"","sources":["../../src/lib/plugin-assets.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* An image content block (base64-encoded bytes + MIME type) plus an optional text block of
|
|
4
|
+
* metadata — the shape a client needs to actually render the image rather than just read about it.
|
|
5
|
+
* `preview_creative` is the first tool to need this; every other tool emits text only.
|
|
6
|
+
*/
|
|
7
|
+
export declare function imageResponse(image: {
|
|
8
|
+
data: Buffer;
|
|
9
|
+
mimeType: string;
|
|
10
|
+
}, meta?: unknown): {
|
|
11
|
+
content: ({
|
|
12
|
+
type: "image";
|
|
13
|
+
data: string;
|
|
14
|
+
mimeType: string;
|
|
15
|
+
} | {
|
|
16
|
+
type: "text";
|
|
17
|
+
text: string;
|
|
18
|
+
})[];
|
|
19
|
+
};
|
|
2
20
|
export declare function runMcpServer(): Promise<void>;
|
|
3
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/mcp/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AAywCA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,CAAC,EAAE,OAAO;;cACxD,OAAO;cAAQ,MAAM;kBAAY,MAAM;;cAAa,MAAM;cAAQ,MAAM;;EAOtG;AAoBD,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA4zBlD"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -15,6 +15,17 @@ import { submitKnowledgeSource, readKnowledgeSources, searchKnowledge, readKnowl
|
|
|
15
15
|
import { listPublishTargets, setPublishTargets, uploadAsset, retryFailedPublishTargets, completeManualPublish, } from './tools/marketing.js';
|
|
16
16
|
import { createPost, getPostStatus, submitPost, listPosts, submitReview, listAssets, getPostAnalytics, listTopPosts, } from './tools/posts.js';
|
|
17
17
|
import { getMarketingInsights } from './tools/insights.js';
|
|
18
|
+
import { getBrandKit, listCreatives, getCreative, createCreative, updateCreative, uploadCreativePhoto, renderCreativeTool, previewCreative, attachCreativeToPost, createExperiment, } from './tools/creatives.js';
|
|
19
|
+
import { resolveCreativeId } from '../lib/creative-id.js';
|
|
20
|
+
const CREATIVE_TOOLS = [
|
|
21
|
+
'get_creative',
|
|
22
|
+
'create_creative',
|
|
23
|
+
'update_creative',
|
|
24
|
+
'render_creative',
|
|
25
|
+
'preview_creative',
|
|
26
|
+
'attach_creative_to_post',
|
|
27
|
+
'create_experiment',
|
|
28
|
+
];
|
|
18
29
|
import { listProjectDocs, readProjectDoc, writeProjectDoc, moveProjectDoc, deleteProjectDoc, setProjectDocTask, listProjectDocComments, commentOnProjectDoc, respondToProjectDocComment, listProjectDocVersions, restoreProjectDocVersion, uploadProjectDocImage, moveProjectFolder, deleteProjectFolder, } from './tools/project-docs.js';
|
|
19
30
|
const TOOLS = [
|
|
20
31
|
// --- Canonical Work Item tools (v2 /work-items surface) ---
|
|
@@ -957,7 +968,7 @@ const TOOLS = [
|
|
|
957
968
|
},
|
|
958
969
|
{
|
|
959
970
|
name: 'get_marketing_insights',
|
|
960
|
-
description: 'What is working across the project\'s published Posts: totals, engagement rate by platform, format and time, best and worst posts, and movers vs the prior window. Read-only. Use get_post_analytics for one Post\'s series and list_top_posts for a full ranking by one metric.',
|
|
971
|
+
description: 'What is working across the project\'s published Posts: totals, engagement rate by platform, format and time, best and worst posts, top-performing Creatives, and movers vs the prior window. Read-only. Use get_post_analytics for one Post\'s series and list_top_posts for a full ranking by one metric.',
|
|
961
972
|
inputSchema: {
|
|
962
973
|
type: 'object',
|
|
963
974
|
properties: {
|
|
@@ -979,6 +990,198 @@ const TOOLS = [
|
|
|
979
990
|
required: ['postId', 'verdict'],
|
|
980
991
|
},
|
|
981
992
|
},
|
|
993
|
+
// --- Creatives: Brand Kit + Creative library + local rendering ---
|
|
994
|
+
{
|
|
995
|
+
name: 'get_brand_kit',
|
|
996
|
+
description: "Read a workspace Brand Kit: colour tokens, font, logo/wordmark/badge URLs, CTA claim, copy rules, approved lines, enabled placements, and the Knowledge page path holding its prose context. Omit kitId for the project's default kit.",
|
|
997
|
+
inputSchema: {
|
|
998
|
+
type: 'object',
|
|
999
|
+
properties: {
|
|
1000
|
+
kitId: { type: 'string', description: "Brand Kit id (optional — omit for the project's default kit)" },
|
|
1001
|
+
},
|
|
1002
|
+
},
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
name: 'list_creatives',
|
|
1006
|
+
description: "List the project's Creatives (photo + headline + layout), newest display number first, lettered variants grouped together. Filter by state or brandKitId.",
|
|
1007
|
+
inputSchema: {
|
|
1008
|
+
type: 'object',
|
|
1009
|
+
properties: {
|
|
1010
|
+
state: { type: 'string', enum: ['DRAFT', 'READY', 'ARCHIVED'], description: 'Filter by state (optional)' },
|
|
1011
|
+
brandKitId: { type: 'string', description: 'Filter to Creatives on one Brand Kit (optional)' },
|
|
1012
|
+
},
|
|
1013
|
+
},
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
name: 'get_creative',
|
|
1017
|
+
description: "One Creative in full: its fields, its readiness checklist (what still blocks it going to review), the other lettered variants in its family, each variant's attributed performance (posts, views, engagement rate, average view percentage, 72h views), and the family's active or most recent hook experiment (state, and once decided, the winner and its numbers). Call after create_creative/update_creative/create_experiment to verify.",
|
|
1018
|
+
inputSchema: {
|
|
1019
|
+
type: 'object',
|
|
1020
|
+
properties: {
|
|
1021
|
+
creativeId: { type: 'string', description: 'Creative id, or its display id such as 12a' },
|
|
1022
|
+
},
|
|
1023
|
+
required: ['creativeId'],
|
|
1024
|
+
},
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
name: 'create_creative',
|
|
1028
|
+
description: "Create a Creative (photo, headline, layout, theme, body, caption, alt text, optional story/carousel sequence), or, with variantOf, cut a lettered variant of an existing one instead (inherits everything but headline/name — every other field here is ignored). Refused with the failing rule's message on a bad layout/theme/placement, the kit's accent-phrase rule, a copy rule, or (when state is READY) a readiness rule. Call get_creative after to verify.",
|
|
1029
|
+
inputSchema: {
|
|
1030
|
+
type: 'object',
|
|
1031
|
+
properties: {
|
|
1032
|
+
variantOf: { type: 'string', description: 'Cut a lettered variant of this existing Creative instead of creating a fresh one (optional)' },
|
|
1033
|
+
brandKitId: { type: 'string', description: "Brand Kit this Creative renders with (optional — defaults to the project's default kit)" },
|
|
1034
|
+
name: { type: 'string', description: 'Internal name, not shown on the artwork (optional)' },
|
|
1035
|
+
state: { type: 'string', enum: ['DRAFT', 'READY', 'ARCHIVED'], description: 'Defaults to DRAFT (optional)' },
|
|
1036
|
+
layout: { type: 'string', description: "Layout key from the creative registry, e.g. stacked/bleed/card/split (optional — defaults to the registry's first layout)" },
|
|
1037
|
+
theme: { type: 'string', enum: ['dark', 'light'], description: 'Optional — defaults to dark' },
|
|
1038
|
+
photoId: { type: 'string', description: 'A photo from upload_creative_photo (optional)' },
|
|
1039
|
+
focalOverride: { type: 'object', additionalProperties: { type: 'string' }, description: 'Per-placement focal point override, e.g. {"9x16":"50% 30%"} (optional)' },
|
|
1040
|
+
headline: { type: 'string', description: 'Exactly one *accent phrase* marked with asterisks, when the Brand Kit requires one (optional)' },
|
|
1041
|
+
body: { type: 'string', description: 'Body copy (optional)' },
|
|
1042
|
+
caption: { type: 'string', description: "The post caption this Creative is meant for, carried through but never rendered onto the artwork (optional)" },
|
|
1043
|
+
altText: { type: 'string', description: 'Accessibility description of the photo, not the copy (optional)' },
|
|
1044
|
+
placements: { type: 'array', items: { type: 'string' }, description: "Extra placement keys this Creative opts into beyond the Brand Kit's enabled set (optional)" },
|
|
1045
|
+
sequenceKind: { type: 'string', enum: ['story', 'carousel'], description: 'Set to render a multi-beat sequence instead of one frame (optional)' },
|
|
1046
|
+
sequence: {
|
|
1047
|
+
type: 'array',
|
|
1048
|
+
description: 'Story beats (2-7) or carousel cards (2-10); each inherits the Creative and overrides only what changes (optional)',
|
|
1049
|
+
items: {
|
|
1050
|
+
type: 'object',
|
|
1051
|
+
properties: {
|
|
1052
|
+
headline: { type: 'string' },
|
|
1053
|
+
body: { type: 'string' },
|
|
1054
|
+
photoId: { type: 'string' },
|
|
1055
|
+
cta: { type: 'boolean', description: 'Forces the CTA row on/off for this beat (optional — default: only the last beat shows it)' },
|
|
1056
|
+
},
|
|
1057
|
+
},
|
|
1058
|
+
},
|
|
1059
|
+
carouselRatio: { type: 'string', description: 'Aspect ratio key for a carousel sequence, e.g. 4x5 or 1x1 (optional)' },
|
|
1060
|
+
lockup: { type: 'string', enum: ['plain', 'chip'], description: 'Optional — defaults to plain. "chip" puts the logo lockup on a white pill, for busy photography.' },
|
|
1061
|
+
layoutOverrides: {
|
|
1062
|
+
type: 'object',
|
|
1063
|
+
description: 'Per-placement overrides of layout-derived numbers, in pixels (optional). A placement key not named here keeps the layout\'s own default.',
|
|
1064
|
+
properties: {
|
|
1065
|
+
band: { type: 'object', additionalProperties: { type: 'integer' }, description: 'Overrides the stacked layout\'s photo band height per placement, e.g. {"9x16": 1200}' },
|
|
1066
|
+
padBottom: { type: 'object', additionalProperties: { type: 'integer' }, description: "Overrides the 9x16 panel's bottom safe-zone clearance per placement" },
|
|
1067
|
+
},
|
|
1068
|
+
},
|
|
1069
|
+
},
|
|
1070
|
+
},
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
name: 'update_creative',
|
|
1074
|
+
description: "Patch a Creative's fields. version must equal its current value (from get_creative) or the write is refused with a 409 conflict — reread and reapply on top of the newer version rather than retrying blind. A failing structural or readiness rule is refused with the rule's own message. Call get_creative after to verify.",
|
|
1075
|
+
inputSchema: {
|
|
1076
|
+
type: 'object',
|
|
1077
|
+
properties: {
|
|
1078
|
+
creativeId: { type: 'string', description: 'Creative id, or its display id such as 12a' },
|
|
1079
|
+
version: { type: 'number', description: "The Creative's current version, from get_creative" },
|
|
1080
|
+
brandKitId: { type: 'string' },
|
|
1081
|
+
name: { type: 'string' },
|
|
1082
|
+
state: { type: 'string', enum: ['DRAFT', 'READY', 'ARCHIVED'] },
|
|
1083
|
+
layout: { type: 'string' },
|
|
1084
|
+
theme: { type: 'string', enum: ['dark', 'light'] },
|
|
1085
|
+
photoId: { type: 'string' },
|
|
1086
|
+
focalOverride: { type: 'object', additionalProperties: { type: 'string' } },
|
|
1087
|
+
headline: { type: 'string' },
|
|
1088
|
+
body: { type: 'string' },
|
|
1089
|
+
caption: { type: 'string' },
|
|
1090
|
+
altText: { type: 'string' },
|
|
1091
|
+
placements: { type: 'array', items: { type: 'string' } },
|
|
1092
|
+
sequenceKind: { type: 'string', enum: ['story', 'carousel'] },
|
|
1093
|
+
sequence: {
|
|
1094
|
+
type: 'array',
|
|
1095
|
+
items: {
|
|
1096
|
+
type: 'object',
|
|
1097
|
+
properties: {
|
|
1098
|
+
headline: { type: 'string' },
|
|
1099
|
+
body: { type: 'string' },
|
|
1100
|
+
photoId: { type: 'string' },
|
|
1101
|
+
cta: { type: 'boolean' },
|
|
1102
|
+
},
|
|
1103
|
+
},
|
|
1104
|
+
},
|
|
1105
|
+
carouselRatio: { type: 'string' },
|
|
1106
|
+
lockup: { type: 'string', enum: ['plain', 'chip'] },
|
|
1107
|
+
layoutOverrides: {
|
|
1108
|
+
type: 'object',
|
|
1109
|
+
properties: {
|
|
1110
|
+
band: { type: 'object', additionalProperties: { type: 'integer' } },
|
|
1111
|
+
padBottom: { type: 'object', additionalProperties: { type: 'integer' } },
|
|
1112
|
+
},
|
|
1113
|
+
},
|
|
1114
|
+
},
|
|
1115
|
+
required: ['creativeId', 'version'],
|
|
1116
|
+
},
|
|
1117
|
+
},
|
|
1118
|
+
{
|
|
1119
|
+
name: 'upload_creative_photo',
|
|
1120
|
+
description: "Upload a photo into the project's photo library from a local file or a public URL, recording its provenance (source, licence, aiGenerated) for the readiness checklist. Width and height are read from the file itself. Use the returned photo's id as a Creative's photoId.",
|
|
1121
|
+
inputSchema: {
|
|
1122
|
+
type: 'object',
|
|
1123
|
+
properties: {
|
|
1124
|
+
filePath: { type: 'string', description: 'A file on this machine (use this or url)' },
|
|
1125
|
+
url: { type: 'string', description: 'A public http(s) URL (use this or filePath)' },
|
|
1126
|
+
label: { type: 'string', description: 'Human label (optional — defaults to the filename)' },
|
|
1127
|
+
source: { type: 'string', description: 'Provenance note, e.g. a URL or "Generated with <model> on <date>" (optional)' },
|
|
1128
|
+
licence: { type: 'string', description: 'e.g. "Own work", "Unsplash Licence", "Generated, house use" (optional)' },
|
|
1129
|
+
aiGenerated: { type: 'boolean', description: 'Whether the photo is AI-generated (optional, informational only)' },
|
|
1130
|
+
},
|
|
1131
|
+
},
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
name: 'render_creative',
|
|
1135
|
+
description: 'Render a Creative locally (Playwright on this machine) to upload-ready JPEG frames (one per placement), or a small contact sheet with previewOnly. Runs synchronously — typically well under a minute — and returns the render id, state, frame URLs and any warnings. Call preview_creative to actually look at the result.',
|
|
1136
|
+
inputSchema: {
|
|
1137
|
+
type: 'object',
|
|
1138
|
+
properties: {
|
|
1139
|
+
creativeId: { type: 'string', description: 'Creative id, or its display id such as 12a' },
|
|
1140
|
+
previewOnly: { type: 'boolean', description: 'Render one small contact sheet instead of full-size placement frames (optional, default false)' },
|
|
1141
|
+
renderer: { type: 'string', description: 'Attribution tag stored on the render (optional, default "mcp")' },
|
|
1142
|
+
workflowRunId: { type: 'string', description: 'Attribute this render to a Workflow run (optional)' },
|
|
1143
|
+
},
|
|
1144
|
+
required: ['creativeId'],
|
|
1145
|
+
},
|
|
1146
|
+
},
|
|
1147
|
+
{
|
|
1148
|
+
name: 'preview_creative',
|
|
1149
|
+
description: "Look at a Creative: returns its latest contact sheet as an image (rendering a fresh previewOnly one first if none exists yet). Use this to judge the actual artwork — does the headline read at a glance, is the copy sitting on the subject's face — not just the data. If the image is too large to inline it returns the URL instead, with a note saying so.",
|
|
1150
|
+
inputSchema: {
|
|
1151
|
+
type: 'object',
|
|
1152
|
+
properties: {
|
|
1153
|
+
creativeId: { type: 'string', description: 'Creative id, or its display id such as 12a' },
|
|
1154
|
+
},
|
|
1155
|
+
required: ['creativeId'],
|
|
1156
|
+
},
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
name: 'attach_creative_to_post',
|
|
1160
|
+
description: "Attach a Creative's rendered frames to a Post as its media — placement to platform (9x16 to TikTok/Instagram Reels, 4x5 to Instagram feed, 1x1 to Facebook, story to story targets; sequence frames in order) — for every destination that has not set its own custom media. Uses the latest SUCCEEDED, non-preview render unless renderId is given. Call get_post_status (postId) to verify.",
|
|
1161
|
+
inputSchema: {
|
|
1162
|
+
type: 'object',
|
|
1163
|
+
properties: {
|
|
1164
|
+
creativeId: { type: 'string', description: 'Creative id, or its display id such as 12a' },
|
|
1165
|
+
postId: { type: 'string', description: "The Post's Work Item id — same value get_post_status takes as postId" },
|
|
1166
|
+
workItemId: { type: 'string', description: 'Deprecated alias for postId' },
|
|
1167
|
+
renderId: { type: 'string', description: 'A specific render to attach (optional — defaults to the latest SUCCEEDED render)' },
|
|
1168
|
+
},
|
|
1169
|
+
required: ['creativeId'],
|
|
1170
|
+
},
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
name: 'create_experiment',
|
|
1174
|
+
description: "Start a hook experiment comparing every lettered variant of a Creative's family (needs at least two; only one RUNNING experiment per family at a time — refused with a conflict otherwise). It settles itself once every variant has published and reported, or via the weekly insights job — nothing to poll. Call get_creative to see its state and, once decided, the winner and numbers.",
|
|
1175
|
+
inputSchema: {
|
|
1176
|
+
type: 'object',
|
|
1177
|
+
properties: {
|
|
1178
|
+
creativeId: { type: 'string', description: 'Any Creative in the family — a lettered variant or the root; resolved automatically' },
|
|
1179
|
+
metric: { type: 'string', enum: ['views', 'engagement_rate', 'avg_view_pct'], description: 'Optional — defaults to views. The decision prefers avg_view_pct whenever every variant reports it, regardless of this choice.' },
|
|
1180
|
+
windowHours: { type: 'number', description: 'Hours after each variant fires before it counts toward the decision (optional, default 72)' },
|
|
1181
|
+
},
|
|
1182
|
+
required: ['creativeId'],
|
|
1183
|
+
},
|
|
1184
|
+
},
|
|
982
1185
|
];
|
|
983
1186
|
function authErrorResponse() {
|
|
984
1187
|
return {
|
|
@@ -1000,6 +1203,20 @@ function successResponse(data) {
|
|
|
1000
1203
|
],
|
|
1001
1204
|
};
|
|
1002
1205
|
}
|
|
1206
|
+
/**
|
|
1207
|
+
* An image content block (base64-encoded bytes + MIME type) plus an optional text block of
|
|
1208
|
+
* metadata — the shape a client needs to actually render the image rather than just read about it.
|
|
1209
|
+
* `preview_creative` is the first tool to need this; every other tool emits text only.
|
|
1210
|
+
*/
|
|
1211
|
+
export function imageResponse(image, meta) {
|
|
1212
|
+
const content = [
|
|
1213
|
+
{ type: 'image', data: image.data.toString('base64'), mimeType: image.mimeType },
|
|
1214
|
+
];
|
|
1215
|
+
if (meta !== undefined) {
|
|
1216
|
+
content.push({ type: 'text', text: JSON.stringify(meta) });
|
|
1217
|
+
}
|
|
1218
|
+
return { content };
|
|
1219
|
+
}
|
|
1003
1220
|
/**
|
|
1004
1221
|
* A shorthand string keeps every existing call site working; the richer object form lets the dispatch
|
|
1005
1222
|
* catch hand back the server's own status/code/title alongside its message, without changing the
|
|
@@ -1045,6 +1262,12 @@ export async function runMcpServer() {
|
|
|
1045
1262
|
const { name, arguments: args } = request.params;
|
|
1046
1263
|
const params = (args ?? {});
|
|
1047
1264
|
try {
|
|
1265
|
+
// Creative tools accept a display id ("12a") wherever they take a Creative.
|
|
1266
|
+
for (const key of ['creativeId', 'variantOf']) {
|
|
1267
|
+
if (typeof params[key] === 'string' && CREATIVE_TOOLS.includes(name)) {
|
|
1268
|
+
params[key] = await resolveCreativeId(params[key], config);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1048
1271
|
switch (name) {
|
|
1049
1272
|
case 'create_work_item': {
|
|
1050
1273
|
const workflow = params['workflow'];
|
|
@@ -1504,6 +1727,66 @@ export async function runMcpServer() {
|
|
|
1504
1727
|
case 'retry_failed_publish_targets': {
|
|
1505
1728
|
return successResponse(await retryFailedPublishTargets({ issueId: params['issueId'] }, config));
|
|
1506
1729
|
}
|
|
1730
|
+
case 'get_brand_kit': {
|
|
1731
|
+
return successResponse(await getBrandKit({ kitId: params['kitId'] }, config));
|
|
1732
|
+
}
|
|
1733
|
+
case 'list_creatives': {
|
|
1734
|
+
return successResponse(await listCreatives({ state: params['state'], brandKitId: params['brandKitId'] }, config));
|
|
1735
|
+
}
|
|
1736
|
+
case 'get_creative': {
|
|
1737
|
+
return successResponse(await getCreative({ creativeId: params['creativeId'] }, config));
|
|
1738
|
+
}
|
|
1739
|
+
case 'create_creative': {
|
|
1740
|
+
return successResponse(await createCreative(params, config));
|
|
1741
|
+
}
|
|
1742
|
+
case 'update_creative': {
|
|
1743
|
+
return successResponse(await updateCreative(params, config));
|
|
1744
|
+
}
|
|
1745
|
+
case 'upload_creative_photo': {
|
|
1746
|
+
return successResponse(await uploadCreativePhoto({
|
|
1747
|
+
filePath: params['filePath'],
|
|
1748
|
+
url: params['url'],
|
|
1749
|
+
label: params['label'],
|
|
1750
|
+
source: params['source'],
|
|
1751
|
+
licence: params['licence'],
|
|
1752
|
+
aiGenerated: params['aiGenerated'],
|
|
1753
|
+
}, config));
|
|
1754
|
+
}
|
|
1755
|
+
case 'render_creative': {
|
|
1756
|
+
return successResponse(await renderCreativeTool({
|
|
1757
|
+
creativeId: params['creativeId'],
|
|
1758
|
+
previewOnly: params['previewOnly'],
|
|
1759
|
+
renderer: params['renderer'],
|
|
1760
|
+
workflowRunId: params['workflowRunId'],
|
|
1761
|
+
}, config));
|
|
1762
|
+
}
|
|
1763
|
+
case 'preview_creative': {
|
|
1764
|
+
const result = await previewCreative({ creativeId: params['creativeId'] }, config);
|
|
1765
|
+
if (result.image) {
|
|
1766
|
+
return imageResponse(result.image, {
|
|
1767
|
+
renderId: result.renderId,
|
|
1768
|
+
state: result.state,
|
|
1769
|
+
url: result.url,
|
|
1770
|
+
note: result.note,
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
return successResponse(result);
|
|
1774
|
+
}
|
|
1775
|
+
case 'attach_creative_to_post': {
|
|
1776
|
+
return successResponse(await attachCreativeToPost({
|
|
1777
|
+
creativeId: params['creativeId'],
|
|
1778
|
+
postId: params['postId'],
|
|
1779
|
+
workItemId: params['workItemId'],
|
|
1780
|
+
renderId: params['renderId'],
|
|
1781
|
+
}, config));
|
|
1782
|
+
}
|
|
1783
|
+
case 'create_experiment': {
|
|
1784
|
+
return successResponse(await createExperiment({
|
|
1785
|
+
creativeId: params['creativeId'],
|
|
1786
|
+
metric: params['metric'],
|
|
1787
|
+
windowHours: params['windowHours'],
|
|
1788
|
+
}, config));
|
|
1789
|
+
}
|
|
1507
1790
|
case 'upload_project_doc_image': {
|
|
1508
1791
|
const result = await uploadProjectDocImage({
|
|
1509
1792
|
path: params['path'],
|