@pixeldojo/mcp 0.6.0 → 0.8.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/dist/cli.cjs +292 -63
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +292 -63
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +292 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +292 -63
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -183,6 +183,85 @@ var init_upload_helpers = __esm({
|
|
|
183
183
|
};
|
|
184
184
|
}
|
|
185
185
|
});
|
|
186
|
+
|
|
187
|
+
// src/skills/schema-snap.ts
|
|
188
|
+
function getFieldConstraints(apiId, client) {
|
|
189
|
+
const cached = schemaCache.get(apiId);
|
|
190
|
+
if (cached) return cached;
|
|
191
|
+
const pending = client.getModelSchema(apiId).then(
|
|
192
|
+
(res) => res.schema?.properties ?? {}
|
|
193
|
+
).catch(() => {
|
|
194
|
+
schemaCache.delete(apiId);
|
|
195
|
+
return null;
|
|
196
|
+
});
|
|
197
|
+
schemaCache.set(apiId, pending);
|
|
198
|
+
return pending;
|
|
199
|
+
}
|
|
200
|
+
function parseAspectRatio(ar) {
|
|
201
|
+
const m = /^\s*(\d+)\s*:\s*(\d+)\s*$/.exec(ar);
|
|
202
|
+
if (!m) return null;
|
|
203
|
+
const w = Number(m[1]);
|
|
204
|
+
const h = Number(m[2]);
|
|
205
|
+
return h > 0 ? w / h : null;
|
|
206
|
+
}
|
|
207
|
+
function nearestAspectFromEnum(requested, allowed) {
|
|
208
|
+
if (allowed.includes(requested)) return requested;
|
|
209
|
+
const target = parseAspectRatio(requested);
|
|
210
|
+
if (target === null) return requested;
|
|
211
|
+
let best = requested;
|
|
212
|
+
let bestDiff = Infinity;
|
|
213
|
+
for (const candidate of allowed) {
|
|
214
|
+
const r = parseAspectRatio(candidate);
|
|
215
|
+
if (r === null) continue;
|
|
216
|
+
const diff = Math.abs(r - target);
|
|
217
|
+
if (diff < bestDiff) {
|
|
218
|
+
bestDiff = diff;
|
|
219
|
+
best = candidate;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return best;
|
|
223
|
+
}
|
|
224
|
+
async function snapAspectRatio(apiId, requested, client, opts = {}) {
|
|
225
|
+
if (!requested) return void 0;
|
|
226
|
+
const props = await getFieldConstraints(apiId, client);
|
|
227
|
+
if (props === null) {
|
|
228
|
+
return opts.onUnknown === "omit" ? void 0 : requested;
|
|
229
|
+
}
|
|
230
|
+
const field = props.aspect_ratio;
|
|
231
|
+
if (!field) return void 0;
|
|
232
|
+
if (!field.enum || field.enum.length === 0) return requested;
|
|
233
|
+
return nearestAspectFromEnum(requested, field.enum);
|
|
234
|
+
}
|
|
235
|
+
async function snapDuration(apiId, requested, client, opts = {}) {
|
|
236
|
+
if (requested === void 0) return void 0;
|
|
237
|
+
const props = await getFieldConstraints(apiId, client);
|
|
238
|
+
if (props === null) {
|
|
239
|
+
return opts.onUnknown === "omit" ? void 0 : requested;
|
|
240
|
+
}
|
|
241
|
+
const field = props.duration;
|
|
242
|
+
if (!field) return void 0;
|
|
243
|
+
if (field.enum && field.enum.length > 0) {
|
|
244
|
+
const allowed = field.enum.map(Number).filter((n) => Number.isFinite(n));
|
|
245
|
+
if (allowed.length === 0) return requested;
|
|
246
|
+
if (allowed.includes(requested)) return requested;
|
|
247
|
+
return allowed.reduce(
|
|
248
|
+
(best, candidate) => Math.abs(candidate - requested) < Math.abs(best - requested) ? candidate : best
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
if (typeof field.minimum === "number" || typeof field.maximum === "number") {
|
|
252
|
+
let v = requested;
|
|
253
|
+
if (typeof field.minimum === "number") v = Math.max(field.minimum, v);
|
|
254
|
+
if (typeof field.maximum === "number") v = Math.min(field.maximum, v);
|
|
255
|
+
return v;
|
|
256
|
+
}
|
|
257
|
+
return requested;
|
|
258
|
+
}
|
|
259
|
+
var schemaCache;
|
|
260
|
+
var init_schema_snap = __esm({
|
|
261
|
+
"src/skills/schema-snap.ts"() {
|
|
262
|
+
schemaCache = /* @__PURE__ */ new Map();
|
|
263
|
+
}
|
|
264
|
+
});
|
|
186
265
|
function buildPayload(apiId, input) {
|
|
187
266
|
const body = { prompt: input.prompt };
|
|
188
267
|
if (input.aspect_ratio) body.aspect_ratio = input.aspect_ratio;
|
|
@@ -235,6 +314,13 @@ async function run(input, ctx) {
|
|
|
235
314
|
};
|
|
236
315
|
}
|
|
237
316
|
}
|
|
317
|
+
if (!VIDEO_INPUT_MODELS.has(apiId)) {
|
|
318
|
+
const [aspect_ratio, duration] = await Promise.all([
|
|
319
|
+
snapAspectRatio(apiId, resolved.aspect_ratio, ctx.client),
|
|
320
|
+
snapDuration(apiId, resolved.duration, ctx.client)
|
|
321
|
+
]);
|
|
322
|
+
resolved = { ...resolved, aspect_ratio, duration };
|
|
323
|
+
}
|
|
238
324
|
const body = buildPayload(apiId, resolved);
|
|
239
325
|
const submitted = await ctx.client.run(apiId, body);
|
|
240
326
|
const result = await pollJobUntilDoneOrHandoff(
|
|
@@ -251,12 +337,13 @@ async function run(input, ctx) {
|
|
|
251
337
|
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : urls.length === 1 ? `Generated. Asset: ${urls[0]}` : `Generated ${urls.length} assets. URLs: ${urls.join(", ")}`
|
|
252
338
|
);
|
|
253
339
|
}
|
|
254
|
-
var InputSchema, DEFAULT_MODEL, InputJsonSchema, generateSkill;
|
|
340
|
+
var InputSchema, DEFAULT_MODEL, VIDEO_INPUT_MODELS, InputJsonSchema, generateSkill;
|
|
255
341
|
var init_generate = __esm({
|
|
256
342
|
"src/skills/generate.ts"() {
|
|
257
343
|
init_poll();
|
|
258
344
|
init_types();
|
|
259
345
|
init_upload_helpers();
|
|
346
|
+
init_schema_snap();
|
|
260
347
|
InputSchema = zod.z.object({
|
|
261
348
|
prompt: zod.z.string().min(1).max(8e3).describe("Prompt describing what to generate."),
|
|
262
349
|
model: zod.z.string().optional().describe(
|
|
@@ -273,6 +360,7 @@ var init_generate = __esm({
|
|
|
273
360
|
)
|
|
274
361
|
});
|
|
275
362
|
DEFAULT_MODEL = "google-nano-banana";
|
|
363
|
+
VIDEO_INPUT_MODELS = /* @__PURE__ */ new Set(["grok-video-extend", "wan-video-edit", "seedance-video-edit"]);
|
|
276
364
|
InputJsonSchema = {
|
|
277
365
|
type: "object",
|
|
278
366
|
properties: {
|
|
@@ -370,6 +458,10 @@ async function run2(input, ctx) {
|
|
|
370
458
|
};
|
|
371
459
|
}
|
|
372
460
|
const apiId = resolved.model ?? DEFAULT_MODEL2;
|
|
461
|
+
resolved = {
|
|
462
|
+
...resolved,
|
|
463
|
+
aspect_ratio: await snapAspectRatio(apiId, resolved.aspect_ratio, ctx.client)
|
|
464
|
+
};
|
|
373
465
|
const body = buildPayload2(apiId, resolved);
|
|
374
466
|
const submitted = await ctx.client.run(apiId, body);
|
|
375
467
|
const result = await pollJobUntilDoneOrHandoff(
|
|
@@ -392,6 +484,7 @@ var init_edit = __esm({
|
|
|
392
484
|
init_poll();
|
|
393
485
|
init_types();
|
|
394
486
|
init_upload_helpers();
|
|
487
|
+
init_schema_snap();
|
|
395
488
|
DEFAULT_MODEL2 = "wan-2.7-image-edit";
|
|
396
489
|
ALLOWED_MODELS = [
|
|
397
490
|
"wan-2.7-image-edit",
|
|
@@ -487,9 +580,10 @@ async function run3(input, ctx) {
|
|
|
487
580
|
body.image_urls = [input.reference_image_url];
|
|
488
581
|
}
|
|
489
582
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
}
|
|
583
|
+
const snappedAspect = await snapAspectRatio(apiId, input.aspect_ratio, ctx.client, {
|
|
584
|
+
onUnknown: "omit"
|
|
585
|
+
});
|
|
586
|
+
if (snappedAspect !== void 0) body.aspect_ratio = snappedAspect;
|
|
493
587
|
const submitted = await ctx.client.run(apiId, body);
|
|
494
588
|
const result = await pollJobUntilDoneOrHandoff(
|
|
495
589
|
submitted.jobId,
|
|
@@ -505,28 +599,15 @@ async function run3(input, ctx) {
|
|
|
505
599
|
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Character shot ready. Asset: ${urls[0]}`
|
|
506
600
|
);
|
|
507
601
|
}
|
|
508
|
-
var ALLOWED, DEFAULT_MODEL3, REQUIRES_REFERENCE,
|
|
602
|
+
var ALLOWED, DEFAULT_MODEL3, REQUIRES_REFERENCE, InputSchema3, InputJsonSchema3, characterSkill;
|
|
509
603
|
var init_character = __esm({
|
|
510
604
|
"src/skills/character.ts"() {
|
|
511
605
|
init_poll();
|
|
512
606
|
init_types();
|
|
607
|
+
init_schema_snap();
|
|
513
608
|
ALLOWED = ["seedream-5", "seedream-4", "flux-edit", "gpt-image-2-edit"];
|
|
514
609
|
DEFAULT_MODEL3 = "seedream-5";
|
|
515
610
|
REQUIRES_REFERENCE = /* @__PURE__ */ new Set(["flux-edit", "gpt-image-2-edit"]);
|
|
516
|
-
FLUX_EDIT_ASPECT_RATIOS = /* @__PURE__ */ new Set([
|
|
517
|
-
"1:1",
|
|
518
|
-
"16:9",
|
|
519
|
-
"9:16",
|
|
520
|
-
"21:9",
|
|
521
|
-
"9:21",
|
|
522
|
-
"3:2",
|
|
523
|
-
"2:3",
|
|
524
|
-
"4:5",
|
|
525
|
-
"5:4",
|
|
526
|
-
"3:4",
|
|
527
|
-
"4:3",
|
|
528
|
-
"match_input_image"
|
|
529
|
-
]);
|
|
530
611
|
InputSchema3 = zod.z.object({
|
|
531
612
|
prompt: zod.z.string().min(1).max(8e3),
|
|
532
613
|
model: zod.z.string().optional().describe(`One of: ${ALLOWED.join(", ")}. Defaults to ${DEFAULT_MODEL3}.`),
|
|
@@ -569,9 +650,13 @@ async function run4(input, ctx) {
|
|
|
569
650
|
};
|
|
570
651
|
}
|
|
571
652
|
const apiId = requested;
|
|
653
|
+
const [snappedAspect, snappedDuration] = await Promise.all([
|
|
654
|
+
snapAspectRatio(apiId, input.aspect_ratio, ctx.client),
|
|
655
|
+
snapDuration(apiId, input.duration, ctx.client)
|
|
656
|
+
]);
|
|
572
657
|
const body = { prompt: input.brief };
|
|
573
|
-
if (
|
|
574
|
-
if (
|
|
658
|
+
if (snappedAspect !== void 0) body.aspect_ratio = snappedAspect;
|
|
659
|
+
if (snappedDuration !== void 0) body.duration = snappedDuration;
|
|
575
660
|
const submitted = await ctx.client.run(apiId, body);
|
|
576
661
|
const result = await pollJobUntilDoneOrHandoff(
|
|
577
662
|
submitted.jobId,
|
|
@@ -592,6 +677,7 @@ var init_storyboard = __esm({
|
|
|
592
677
|
"src/skills/storyboard.ts"() {
|
|
593
678
|
init_poll();
|
|
594
679
|
init_types();
|
|
680
|
+
init_schema_snap();
|
|
595
681
|
ALLOWED2 = [
|
|
596
682
|
"veo-3.1-fast",
|
|
597
683
|
"veo-3.1-standard",
|
|
@@ -850,6 +936,146 @@ var init_from_url = __esm({
|
|
|
850
936
|
}
|
|
851
937
|
});
|
|
852
938
|
async function run8(input, ctx) {
|
|
939
|
+
const productImages = [
|
|
940
|
+
...input.product_image_urls ?? [],
|
|
941
|
+
...await Promise.all((input.product_image_paths ?? []).map((p) => uploadLocalFile(p, ctx.client)))
|
|
942
|
+
];
|
|
943
|
+
const characterImages = [
|
|
944
|
+
...input.character_image_urls ?? [],
|
|
945
|
+
...await Promise.all((input.character_image_paths ?? []).map((p) => uploadLocalFile(p, ctx.client)))
|
|
946
|
+
];
|
|
947
|
+
const body = {
|
|
948
|
+
style: input.style,
|
|
949
|
+
product_url: input.product_url,
|
|
950
|
+
product: !input.product_url && input.product_name ? {
|
|
951
|
+
name: input.product_name,
|
|
952
|
+
description: input.product_description,
|
|
953
|
+
images: productImages
|
|
954
|
+
} : void 0,
|
|
955
|
+
character_images: characterImages.length > 0 ? characterImages : void 0,
|
|
956
|
+
location: input.location_description || input.location_image_url ? { description: input.location_description, image_url: input.location_image_url } : void 0,
|
|
957
|
+
hook: input.hook,
|
|
958
|
+
script: input.script,
|
|
959
|
+
quality: input.quality,
|
|
960
|
+
resolution: input.resolution,
|
|
961
|
+
aspect_ratio: input.aspect_ratio,
|
|
962
|
+
duration: input.duration
|
|
963
|
+
};
|
|
964
|
+
const client = ctx.client;
|
|
965
|
+
const submitted = await client.runAd(body);
|
|
966
|
+
const result = await pollJobUntilDoneOrHandoff(
|
|
967
|
+
submitted.jobId,
|
|
968
|
+
(id) => ctx.client.getJob(id),
|
|
969
|
+
ctx.buildStatusUrl,
|
|
970
|
+
{
|
|
971
|
+
now: ctx.pollOverrides?.now,
|
|
972
|
+
sleep: ctx.pollOverrides?.sleep
|
|
973
|
+
}
|
|
974
|
+
);
|
|
975
|
+
const styleLabel = submitted.ad?.style ?? input.style ?? "ugc-testimonial";
|
|
976
|
+
return pollResultToSkillResult(
|
|
977
|
+
result,
|
|
978
|
+
(urls) => urls.length === 0 ? `Ad job ${submitted.jobId} completed but returned no assets.` : `Ad rendered (style: ${styleLabel}${submitted.ad?.product?.name ? `, product: ${submitted.ad.product.name}` : ""}). Video: ${urls[0]}`
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
var InputSchema8, InputJsonSchema8, adSkill;
|
|
982
|
+
var init_ad = __esm({
|
|
983
|
+
"src/skills/ad.ts"() {
|
|
984
|
+
init_types();
|
|
985
|
+
init_poll();
|
|
986
|
+
init_upload_helpers();
|
|
987
|
+
InputSchema8 = zod.z.object({
|
|
988
|
+
style: zod.z.string().max(80).optional().describe(
|
|
989
|
+
"Ad style slug (default ugc-testimonial). Catalog: GET /api/v1/marketing/presets \u2014 e.g. ugc-testimonial, unboxing-reveal, unboxing-asmr, virtual-try-on, street-style, product-showcase, macro-details, crush-test, hyper-motion, before-after, day-in-the-life, the-gift, tv-spot."
|
|
990
|
+
),
|
|
991
|
+
product_url: zod.z.string().url().optional().describe("Product page URL. Name, description, and images are extracted automatically."),
|
|
992
|
+
product_name: zod.z.string().max(200).optional(),
|
|
993
|
+
product_description: zod.z.string().max(2e3).optional(),
|
|
994
|
+
product_image_urls: zod.z.array(zod.z.string().url()).max(5).optional(),
|
|
995
|
+
product_image_paths: zod.z.array(zod.z.string()).max(5).optional().describe("Absolute local paths; uploaded to 24h temp storage automatically."),
|
|
996
|
+
character_image_urls: zod.z.array(zod.z.string().url()).max(4).optional().describe("Presenter reference images for a consistent on-camera character."),
|
|
997
|
+
character_image_paths: zod.z.array(zod.z.string()).max(4).optional(),
|
|
998
|
+
location_description: zod.z.string().max(1500).optional().describe('Where the ad takes place ("a sunlit Parisian cafe"). Text is enough; no image needed.'),
|
|
999
|
+
location_image_url: zod.z.string().url().optional(),
|
|
1000
|
+
hook: zod.z.string().max(1e3).optional().describe("The opening visual beat (first 1-2 seconds). Omit to use the style default."),
|
|
1001
|
+
script: zod.z.string().max(1e3).optional().describe("The exact spoken line, voiced word for word. Omit and the presenter improvises."),
|
|
1002
|
+
quality: zod.z.enum(["mini", "fast", "high"]).optional(),
|
|
1003
|
+
resolution: zod.z.enum(["480p", "720p", "1080p", "4k"]).optional().describe('1080p/4k require quality "high".'),
|
|
1004
|
+
aspect_ratio: zod.z.enum(["16:9", "4:3", "1:1", "3:4", "9:16", "21:9"]).optional(),
|
|
1005
|
+
duration: zod.z.number().int().min(4).max(15).optional()
|
|
1006
|
+
}).refine(
|
|
1007
|
+
(v) => v.product_url || (v.product_image_urls?.length || v.product_image_paths?.length) && v.product_name,
|
|
1008
|
+
{
|
|
1009
|
+
message: "Pass product_url, OR product_name plus product_image_urls/product_image_paths.",
|
|
1010
|
+
path: ["product_url"]
|
|
1011
|
+
}
|
|
1012
|
+
);
|
|
1013
|
+
InputJsonSchema8 = {
|
|
1014
|
+
type: "object",
|
|
1015
|
+
properties: {
|
|
1016
|
+
style: {
|
|
1017
|
+
type: "string",
|
|
1018
|
+
description: "Ad style slug (default ugc-testimonial). Catalog: GET /api/v1/marketing/presets \u2014 e.g. ugc-testimonial, unboxing-reveal, unboxing-asmr, virtual-try-on, street-style, mirror-fit-check, pro-try-on, product-showcase, macro-details, secret-hack-reveal, crush-test, hyper-motion, before-after, day-in-the-life, the-gift, tv-spot, gadget-saved-me, selfie-testimonial, direct-to-camera, pack-an-order, mystery-box."
|
|
1019
|
+
},
|
|
1020
|
+
product_url: {
|
|
1021
|
+
type: "string",
|
|
1022
|
+
format: "uri",
|
|
1023
|
+
description: "Product page URL. Name, description, and images are extracted automatically."
|
|
1024
|
+
},
|
|
1025
|
+
product_name: { type: "string" },
|
|
1026
|
+
product_description: { type: "string" },
|
|
1027
|
+
product_image_urls: { type: "array", items: { type: "string", format: "uri" }, maxItems: 5 },
|
|
1028
|
+
product_image_paths: {
|
|
1029
|
+
type: "array",
|
|
1030
|
+
items: { type: "string" },
|
|
1031
|
+
maxItems: 5,
|
|
1032
|
+
description: "Absolute local file paths; uploaded to 24h temp storage automatically."
|
|
1033
|
+
},
|
|
1034
|
+
character_image_urls: {
|
|
1035
|
+
type: "array",
|
|
1036
|
+
items: { type: "string", format: "uri" },
|
|
1037
|
+
maxItems: 4,
|
|
1038
|
+
description: "Presenter reference images for a consistent on-camera character."
|
|
1039
|
+
},
|
|
1040
|
+
character_image_paths: { type: "array", items: { type: "string" }, maxItems: 4 },
|
|
1041
|
+
location_description: {
|
|
1042
|
+
type: "string",
|
|
1043
|
+
description: 'Where the ad takes place ("a sunlit Parisian cafe"). Text is enough.'
|
|
1044
|
+
},
|
|
1045
|
+
location_image_url: { type: "string", format: "uri" },
|
|
1046
|
+
hook: {
|
|
1047
|
+
type: "string",
|
|
1048
|
+
description: "The opening visual beat (first 1-2 seconds). Omit to use the style default."
|
|
1049
|
+
},
|
|
1050
|
+
script: {
|
|
1051
|
+
type: "string",
|
|
1052
|
+
description: "The exact spoken line, voiced word for word. Omit and the presenter improvises."
|
|
1053
|
+
},
|
|
1054
|
+
quality: { type: "string", enum: ["mini", "fast", "high"] },
|
|
1055
|
+
resolution: {
|
|
1056
|
+
type: "string",
|
|
1057
|
+
enum: ["480p", "720p", "1080p", "4k"],
|
|
1058
|
+
description: '1080p/4k require quality "high".'
|
|
1059
|
+
},
|
|
1060
|
+
aspect_ratio: { type: "string", enum: ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9"] },
|
|
1061
|
+
duration: { type: "integer", minimum: 4, maximum: 15 }
|
|
1062
|
+
}
|
|
1063
|
+
// "product_url OR product_name+images" is enforced by the server and the
|
|
1064
|
+
// Zod refine; no root-level oneOf (Grok rejects non-object root unions).
|
|
1065
|
+
};
|
|
1066
|
+
adSkill = {
|
|
1067
|
+
name: "pixeldojo:ad",
|
|
1068
|
+
description: "Marketing Studio: turn any product into a video ad. Pass a product URL (auto-extracted) or product images, pick an ad style (UGC testimonial, unboxing, try-on, showcase, TV spot, and more via GET /api/v1/marketing/presets), optionally add presenter reference images, a location, a hook, and the exact spoken script. Renders with voiceover; returns the video or a statusUrl handoff to poll via pixeldojo:status. Ideal for automated generate-and-post workflows.",
|
|
1069
|
+
inputZod: InputSchema8,
|
|
1070
|
+
inputJsonSchema: InputJsonSchema8,
|
|
1071
|
+
// Composition skill — the server routes to the ad engine internally.
|
|
1072
|
+
allowedModels: [],
|
|
1073
|
+
defaultModel: "",
|
|
1074
|
+
run: run8
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
1078
|
+
async function run9(input, ctx) {
|
|
853
1079
|
const client = ctx.client;
|
|
854
1080
|
const result = await client.runCampaign(input);
|
|
855
1081
|
if (result.kind === "campaign") {
|
|
@@ -876,10 +1102,10 @@ async function run8(input, ctx) {
|
|
|
876
1102
|
statusUrl: result.statusUrl ?? ctx.buildStatusUrl(result.campaignId)
|
|
877
1103
|
};
|
|
878
1104
|
}
|
|
879
|
-
var
|
|
1105
|
+
var InputSchema9, InputJsonSchema9, campaignSkill;
|
|
880
1106
|
var init_campaign = __esm({
|
|
881
1107
|
"src/skills/campaign.ts"() {
|
|
882
|
-
|
|
1108
|
+
InputSchema9 = zod.z.object({
|
|
883
1109
|
productUrl: zod.z.string().url().optional().describe("Product page URL. We extract name + description + images automatically."),
|
|
884
1110
|
product: zod.z.object({
|
|
885
1111
|
name: zod.z.string().min(1).max(200),
|
|
@@ -895,7 +1121,7 @@ var init_campaign = __esm({
|
|
|
895
1121
|
message: "productUrl or product is required",
|
|
896
1122
|
path: ["productUrl"]
|
|
897
1123
|
});
|
|
898
|
-
|
|
1124
|
+
InputJsonSchema9 = {
|
|
899
1125
|
type: "object",
|
|
900
1126
|
properties: {
|
|
901
1127
|
productUrl: {
|
|
@@ -926,17 +1152,17 @@ var init_campaign = __esm({
|
|
|
926
1152
|
campaignSkill = {
|
|
927
1153
|
name: "pixeldojo:campaign",
|
|
928
1154
|
description: "Generate a coherent product launch package (hero image + N lifestyle variants + optional vertical video) from one URL or product profile. Composes hero / lifestyle / video models server-side; returns assets in one call or a handoff with campaignId to poll via pixeldojo:campaign_status.",
|
|
929
|
-
inputZod:
|
|
930
|
-
inputJsonSchema:
|
|
1155
|
+
inputZod: InputSchema9,
|
|
1156
|
+
inputJsonSchema: InputJsonSchema9,
|
|
931
1157
|
// Composition skill — internal sub-jobs route to per-tool models, no
|
|
932
1158
|
// single allowed-models list applies here.
|
|
933
1159
|
allowedModels: [],
|
|
934
1160
|
defaultModel: "",
|
|
935
|
-
run:
|
|
1161
|
+
run: run9
|
|
936
1162
|
};
|
|
937
1163
|
}
|
|
938
1164
|
});
|
|
939
|
-
async function
|
|
1165
|
+
async function run10(input, ctx) {
|
|
940
1166
|
const client = ctx.client;
|
|
941
1167
|
const result = await client.getCampaign(input.campaignId);
|
|
942
1168
|
if (result.kind === "campaign") {
|
|
@@ -966,13 +1192,13 @@ async function run9(input, ctx) {
|
|
|
966
1192
|
statusUrl: result.statusUrl ?? ctx.buildStatusUrl(result.campaignId)
|
|
967
1193
|
};
|
|
968
1194
|
}
|
|
969
|
-
var
|
|
1195
|
+
var InputSchema10, InputJsonSchema10, campaignStatusSkill;
|
|
970
1196
|
var init_campaign_status = __esm({
|
|
971
1197
|
"src/skills/campaign-status.ts"() {
|
|
972
|
-
|
|
1198
|
+
InputSchema10 = zod.z.object({
|
|
973
1199
|
campaignId: zod.z.string().min(1).max(200).describe("Campaign id returned from a prior pixeldojo:campaign handoff.")
|
|
974
1200
|
});
|
|
975
|
-
|
|
1201
|
+
InputJsonSchema10 = {
|
|
976
1202
|
type: "object",
|
|
977
1203
|
properties: {
|
|
978
1204
|
campaignId: {
|
|
@@ -985,15 +1211,15 @@ var init_campaign_status = __esm({
|
|
|
985
1211
|
campaignStatusSkill = {
|
|
986
1212
|
name: "pixeldojo:campaign_status",
|
|
987
1213
|
description: "Poll a campaign by campaignId returned from pixeldojo:campaign. Returns assets when every sub-job is done, or a handoff describing what is still in flight.",
|
|
988
|
-
inputZod:
|
|
989
|
-
inputJsonSchema:
|
|
1214
|
+
inputZod: InputSchema10,
|
|
1215
|
+
inputJsonSchema: InputJsonSchema10,
|
|
990
1216
|
allowedModels: [],
|
|
991
1217
|
defaultModel: "",
|
|
992
|
-
run:
|
|
1218
|
+
run: run10
|
|
993
1219
|
};
|
|
994
1220
|
}
|
|
995
1221
|
});
|
|
996
|
-
async function
|
|
1222
|
+
async function run11(input, ctx) {
|
|
997
1223
|
let url;
|
|
998
1224
|
try {
|
|
999
1225
|
url = await uploadLocalFile(input.path, ctx.client);
|
|
@@ -1009,16 +1235,16 @@ async function run10(input, ctx) {
|
|
|
1009
1235
|
(temp storage; auto-deletes in ~24h \u2014 pass this URL as image_url to :generate or :edit)`
|
|
1010
1236
|
};
|
|
1011
1237
|
}
|
|
1012
|
-
var
|
|
1238
|
+
var InputSchema11, InputJsonSchema11, uploadSkill;
|
|
1013
1239
|
var init_upload = __esm({
|
|
1014
1240
|
"src/skills/upload.ts"() {
|
|
1015
1241
|
init_upload_helpers();
|
|
1016
|
-
|
|
1242
|
+
InputSchema11 = zod.z.object({
|
|
1017
1243
|
path: zod.z.string().min(1).max(4096).describe(
|
|
1018
1244
|
"Absolute local file path to upload. JPEG, PNG, WebP, GIF (\u226450MB) or MP4, WebM, MOV (\u2264200MB). Returns a public URL on the temp CDN; storage auto-expires after 24 hours."
|
|
1019
1245
|
)
|
|
1020
1246
|
});
|
|
1021
|
-
|
|
1247
|
+
InputJsonSchema11 = {
|
|
1022
1248
|
type: "object",
|
|
1023
1249
|
properties: {
|
|
1024
1250
|
path: {
|
|
@@ -1031,15 +1257,15 @@ var init_upload = __esm({
|
|
|
1031
1257
|
uploadSkill = {
|
|
1032
1258
|
name: "pixeldojo:upload",
|
|
1033
1259
|
description: "Upload a local image or video file and get back a public URL you can pass to :generate or :edit as image_url. Use when the user has a reference image on disk (drag-dropped into Claude Code, screenshot, etc.) and you need a URL. Storage auto-expires after 24 hours.",
|
|
1034
|
-
inputZod:
|
|
1035
|
-
inputJsonSchema:
|
|
1260
|
+
inputZod: InputSchema11,
|
|
1261
|
+
inputJsonSchema: InputJsonSchema11,
|
|
1036
1262
|
allowedModels: [],
|
|
1037
1263
|
defaultModel: "",
|
|
1038
|
-
run:
|
|
1264
|
+
run: run11
|
|
1039
1265
|
};
|
|
1040
1266
|
}
|
|
1041
1267
|
});
|
|
1042
|
-
async function
|
|
1268
|
+
async function run12(input, ctx) {
|
|
1043
1269
|
const requested = input.model ?? DEFAULT_MODEL6;
|
|
1044
1270
|
if (!ALLOWED4.includes(requested)) {
|
|
1045
1271
|
return {
|
|
@@ -1088,7 +1314,7 @@ async function run11(input, ctx) {
|
|
|
1088
1314
|
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Audio ready. Asset: ${urls[0]}`
|
|
1089
1315
|
);
|
|
1090
1316
|
}
|
|
1091
|
-
var ALLOWED4, DEFAULT_MODEL6,
|
|
1317
|
+
var ALLOWED4, DEFAULT_MODEL6, InputSchema12, InputJsonSchema12, audioSkill;
|
|
1092
1318
|
var init_audio = __esm({
|
|
1093
1319
|
"src/skills/audio.ts"() {
|
|
1094
1320
|
init_poll();
|
|
@@ -1096,7 +1322,7 @@ var init_audio = __esm({
|
|
|
1096
1322
|
init_types();
|
|
1097
1323
|
ALLOWED4 = ["seed-audio", "text-to-speech"];
|
|
1098
1324
|
DEFAULT_MODEL6 = "seed-audio";
|
|
1099
|
-
|
|
1325
|
+
InputSchema12 = zod.z.object({
|
|
1100
1326
|
prompt: zod.z.string().min(1).describe(
|
|
1101
1327
|
"A script for speech, or a scene description for cinematic audio (dialogue + effects + music). Reference uploaded clips as @Audio1..@Audio3."
|
|
1102
1328
|
),
|
|
@@ -1107,7 +1333,7 @@ var init_audio = __esm({
|
|
|
1107
1333
|
output_format: zod.z.string().optional().describe("seed-audio: mp3 (default), wav, pcm, ogg_opus. text-to-speech: mp3, wav, flac, pcm."),
|
|
1108
1334
|
speed: zod.z.number().min(0.5).max(2).optional().describe("Speech speed multiplier (0.5\u20132).")
|
|
1109
1335
|
});
|
|
1110
|
-
|
|
1336
|
+
InputJsonSchema12 = {
|
|
1111
1337
|
type: "object",
|
|
1112
1338
|
properties: {
|
|
1113
1339
|
prompt: { type: "string" },
|
|
@@ -1123,15 +1349,15 @@ var init_audio = __esm({
|
|
|
1123
1349
|
audioSkill = {
|
|
1124
1350
|
name: "pixeldojo:audio",
|
|
1125
1351
|
description: "Generate audio: speech, multi-character dialogue, sound effects, and background music from one prompt (Seed Audio 1.0 by default; plain TTS available).",
|
|
1126
|
-
inputZod:
|
|
1127
|
-
inputJsonSchema:
|
|
1352
|
+
inputZod: InputSchema12,
|
|
1353
|
+
inputJsonSchema: InputJsonSchema12,
|
|
1128
1354
|
allowedModels: [...ALLOWED4],
|
|
1129
1355
|
defaultModel: DEFAULT_MODEL6,
|
|
1130
|
-
run:
|
|
1356
|
+
run: run12
|
|
1131
1357
|
};
|
|
1132
1358
|
}
|
|
1133
1359
|
});
|
|
1134
|
-
async function
|
|
1360
|
+
async function run13(input, ctx) {
|
|
1135
1361
|
const res = await ctx.client.listLibrary({
|
|
1136
1362
|
q: input.q,
|
|
1137
1363
|
model: input.model,
|
|
@@ -1162,16 +1388,16 @@ ${lines.join("\n")}
|
|
|
1162
1388
|
Pass any URL back into :generate, :edit, :character, or :upscale as a reference input.`
|
|
1163
1389
|
};
|
|
1164
1390
|
}
|
|
1165
|
-
var
|
|
1391
|
+
var InputSchema13, InputJsonSchema13, librarySkill;
|
|
1166
1392
|
var init_library = __esm({
|
|
1167
1393
|
"src/skills/library.ts"() {
|
|
1168
|
-
|
|
1394
|
+
InputSchema13 = zod.z.object({
|
|
1169
1395
|
q: zod.z.string().optional().describe("Substring match against the prompt that produced the asset."),
|
|
1170
1396
|
model: zod.z.string().optional().describe("Restrict to a single model (apiId)."),
|
|
1171
1397
|
modality: zod.z.enum(["image", "video", "audio"]).optional().describe("Restrict to one output type."),
|
|
1172
1398
|
limit: zod.z.number().int().min(1).max(50).optional().describe("Max results (default 10).")
|
|
1173
1399
|
});
|
|
1174
|
-
|
|
1400
|
+
InputJsonSchema13 = {
|
|
1175
1401
|
type: "object",
|
|
1176
1402
|
properties: {
|
|
1177
1403
|
q: { type: "string" },
|
|
@@ -1184,15 +1410,15 @@ var init_library = __esm({
|
|
|
1184
1410
|
librarySkill = {
|
|
1185
1411
|
name: "pixeldojo:library",
|
|
1186
1412
|
description: "Search your media library: saved My Media items (permanent) and recent API/MCP generations (expire after 24h), newest first. Returns asset URLs to reuse as reference inputs. Keep a result forever with pixeldojo:save.",
|
|
1187
|
-
inputZod:
|
|
1188
|
-
inputJsonSchema:
|
|
1413
|
+
inputZod: InputSchema13,
|
|
1414
|
+
inputJsonSchema: InputJsonSchema13,
|
|
1189
1415
|
allowedModels: [],
|
|
1190
1416
|
defaultModel: "",
|
|
1191
|
-
run:
|
|
1417
|
+
run: run13
|
|
1192
1418
|
};
|
|
1193
1419
|
}
|
|
1194
1420
|
});
|
|
1195
|
-
async function
|
|
1421
|
+
async function run14(input, ctx) {
|
|
1196
1422
|
const res = await ctx.client.saveMedia({
|
|
1197
1423
|
url: input.url,
|
|
1198
1424
|
prompt: input.prompt,
|
|
@@ -1206,17 +1432,17 @@ async function run13(input, ctx) {
|
|
|
1206
1432
|
It will appear at https://pixeldojo.ai/my-images and in pixeldojo:library searches.`
|
|
1207
1433
|
};
|
|
1208
1434
|
}
|
|
1209
|
-
var
|
|
1435
|
+
var InputSchema14, InputJsonSchema14, saveSkill;
|
|
1210
1436
|
var init_save = __esm({
|
|
1211
1437
|
"src/skills/save.ts"() {
|
|
1212
|
-
|
|
1438
|
+
InputSchema14 = zod.z.object({
|
|
1213
1439
|
url: zod.z.string().url().describe("The asset URL to save (image or video)."),
|
|
1214
1440
|
prompt: zod.z.string().optional().describe("The prompt that produced it \u2014 makes it findable in the library later."),
|
|
1215
1441
|
tool_name: zod.z.string().optional().describe("Tool/model slug that produced it."),
|
|
1216
1442
|
modality: zod.z.enum(["image", "video", "audio"]).optional(),
|
|
1217
1443
|
job_id: zod.z.string().optional().describe("The jobId that produced this asset, when known.")
|
|
1218
1444
|
});
|
|
1219
|
-
|
|
1445
|
+
InputJsonSchema14 = {
|
|
1220
1446
|
type: "object",
|
|
1221
1447
|
properties: {
|
|
1222
1448
|
url: { type: "string", format: "uri" },
|
|
@@ -1230,11 +1456,11 @@ var init_save = __esm({
|
|
|
1230
1456
|
saveSkill = {
|
|
1231
1457
|
name: "pixeldojo:save",
|
|
1232
1458
|
description: "Save a generated image or video into the user's My Media library permanently. Generation outputs otherwise expire after 24 hours \u2014 call this when the user wants to keep a result.",
|
|
1233
|
-
inputZod:
|
|
1234
|
-
inputJsonSchema:
|
|
1459
|
+
inputZod: InputSchema14,
|
|
1460
|
+
inputJsonSchema: InputJsonSchema14,
|
|
1235
1461
|
allowedModels: [],
|
|
1236
1462
|
defaultModel: "",
|
|
1237
|
-
run:
|
|
1463
|
+
run: run14
|
|
1238
1464
|
};
|
|
1239
1465
|
}
|
|
1240
1466
|
});
|
|
@@ -1446,6 +1672,7 @@ var init_workflows = __esm({
|
|
|
1446
1672
|
var skills_exports = {};
|
|
1447
1673
|
__export(skills_exports, {
|
|
1448
1674
|
ALL_SKILLS: () => ALL_SKILLS,
|
|
1675
|
+
adSkill: () => adSkill,
|
|
1449
1676
|
audioSkill: () => audioSkill,
|
|
1450
1677
|
campaignSkill: () => campaignSkill,
|
|
1451
1678
|
campaignStatusSkill: () => campaignStatusSkill,
|
|
@@ -1477,6 +1704,7 @@ var init_skills = __esm({
|
|
|
1477
1704
|
init_upscale();
|
|
1478
1705
|
init_status();
|
|
1479
1706
|
init_from_url();
|
|
1707
|
+
init_ad();
|
|
1480
1708
|
init_campaign();
|
|
1481
1709
|
init_campaign_status();
|
|
1482
1710
|
init_upload();
|
|
@@ -1499,6 +1727,7 @@ var init_skills = __esm({
|
|
|
1499
1727
|
statusSkill,
|
|
1500
1728
|
fromUrlSkill,
|
|
1501
1729
|
uploadSkill,
|
|
1730
|
+
adSkill,
|
|
1502
1731
|
campaignSkill,
|
|
1503
1732
|
campaignStatusSkill
|
|
1504
1733
|
];
|
|
@@ -1555,7 +1784,7 @@ function makeRedactedLogger(target = console) {
|
|
|
1555
1784
|
}
|
|
1556
1785
|
|
|
1557
1786
|
// src/server.ts
|
|
1558
|
-
var PACKAGE_VERSION = "0.
|
|
1787
|
+
var PACKAGE_VERSION = "0.8.0" ;
|
|
1559
1788
|
function buildServer(options) {
|
|
1560
1789
|
if (!options.apiKey) {
|
|
1561
1790
|
throw new Error(
|