@pixeldojo/mcp 0.5.1 → 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 +356 -66
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +356 -66
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +356 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +356 -66
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -181,6 +181,85 @@ var init_upload_helpers = __esm({
|
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
183
|
});
|
|
184
|
+
|
|
185
|
+
// src/skills/schema-snap.ts
|
|
186
|
+
function getFieldConstraints(apiId, client) {
|
|
187
|
+
const cached = schemaCache.get(apiId);
|
|
188
|
+
if (cached) return cached;
|
|
189
|
+
const pending = client.getModelSchema(apiId).then(
|
|
190
|
+
(res) => res.schema?.properties ?? {}
|
|
191
|
+
).catch(() => {
|
|
192
|
+
schemaCache.delete(apiId);
|
|
193
|
+
return null;
|
|
194
|
+
});
|
|
195
|
+
schemaCache.set(apiId, pending);
|
|
196
|
+
return pending;
|
|
197
|
+
}
|
|
198
|
+
function parseAspectRatio(ar) {
|
|
199
|
+
const m = /^\s*(\d+)\s*:\s*(\d+)\s*$/.exec(ar);
|
|
200
|
+
if (!m) return null;
|
|
201
|
+
const w = Number(m[1]);
|
|
202
|
+
const h = Number(m[2]);
|
|
203
|
+
return h > 0 ? w / h : null;
|
|
204
|
+
}
|
|
205
|
+
function nearestAspectFromEnum(requested, allowed) {
|
|
206
|
+
if (allowed.includes(requested)) return requested;
|
|
207
|
+
const target = parseAspectRatio(requested);
|
|
208
|
+
if (target === null) return requested;
|
|
209
|
+
let best = requested;
|
|
210
|
+
let bestDiff = Infinity;
|
|
211
|
+
for (const candidate of allowed) {
|
|
212
|
+
const r = parseAspectRatio(candidate);
|
|
213
|
+
if (r === null) continue;
|
|
214
|
+
const diff = Math.abs(r - target);
|
|
215
|
+
if (diff < bestDiff) {
|
|
216
|
+
bestDiff = diff;
|
|
217
|
+
best = candidate;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return best;
|
|
221
|
+
}
|
|
222
|
+
async function snapAspectRatio(apiId, requested, client, opts = {}) {
|
|
223
|
+
if (!requested) return void 0;
|
|
224
|
+
const props = await getFieldConstraints(apiId, client);
|
|
225
|
+
if (props === null) {
|
|
226
|
+
return opts.onUnknown === "omit" ? void 0 : requested;
|
|
227
|
+
}
|
|
228
|
+
const field = props.aspect_ratio;
|
|
229
|
+
if (!field) return void 0;
|
|
230
|
+
if (!field.enum || field.enum.length === 0) return requested;
|
|
231
|
+
return nearestAspectFromEnum(requested, field.enum);
|
|
232
|
+
}
|
|
233
|
+
async function snapDuration(apiId, requested, client, opts = {}) {
|
|
234
|
+
if (requested === void 0) return void 0;
|
|
235
|
+
const props = await getFieldConstraints(apiId, client);
|
|
236
|
+
if (props === null) {
|
|
237
|
+
return opts.onUnknown === "omit" ? void 0 : requested;
|
|
238
|
+
}
|
|
239
|
+
const field = props.duration;
|
|
240
|
+
if (!field) return void 0;
|
|
241
|
+
if (field.enum && field.enum.length > 0) {
|
|
242
|
+
const allowed = field.enum.map(Number).filter((n) => Number.isFinite(n));
|
|
243
|
+
if (allowed.length === 0) return requested;
|
|
244
|
+
if (allowed.includes(requested)) return requested;
|
|
245
|
+
return allowed.reduce(
|
|
246
|
+
(best, candidate) => Math.abs(candidate - requested) < Math.abs(best - requested) ? candidate : best
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
if (typeof field.minimum === "number" || typeof field.maximum === "number") {
|
|
250
|
+
let v = requested;
|
|
251
|
+
if (typeof field.minimum === "number") v = Math.max(field.minimum, v);
|
|
252
|
+
if (typeof field.maximum === "number") v = Math.min(field.maximum, v);
|
|
253
|
+
return v;
|
|
254
|
+
}
|
|
255
|
+
return requested;
|
|
256
|
+
}
|
|
257
|
+
var schemaCache;
|
|
258
|
+
var init_schema_snap = __esm({
|
|
259
|
+
"src/skills/schema-snap.ts"() {
|
|
260
|
+
schemaCache = /* @__PURE__ */ new Map();
|
|
261
|
+
}
|
|
262
|
+
});
|
|
184
263
|
function buildPayload(apiId, input) {
|
|
185
264
|
const body = { prompt: input.prompt };
|
|
186
265
|
if (input.aspect_ratio) body.aspect_ratio = input.aspect_ratio;
|
|
@@ -233,6 +312,13 @@ async function run(input, ctx) {
|
|
|
233
312
|
};
|
|
234
313
|
}
|
|
235
314
|
}
|
|
315
|
+
if (!VIDEO_INPUT_MODELS.has(apiId)) {
|
|
316
|
+
const [aspect_ratio, duration] = await Promise.all([
|
|
317
|
+
snapAspectRatio(apiId, resolved.aspect_ratio, ctx.client),
|
|
318
|
+
snapDuration(apiId, resolved.duration, ctx.client)
|
|
319
|
+
]);
|
|
320
|
+
resolved = { ...resolved, aspect_ratio, duration };
|
|
321
|
+
}
|
|
236
322
|
const body = buildPayload(apiId, resolved);
|
|
237
323
|
const submitted = await ctx.client.run(apiId, body);
|
|
238
324
|
const result = await pollJobUntilDoneOrHandoff(
|
|
@@ -249,16 +335,17 @@ async function run(input, ctx) {
|
|
|
249
335
|
(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(", ")}`
|
|
250
336
|
);
|
|
251
337
|
}
|
|
252
|
-
var InputSchema, DEFAULT_MODEL, InputJsonSchema, generateSkill;
|
|
338
|
+
var InputSchema, DEFAULT_MODEL, VIDEO_INPUT_MODELS, InputJsonSchema, generateSkill;
|
|
253
339
|
var init_generate = __esm({
|
|
254
340
|
"src/skills/generate.ts"() {
|
|
255
341
|
init_poll();
|
|
256
342
|
init_types();
|
|
257
343
|
init_upload_helpers();
|
|
344
|
+
init_schema_snap();
|
|
258
345
|
InputSchema = z.object({
|
|
259
346
|
prompt: z.string().min(1).max(8e3).describe("Prompt describing what to generate."),
|
|
260
347
|
model: z.string().optional().describe(
|
|
261
|
-
'Override the model. Any apiId from /api/v1/models (e.g. "flux", "google-nano-banana", "veo-3.1", "kling-video"). Omit to use the default.'
|
|
348
|
+
'Override the model. Any apiId from /api/v1/models (e.g. "flux", "google-nano-banana", "veo-3.1-fast", "kling-video-v3-standard-text"). Omit to use the default.'
|
|
262
349
|
),
|
|
263
350
|
preset: z.string().optional().describe(
|
|
264
351
|
'Preset slug to seed the params (e.g. "cinematic-portrait", "product-floating-clean", "magazine-cover-text"). Browse the catalog at https://pixeldojo.ai/presets. Explicit fields override preset values.'
|
|
@@ -271,13 +358,14 @@ var init_generate = __esm({
|
|
|
271
358
|
)
|
|
272
359
|
});
|
|
273
360
|
DEFAULT_MODEL = "google-nano-banana";
|
|
361
|
+
VIDEO_INPUT_MODELS = /* @__PURE__ */ new Set(["grok-video-extend", "wan-video-edit", "seedance-video-edit"]);
|
|
274
362
|
InputJsonSchema = {
|
|
275
363
|
type: "object",
|
|
276
364
|
properties: {
|
|
277
365
|
prompt: { type: "string", description: "Prompt describing what to generate." },
|
|
278
366
|
model: {
|
|
279
367
|
type: "string",
|
|
280
|
-
description: 'Override the model. Any apiId from /api/v1/models (e.g. "flux", "google-nano-banana", "veo-3.1", "kling-video"). Omit to use the default.'
|
|
368
|
+
description: 'Override the model. Any apiId from /api/v1/models (e.g. "flux", "google-nano-banana", "veo-3.1-fast", "kling-video-v3-standard-text"). Omit to use the default.'
|
|
281
369
|
},
|
|
282
370
|
preset: {
|
|
283
371
|
type: "string",
|
|
@@ -368,6 +456,10 @@ async function run2(input, ctx) {
|
|
|
368
456
|
};
|
|
369
457
|
}
|
|
370
458
|
const apiId = resolved.model ?? DEFAULT_MODEL2;
|
|
459
|
+
resolved = {
|
|
460
|
+
...resolved,
|
|
461
|
+
aspect_ratio: await snapAspectRatio(apiId, resolved.aspect_ratio, ctx.client)
|
|
462
|
+
};
|
|
371
463
|
const body = buildPayload2(apiId, resolved);
|
|
372
464
|
const submitted = await ctx.client.run(apiId, body);
|
|
373
465
|
const result = await pollJobUntilDoneOrHandoff(
|
|
@@ -390,6 +482,7 @@ var init_edit = __esm({
|
|
|
390
482
|
init_poll();
|
|
391
483
|
init_types();
|
|
392
484
|
init_upload_helpers();
|
|
485
|
+
init_schema_snap();
|
|
393
486
|
DEFAULT_MODEL2 = "wan-2.7-image-edit";
|
|
394
487
|
ALLOWED_MODELS = [
|
|
395
488
|
"wan-2.7-image-edit",
|
|
@@ -471,18 +564,24 @@ async function run3(input, ctx) {
|
|
|
471
564
|
};
|
|
472
565
|
}
|
|
473
566
|
const apiId = requested;
|
|
474
|
-
if ((apiId
|
|
567
|
+
if (REQUIRES_REFERENCE.has(apiId) && !input.reference_image_url) {
|
|
475
568
|
return {
|
|
476
569
|
kind: "text",
|
|
477
|
-
text: `pixeldojo:character with model="${apiId}" requires reference_image_url (the source image of the character to edit). For generation from a prompt alone, use model="
|
|
570
|
+
text: `pixeldojo:character with model="${apiId}" requires reference_image_url (the source image of the character to edit). For generation from a prompt alone, use model="${DEFAULT_MODEL3}".`
|
|
478
571
|
};
|
|
479
572
|
}
|
|
480
573
|
const body = { prompt: input.prompt };
|
|
481
|
-
if (input.aspect_ratio) body.aspect_ratio = input.aspect_ratio;
|
|
482
574
|
if (input.reference_image_url) {
|
|
483
|
-
|
|
484
|
-
|
|
575
|
+
if (apiId === "flux-edit") {
|
|
576
|
+
body.input_image = input.reference_image_url;
|
|
577
|
+
} else {
|
|
578
|
+
body.image_urls = [input.reference_image_url];
|
|
579
|
+
}
|
|
485
580
|
}
|
|
581
|
+
const snappedAspect = await snapAspectRatio(apiId, input.aspect_ratio, ctx.client, {
|
|
582
|
+
onUnknown: "omit"
|
|
583
|
+
});
|
|
584
|
+
if (snappedAspect !== void 0) body.aspect_ratio = snappedAspect;
|
|
486
585
|
const submitted = await ctx.client.run(apiId, body);
|
|
487
586
|
const result = await pollJobUntilDoneOrHandoff(
|
|
488
587
|
submitted.jobId,
|
|
@@ -498,20 +597,22 @@ async function run3(input, ctx) {
|
|
|
498
597
|
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Character shot ready. Asset: ${urls[0]}`
|
|
499
598
|
);
|
|
500
599
|
}
|
|
501
|
-
var ALLOWED, DEFAULT_MODEL3, InputSchema3, InputJsonSchema3, characterSkill;
|
|
600
|
+
var ALLOWED, DEFAULT_MODEL3, REQUIRES_REFERENCE, InputSchema3, InputJsonSchema3, characterSkill;
|
|
502
601
|
var init_character = __esm({
|
|
503
602
|
"src/skills/character.ts"() {
|
|
504
603
|
init_poll();
|
|
505
604
|
init_types();
|
|
506
|
-
|
|
507
|
-
|
|
605
|
+
init_schema_snap();
|
|
606
|
+
ALLOWED = ["seedream-5", "seedream-4", "flux-edit", "gpt-image-2-edit"];
|
|
607
|
+
DEFAULT_MODEL3 = "seedream-5";
|
|
608
|
+
REQUIRES_REFERENCE = /* @__PURE__ */ new Set(["flux-edit", "gpt-image-2-edit"]);
|
|
508
609
|
InputSchema3 = z.object({
|
|
509
610
|
prompt: z.string().min(1).max(8e3),
|
|
510
611
|
model: z.string().optional().describe(`One of: ${ALLOWED.join(", ")}. Defaults to ${DEFAULT_MODEL3}.`),
|
|
511
612
|
reference_image_url: z.string().url().optional().describe(
|
|
512
|
-
"Reference image of the character. Required by flux-edit and gpt-image-2-edit; optional for
|
|
613
|
+
"Reference image of the character. Required by flux-edit and gpt-image-2-edit; optional for seedream-5/seedream-4."
|
|
513
614
|
),
|
|
514
|
-
aspect_ratio: z.string().optional()
|
|
615
|
+
aspect_ratio: z.string().optional().describe('Only honored for model="flux-edit".')
|
|
515
616
|
});
|
|
516
617
|
InputJsonSchema3 = {
|
|
517
618
|
type: "object",
|
|
@@ -529,7 +630,7 @@ var init_character = __esm({
|
|
|
529
630
|
};
|
|
530
631
|
characterSkill = {
|
|
531
632
|
name: "pixeldojo:character",
|
|
532
|
-
description: "Generate or edit consistent characters across shots. Pass a reference_image_url for
|
|
633
|
+
description: "Generate or edit consistent characters across shots. Pass a reference_image_url for identity locking (seedream-5 by default).",
|
|
533
634
|
inputZod: InputSchema3,
|
|
534
635
|
inputJsonSchema: InputJsonSchema3,
|
|
535
636
|
allowedModels: [...ALLOWED],
|
|
@@ -547,9 +648,13 @@ async function run4(input, ctx) {
|
|
|
547
648
|
};
|
|
548
649
|
}
|
|
549
650
|
const apiId = requested;
|
|
651
|
+
const [snappedAspect, snappedDuration] = await Promise.all([
|
|
652
|
+
snapAspectRatio(apiId, input.aspect_ratio, ctx.client),
|
|
653
|
+
snapDuration(apiId, input.duration, ctx.client)
|
|
654
|
+
]);
|
|
550
655
|
const body = { prompt: input.brief };
|
|
551
|
-
if (
|
|
552
|
-
if (
|
|
656
|
+
if (snappedAspect !== void 0) body.aspect_ratio = snappedAspect;
|
|
657
|
+
if (snappedDuration !== void 0) body.duration = snappedDuration;
|
|
553
658
|
const submitted = await ctx.client.run(apiId, body);
|
|
554
659
|
const result = await pollJobUntilDoneOrHandoff(
|
|
555
660
|
submitted.jobId,
|
|
@@ -570,8 +675,14 @@ var init_storyboard = __esm({
|
|
|
570
675
|
"src/skills/storyboard.ts"() {
|
|
571
676
|
init_poll();
|
|
572
677
|
init_types();
|
|
573
|
-
|
|
574
|
-
|
|
678
|
+
init_schema_snap();
|
|
679
|
+
ALLOWED2 = [
|
|
680
|
+
"veo-3.1-fast",
|
|
681
|
+
"veo-3.1-standard",
|
|
682
|
+
"kling-video-v3-standard-text",
|
|
683
|
+
"seedance-2-high"
|
|
684
|
+
];
|
|
685
|
+
DEFAULT_MODEL4 = "veo-3.1-fast";
|
|
575
686
|
InputSchema4 = z.object({
|
|
576
687
|
brief: z.string().min(1).max(8e3).describe("Storyboard brief: scene, shots, mood, action."),
|
|
577
688
|
model: z.string().optional().describe(`One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}.`),
|
|
@@ -617,11 +728,20 @@ async function run5(input, ctx) {
|
|
|
617
728
|
const apiId = requested;
|
|
618
729
|
const body = {
|
|
619
730
|
prompt: "",
|
|
620
|
-
|
|
731
|
+
image: input.image_url
|
|
621
732
|
};
|
|
622
733
|
if (apiId === "magnific-upscaler") {
|
|
623
|
-
|
|
734
|
+
const allowed = [2, 4, 8, 16];
|
|
735
|
+
const requestedScale = input.scale_factor ?? 2;
|
|
736
|
+
const nearest = allowed.reduce(
|
|
737
|
+
(a, b) => Math.abs(b - requestedScale) < Math.abs(a - requestedScale) ? b : a
|
|
738
|
+
);
|
|
739
|
+
body.scale_factor = `${nearest}x`;
|
|
624
740
|
if (input.creativity !== void 0) body.creativity = input.creativity;
|
|
741
|
+
} else if (apiId === "creative-upscale") {
|
|
742
|
+
body.scale_factor = Math.min(10, Math.max(1, input.scale_factor ?? 2));
|
|
743
|
+
} else if (apiId === "face-enhance") {
|
|
744
|
+
body.scale_factor = Math.min(8, Math.max(1, input.scale_factor ?? 4));
|
|
625
745
|
}
|
|
626
746
|
const submitted = await ctx.client.run(apiId, body);
|
|
627
747
|
const result = await pollJobUntilDoneOrHandoff(
|
|
@@ -648,7 +768,9 @@ var init_upscale = __esm({
|
|
|
648
768
|
InputSchema5 = z.object({
|
|
649
769
|
image_url: z.string().url().describe("URL of the source image to upscale."),
|
|
650
770
|
model: z.string().optional().describe(`One of: ${ALLOWED3.join(", ")}. Defaults to ${DEFAULT_MODEL5}.`),
|
|
651
|
-
scale_factor: z.number().
|
|
771
|
+
scale_factor: z.number().min(1).max(16).optional().describe(
|
|
772
|
+
"Upscale multiplier. Magnific snaps to the nearest of 2/4/8/16 (default 2); creative-upscale accepts 1-10 (default 2); face-enhance accepts 1-8 (default 4)."
|
|
773
|
+
),
|
|
652
774
|
creativity: z.number().min(0).max(1).optional().describe("Magnific only: 0 (preserve) \u2192 1 (creative). Defaults to 0.")
|
|
653
775
|
});
|
|
654
776
|
InputJsonSchema5 = {
|
|
@@ -656,7 +778,7 @@ var init_upscale = __esm({
|
|
|
656
778
|
properties: {
|
|
657
779
|
image_url: { type: "string", format: "uri" },
|
|
658
780
|
model: { type: "string", enum: ALLOWED3 },
|
|
659
|
-
scale_factor: { type: "
|
|
781
|
+
scale_factor: { type: "number", minimum: 1, maximum: 16 },
|
|
660
782
|
creativity: { type: "number", minimum: 0, maximum: 1 }
|
|
661
783
|
},
|
|
662
784
|
required: ["image_url"]
|
|
@@ -812,6 +934,146 @@ var init_from_url = __esm({
|
|
|
812
934
|
}
|
|
813
935
|
});
|
|
814
936
|
async function run8(input, ctx) {
|
|
937
|
+
const productImages = [
|
|
938
|
+
...input.product_image_urls ?? [],
|
|
939
|
+
...await Promise.all((input.product_image_paths ?? []).map((p) => uploadLocalFile(p, ctx.client)))
|
|
940
|
+
];
|
|
941
|
+
const characterImages = [
|
|
942
|
+
...input.character_image_urls ?? [],
|
|
943
|
+
...await Promise.all((input.character_image_paths ?? []).map((p) => uploadLocalFile(p, ctx.client)))
|
|
944
|
+
];
|
|
945
|
+
const body = {
|
|
946
|
+
style: input.style,
|
|
947
|
+
product_url: input.product_url,
|
|
948
|
+
product: !input.product_url && input.product_name ? {
|
|
949
|
+
name: input.product_name,
|
|
950
|
+
description: input.product_description,
|
|
951
|
+
images: productImages
|
|
952
|
+
} : void 0,
|
|
953
|
+
character_images: characterImages.length > 0 ? characterImages : void 0,
|
|
954
|
+
location: input.location_description || input.location_image_url ? { description: input.location_description, image_url: input.location_image_url } : void 0,
|
|
955
|
+
hook: input.hook,
|
|
956
|
+
script: input.script,
|
|
957
|
+
quality: input.quality,
|
|
958
|
+
resolution: input.resolution,
|
|
959
|
+
aspect_ratio: input.aspect_ratio,
|
|
960
|
+
duration: input.duration
|
|
961
|
+
};
|
|
962
|
+
const client = ctx.client;
|
|
963
|
+
const submitted = await client.runAd(body);
|
|
964
|
+
const result = await pollJobUntilDoneOrHandoff(
|
|
965
|
+
submitted.jobId,
|
|
966
|
+
(id) => ctx.client.getJob(id),
|
|
967
|
+
ctx.buildStatusUrl,
|
|
968
|
+
{
|
|
969
|
+
now: ctx.pollOverrides?.now,
|
|
970
|
+
sleep: ctx.pollOverrides?.sleep
|
|
971
|
+
}
|
|
972
|
+
);
|
|
973
|
+
const styleLabel = submitted.ad?.style ?? input.style ?? "ugc-testimonial";
|
|
974
|
+
return pollResultToSkillResult(
|
|
975
|
+
result,
|
|
976
|
+
(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]}`
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
var InputSchema8, InputJsonSchema8, adSkill;
|
|
980
|
+
var init_ad = __esm({
|
|
981
|
+
"src/skills/ad.ts"() {
|
|
982
|
+
init_types();
|
|
983
|
+
init_poll();
|
|
984
|
+
init_upload_helpers();
|
|
985
|
+
InputSchema8 = z.object({
|
|
986
|
+
style: z.string().max(80).optional().describe(
|
|
987
|
+
"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."
|
|
988
|
+
),
|
|
989
|
+
product_url: z.string().url().optional().describe("Product page URL. Name, description, and images are extracted automatically."),
|
|
990
|
+
product_name: z.string().max(200).optional(),
|
|
991
|
+
product_description: z.string().max(2e3).optional(),
|
|
992
|
+
product_image_urls: z.array(z.string().url()).max(5).optional(),
|
|
993
|
+
product_image_paths: z.array(z.string()).max(5).optional().describe("Absolute local paths; uploaded to 24h temp storage automatically."),
|
|
994
|
+
character_image_urls: z.array(z.string().url()).max(4).optional().describe("Presenter reference images for a consistent on-camera character."),
|
|
995
|
+
character_image_paths: z.array(z.string()).max(4).optional(),
|
|
996
|
+
location_description: z.string().max(1500).optional().describe('Where the ad takes place ("a sunlit Parisian cafe"). Text is enough; no image needed.'),
|
|
997
|
+
location_image_url: z.string().url().optional(),
|
|
998
|
+
hook: z.string().max(1e3).optional().describe("The opening visual beat (first 1-2 seconds). Omit to use the style default."),
|
|
999
|
+
script: z.string().max(1e3).optional().describe("The exact spoken line, voiced word for word. Omit and the presenter improvises."),
|
|
1000
|
+
quality: z.enum(["mini", "fast", "high"]).optional(),
|
|
1001
|
+
resolution: z.enum(["480p", "720p", "1080p", "4k"]).optional().describe('1080p/4k require quality "high".'),
|
|
1002
|
+
aspect_ratio: z.enum(["16:9", "4:3", "1:1", "3:4", "9:16", "21:9"]).optional(),
|
|
1003
|
+
duration: z.number().int().min(4).max(15).optional()
|
|
1004
|
+
}).refine(
|
|
1005
|
+
(v) => v.product_url || (v.product_image_urls?.length || v.product_image_paths?.length) && v.product_name,
|
|
1006
|
+
{
|
|
1007
|
+
message: "Pass product_url, OR product_name plus product_image_urls/product_image_paths.",
|
|
1008
|
+
path: ["product_url"]
|
|
1009
|
+
}
|
|
1010
|
+
);
|
|
1011
|
+
InputJsonSchema8 = {
|
|
1012
|
+
type: "object",
|
|
1013
|
+
properties: {
|
|
1014
|
+
style: {
|
|
1015
|
+
type: "string",
|
|
1016
|
+
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."
|
|
1017
|
+
},
|
|
1018
|
+
product_url: {
|
|
1019
|
+
type: "string",
|
|
1020
|
+
format: "uri",
|
|
1021
|
+
description: "Product page URL. Name, description, and images are extracted automatically."
|
|
1022
|
+
},
|
|
1023
|
+
product_name: { type: "string" },
|
|
1024
|
+
product_description: { type: "string" },
|
|
1025
|
+
product_image_urls: { type: "array", items: { type: "string", format: "uri" }, maxItems: 5 },
|
|
1026
|
+
product_image_paths: {
|
|
1027
|
+
type: "array",
|
|
1028
|
+
items: { type: "string" },
|
|
1029
|
+
maxItems: 5,
|
|
1030
|
+
description: "Absolute local file paths; uploaded to 24h temp storage automatically."
|
|
1031
|
+
},
|
|
1032
|
+
character_image_urls: {
|
|
1033
|
+
type: "array",
|
|
1034
|
+
items: { type: "string", format: "uri" },
|
|
1035
|
+
maxItems: 4,
|
|
1036
|
+
description: "Presenter reference images for a consistent on-camera character."
|
|
1037
|
+
},
|
|
1038
|
+
character_image_paths: { type: "array", items: { type: "string" }, maxItems: 4 },
|
|
1039
|
+
location_description: {
|
|
1040
|
+
type: "string",
|
|
1041
|
+
description: 'Where the ad takes place ("a sunlit Parisian cafe"). Text is enough.'
|
|
1042
|
+
},
|
|
1043
|
+
location_image_url: { type: "string", format: "uri" },
|
|
1044
|
+
hook: {
|
|
1045
|
+
type: "string",
|
|
1046
|
+
description: "The opening visual beat (first 1-2 seconds). Omit to use the style default."
|
|
1047
|
+
},
|
|
1048
|
+
script: {
|
|
1049
|
+
type: "string",
|
|
1050
|
+
description: "The exact spoken line, voiced word for word. Omit and the presenter improvises."
|
|
1051
|
+
},
|
|
1052
|
+
quality: { type: "string", enum: ["mini", "fast", "high"] },
|
|
1053
|
+
resolution: {
|
|
1054
|
+
type: "string",
|
|
1055
|
+
enum: ["480p", "720p", "1080p", "4k"],
|
|
1056
|
+
description: '1080p/4k require quality "high".'
|
|
1057
|
+
},
|
|
1058
|
+
aspect_ratio: { type: "string", enum: ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9"] },
|
|
1059
|
+
duration: { type: "integer", minimum: 4, maximum: 15 }
|
|
1060
|
+
}
|
|
1061
|
+
// "product_url OR product_name+images" is enforced by the server and the
|
|
1062
|
+
// Zod refine; no root-level oneOf (Grok rejects non-object root unions).
|
|
1063
|
+
};
|
|
1064
|
+
adSkill = {
|
|
1065
|
+
name: "pixeldojo:ad",
|
|
1066
|
+
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.",
|
|
1067
|
+
inputZod: InputSchema8,
|
|
1068
|
+
inputJsonSchema: InputJsonSchema8,
|
|
1069
|
+
// Composition skill — the server routes to the ad engine internally.
|
|
1070
|
+
allowedModels: [],
|
|
1071
|
+
defaultModel: "",
|
|
1072
|
+
run: run8
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
async function run9(input, ctx) {
|
|
815
1077
|
const client = ctx.client;
|
|
816
1078
|
const result = await client.runCampaign(input);
|
|
817
1079
|
if (result.kind === "campaign") {
|
|
@@ -838,10 +1100,10 @@ async function run8(input, ctx) {
|
|
|
838
1100
|
statusUrl: result.statusUrl ?? ctx.buildStatusUrl(result.campaignId)
|
|
839
1101
|
};
|
|
840
1102
|
}
|
|
841
|
-
var
|
|
1103
|
+
var InputSchema9, InputJsonSchema9, campaignSkill;
|
|
842
1104
|
var init_campaign = __esm({
|
|
843
1105
|
"src/skills/campaign.ts"() {
|
|
844
|
-
|
|
1106
|
+
InputSchema9 = z.object({
|
|
845
1107
|
productUrl: z.string().url().optional().describe("Product page URL. We extract name + description + images automatically."),
|
|
846
1108
|
product: z.object({
|
|
847
1109
|
name: z.string().min(1).max(200),
|
|
@@ -857,7 +1119,7 @@ var init_campaign = __esm({
|
|
|
857
1119
|
message: "productUrl or product is required",
|
|
858
1120
|
path: ["productUrl"]
|
|
859
1121
|
});
|
|
860
|
-
|
|
1122
|
+
InputJsonSchema9 = {
|
|
861
1123
|
type: "object",
|
|
862
1124
|
properties: {
|
|
863
1125
|
productUrl: {
|
|
@@ -888,17 +1150,17 @@ var init_campaign = __esm({
|
|
|
888
1150
|
campaignSkill = {
|
|
889
1151
|
name: "pixeldojo:campaign",
|
|
890
1152
|
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.",
|
|
891
|
-
inputZod:
|
|
892
|
-
inputJsonSchema:
|
|
1153
|
+
inputZod: InputSchema9,
|
|
1154
|
+
inputJsonSchema: InputJsonSchema9,
|
|
893
1155
|
// Composition skill — internal sub-jobs route to per-tool models, no
|
|
894
1156
|
// single allowed-models list applies here.
|
|
895
1157
|
allowedModels: [],
|
|
896
1158
|
defaultModel: "",
|
|
897
|
-
run:
|
|
1159
|
+
run: run9
|
|
898
1160
|
};
|
|
899
1161
|
}
|
|
900
1162
|
});
|
|
901
|
-
async function
|
|
1163
|
+
async function run10(input, ctx) {
|
|
902
1164
|
const client = ctx.client;
|
|
903
1165
|
const result = await client.getCampaign(input.campaignId);
|
|
904
1166
|
if (result.kind === "campaign") {
|
|
@@ -928,13 +1190,13 @@ async function run9(input, ctx) {
|
|
|
928
1190
|
statusUrl: result.statusUrl ?? ctx.buildStatusUrl(result.campaignId)
|
|
929
1191
|
};
|
|
930
1192
|
}
|
|
931
|
-
var
|
|
1193
|
+
var InputSchema10, InputJsonSchema10, campaignStatusSkill;
|
|
932
1194
|
var init_campaign_status = __esm({
|
|
933
1195
|
"src/skills/campaign-status.ts"() {
|
|
934
|
-
|
|
1196
|
+
InputSchema10 = z.object({
|
|
935
1197
|
campaignId: z.string().min(1).max(200).describe("Campaign id returned from a prior pixeldojo:campaign handoff.")
|
|
936
1198
|
});
|
|
937
|
-
|
|
1199
|
+
InputJsonSchema10 = {
|
|
938
1200
|
type: "object",
|
|
939
1201
|
properties: {
|
|
940
1202
|
campaignId: {
|
|
@@ -947,15 +1209,15 @@ var init_campaign_status = __esm({
|
|
|
947
1209
|
campaignStatusSkill = {
|
|
948
1210
|
name: "pixeldojo:campaign_status",
|
|
949
1211
|
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.",
|
|
950
|
-
inputZod:
|
|
951
|
-
inputJsonSchema:
|
|
1212
|
+
inputZod: InputSchema10,
|
|
1213
|
+
inputJsonSchema: InputJsonSchema10,
|
|
952
1214
|
allowedModels: [],
|
|
953
1215
|
defaultModel: "",
|
|
954
|
-
run:
|
|
1216
|
+
run: run10
|
|
955
1217
|
};
|
|
956
1218
|
}
|
|
957
1219
|
});
|
|
958
|
-
async function
|
|
1220
|
+
async function run11(input, ctx) {
|
|
959
1221
|
let url;
|
|
960
1222
|
try {
|
|
961
1223
|
url = await uploadLocalFile(input.path, ctx.client);
|
|
@@ -971,16 +1233,16 @@ async function run10(input, ctx) {
|
|
|
971
1233
|
(temp storage; auto-deletes in ~24h \u2014 pass this URL as image_url to :generate or :edit)`
|
|
972
1234
|
};
|
|
973
1235
|
}
|
|
974
|
-
var
|
|
1236
|
+
var InputSchema11, InputJsonSchema11, uploadSkill;
|
|
975
1237
|
var init_upload = __esm({
|
|
976
1238
|
"src/skills/upload.ts"() {
|
|
977
1239
|
init_upload_helpers();
|
|
978
|
-
|
|
1240
|
+
InputSchema11 = z.object({
|
|
979
1241
|
path: z.string().min(1).max(4096).describe(
|
|
980
1242
|
"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."
|
|
981
1243
|
)
|
|
982
1244
|
});
|
|
983
|
-
|
|
1245
|
+
InputJsonSchema11 = {
|
|
984
1246
|
type: "object",
|
|
985
1247
|
properties: {
|
|
986
1248
|
path: {
|
|
@@ -993,15 +1255,15 @@ var init_upload = __esm({
|
|
|
993
1255
|
uploadSkill = {
|
|
994
1256
|
name: "pixeldojo:upload",
|
|
995
1257
|
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.",
|
|
996
|
-
inputZod:
|
|
997
|
-
inputJsonSchema:
|
|
1258
|
+
inputZod: InputSchema11,
|
|
1259
|
+
inputJsonSchema: InputJsonSchema11,
|
|
998
1260
|
allowedModels: [],
|
|
999
1261
|
defaultModel: "",
|
|
1000
|
-
run:
|
|
1262
|
+
run: run11
|
|
1001
1263
|
};
|
|
1002
1264
|
}
|
|
1003
1265
|
});
|
|
1004
|
-
async function
|
|
1266
|
+
async function run12(input, ctx) {
|
|
1005
1267
|
const requested = input.model ?? DEFAULT_MODEL6;
|
|
1006
1268
|
if (!ALLOWED4.includes(requested)) {
|
|
1007
1269
|
return {
|
|
@@ -1050,7 +1312,7 @@ async function run11(input, ctx) {
|
|
|
1050
1312
|
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Audio ready. Asset: ${urls[0]}`
|
|
1051
1313
|
);
|
|
1052
1314
|
}
|
|
1053
|
-
var ALLOWED4, DEFAULT_MODEL6,
|
|
1315
|
+
var ALLOWED4, DEFAULT_MODEL6, InputSchema12, InputJsonSchema12, audioSkill;
|
|
1054
1316
|
var init_audio = __esm({
|
|
1055
1317
|
"src/skills/audio.ts"() {
|
|
1056
1318
|
init_poll();
|
|
@@ -1058,7 +1320,7 @@ var init_audio = __esm({
|
|
|
1058
1320
|
init_types();
|
|
1059
1321
|
ALLOWED4 = ["seed-audio", "text-to-speech"];
|
|
1060
1322
|
DEFAULT_MODEL6 = "seed-audio";
|
|
1061
|
-
|
|
1323
|
+
InputSchema12 = z.object({
|
|
1062
1324
|
prompt: z.string().min(1).describe(
|
|
1063
1325
|
"A script for speech, or a scene description for cinematic audio (dialogue + effects + music). Reference uploaded clips as @Audio1..@Audio3."
|
|
1064
1326
|
),
|
|
@@ -1069,7 +1331,7 @@ var init_audio = __esm({
|
|
|
1069
1331
|
output_format: z.string().optional().describe("seed-audio: mp3 (default), wav, pcm, ogg_opus. text-to-speech: mp3, wav, flac, pcm."),
|
|
1070
1332
|
speed: z.number().min(0.5).max(2).optional().describe("Speech speed multiplier (0.5\u20132).")
|
|
1071
1333
|
});
|
|
1072
|
-
|
|
1334
|
+
InputJsonSchema12 = {
|
|
1073
1335
|
type: "object",
|
|
1074
1336
|
properties: {
|
|
1075
1337
|
prompt: { type: "string" },
|
|
@@ -1085,15 +1347,15 @@ var init_audio = __esm({
|
|
|
1085
1347
|
audioSkill = {
|
|
1086
1348
|
name: "pixeldojo:audio",
|
|
1087
1349
|
description: "Generate audio: speech, multi-character dialogue, sound effects, and background music from one prompt (Seed Audio 1.0 by default; plain TTS available).",
|
|
1088
|
-
inputZod:
|
|
1089
|
-
inputJsonSchema:
|
|
1350
|
+
inputZod: InputSchema12,
|
|
1351
|
+
inputJsonSchema: InputJsonSchema12,
|
|
1090
1352
|
allowedModels: [...ALLOWED4],
|
|
1091
1353
|
defaultModel: DEFAULT_MODEL6,
|
|
1092
|
-
run:
|
|
1354
|
+
run: run12
|
|
1093
1355
|
};
|
|
1094
1356
|
}
|
|
1095
1357
|
});
|
|
1096
|
-
async function
|
|
1358
|
+
async function run13(input, ctx) {
|
|
1097
1359
|
const res = await ctx.client.listLibrary({
|
|
1098
1360
|
q: input.q,
|
|
1099
1361
|
model: input.model,
|
|
@@ -1124,16 +1386,16 @@ ${lines.join("\n")}
|
|
|
1124
1386
|
Pass any URL back into :generate, :edit, :character, or :upscale as a reference input.`
|
|
1125
1387
|
};
|
|
1126
1388
|
}
|
|
1127
|
-
var
|
|
1389
|
+
var InputSchema13, InputJsonSchema13, librarySkill;
|
|
1128
1390
|
var init_library = __esm({
|
|
1129
1391
|
"src/skills/library.ts"() {
|
|
1130
|
-
|
|
1392
|
+
InputSchema13 = z.object({
|
|
1131
1393
|
q: z.string().optional().describe("Substring match against the prompt that produced the asset."),
|
|
1132
1394
|
model: z.string().optional().describe("Restrict to a single model (apiId)."),
|
|
1133
1395
|
modality: z.enum(["image", "video", "audio"]).optional().describe("Restrict to one output type."),
|
|
1134
1396
|
limit: z.number().int().min(1).max(50).optional().describe("Max results (default 10).")
|
|
1135
1397
|
});
|
|
1136
|
-
|
|
1398
|
+
InputJsonSchema13 = {
|
|
1137
1399
|
type: "object",
|
|
1138
1400
|
properties: {
|
|
1139
1401
|
q: { type: "string" },
|
|
@@ -1146,15 +1408,15 @@ var init_library = __esm({
|
|
|
1146
1408
|
librarySkill = {
|
|
1147
1409
|
name: "pixeldojo:library",
|
|
1148
1410
|
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.",
|
|
1149
|
-
inputZod:
|
|
1150
|
-
inputJsonSchema:
|
|
1411
|
+
inputZod: InputSchema13,
|
|
1412
|
+
inputJsonSchema: InputJsonSchema13,
|
|
1151
1413
|
allowedModels: [],
|
|
1152
1414
|
defaultModel: "",
|
|
1153
|
-
run:
|
|
1415
|
+
run: run13
|
|
1154
1416
|
};
|
|
1155
1417
|
}
|
|
1156
1418
|
});
|
|
1157
|
-
async function
|
|
1419
|
+
async function run14(input, ctx) {
|
|
1158
1420
|
const res = await ctx.client.saveMedia({
|
|
1159
1421
|
url: input.url,
|
|
1160
1422
|
prompt: input.prompt,
|
|
@@ -1168,17 +1430,17 @@ async function run13(input, ctx) {
|
|
|
1168
1430
|
It will appear at https://pixeldojo.ai/my-images and in pixeldojo:library searches.`
|
|
1169
1431
|
};
|
|
1170
1432
|
}
|
|
1171
|
-
var
|
|
1433
|
+
var InputSchema14, InputJsonSchema14, saveSkill;
|
|
1172
1434
|
var init_save = __esm({
|
|
1173
1435
|
"src/skills/save.ts"() {
|
|
1174
|
-
|
|
1436
|
+
InputSchema14 = z.object({
|
|
1175
1437
|
url: z.string().url().describe("The asset URL to save (image or video)."),
|
|
1176
1438
|
prompt: z.string().optional().describe("The prompt that produced it \u2014 makes it findable in the library later."),
|
|
1177
1439
|
tool_name: z.string().optional().describe("Tool/model slug that produced it."),
|
|
1178
1440
|
modality: z.enum(["image", "video", "audio"]).optional(),
|
|
1179
1441
|
job_id: z.string().optional().describe("The jobId that produced this asset, when known.")
|
|
1180
1442
|
});
|
|
1181
|
-
|
|
1443
|
+
InputJsonSchema14 = {
|
|
1182
1444
|
type: "object",
|
|
1183
1445
|
properties: {
|
|
1184
1446
|
url: { type: "string", format: "uri" },
|
|
@@ -1192,11 +1454,11 @@ var init_save = __esm({
|
|
|
1192
1454
|
saveSkill = {
|
|
1193
1455
|
name: "pixeldojo:save",
|
|
1194
1456
|
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.",
|
|
1195
|
-
inputZod:
|
|
1196
|
-
inputJsonSchema:
|
|
1457
|
+
inputZod: InputSchema14,
|
|
1458
|
+
inputJsonSchema: InputJsonSchema14,
|
|
1197
1459
|
allowedModels: [],
|
|
1198
1460
|
defaultModel: "",
|
|
1199
|
-
run:
|
|
1461
|
+
run: run14
|
|
1200
1462
|
};
|
|
1201
1463
|
}
|
|
1202
1464
|
});
|
|
@@ -1285,7 +1547,24 @@ async function runWorkflow(input, ctx) {
|
|
|
1285
1547
|
text: `Step ${i + 1} (${step.skill}) has invalid args: ${issue?.path.join(".") || "input"} ${issue?.message || "invalid"}.`
|
|
1286
1548
|
};
|
|
1287
1549
|
}
|
|
1288
|
-
|
|
1550
|
+
let result = await skill.run(parsed.data, ctx);
|
|
1551
|
+
if (result.kind === "handoff") {
|
|
1552
|
+
const handoffJobId = result.jobId;
|
|
1553
|
+
const polled = await pollJobUntilDoneOrHandoff(
|
|
1554
|
+
handoffJobId,
|
|
1555
|
+
(id) => ctx.client.getJob(id),
|
|
1556
|
+
ctx.buildStatusUrl,
|
|
1557
|
+
{
|
|
1558
|
+
syncBudgetMs: WORKFLOW_STEP_EXTRA_BUDGET_MS,
|
|
1559
|
+
now: ctx.pollOverrides?.now,
|
|
1560
|
+
sleep: ctx.pollOverrides?.sleep
|
|
1561
|
+
}
|
|
1562
|
+
);
|
|
1563
|
+
result = pollResultToSkillResult(
|
|
1564
|
+
polled,
|
|
1565
|
+
(urls) => urls.length === 0 ? `Job ${handoffJobId} completed but returned no assets.` : `Done. Asset: ${urls[0]}`
|
|
1566
|
+
);
|
|
1567
|
+
}
|
|
1289
1568
|
const url = firstUrl(result);
|
|
1290
1569
|
if (url) {
|
|
1291
1570
|
prevUrl = url;
|
|
@@ -1295,6 +1574,11 @@ async function runWorkflow(input, ctx) {
|
|
|
1295
1574
|
kind: "text",
|
|
1296
1575
|
text: `Workflow "${workflow.name}" stopped at step ${i + 1} (${step.skill}): ${result.text}`
|
|
1297
1576
|
};
|
|
1577
|
+
} else if (result.kind === "handoff") {
|
|
1578
|
+
return {
|
|
1579
|
+
kind: "text",
|
|
1580
|
+
text: `Workflow "${workflow.name}" is still on step ${i + 1} (${step.skill}) after an extended wait. Poll with pixeldojo:status { jobId: "${result.jobId}" }, then re-run the workflow once it completes.`
|
|
1581
|
+
};
|
|
1298
1582
|
} else {
|
|
1299
1583
|
outputs.push(`step ${i + 1} (${step.skill}): done (no asset URL)`);
|
|
1300
1584
|
}
|
|
@@ -1305,9 +1589,12 @@ async function runWorkflow(input, ctx) {
|
|
|
1305
1589
|
${outputs.join("\n")}`
|
|
1306
1590
|
};
|
|
1307
1591
|
}
|
|
1308
|
-
var StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
|
|
1592
|
+
var WORKFLOW_STEP_EXTRA_BUDGET_MS, StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
|
|
1309
1593
|
var init_workflows = __esm({
|
|
1310
1594
|
"src/skills/workflows.ts"() {
|
|
1595
|
+
init_poll();
|
|
1596
|
+
init_types();
|
|
1597
|
+
WORKFLOW_STEP_EXTRA_BUDGET_MS = 6e4;
|
|
1311
1598
|
StepSchema = z.object({
|
|
1312
1599
|
skill: z.string().regex(/^pixeldojo:(generate|edit|character|storyboard|upscale|audio|upload|from_url)$/, {
|
|
1313
1600
|
message: "Runnable skills only: generate, edit, character, storyboard, upscale, audio, upload, from_url."
|
|
@@ -1383,6 +1670,7 @@ var init_workflows = __esm({
|
|
|
1383
1670
|
var skills_exports = {};
|
|
1384
1671
|
__export(skills_exports, {
|
|
1385
1672
|
ALL_SKILLS: () => ALL_SKILLS,
|
|
1673
|
+
adSkill: () => adSkill,
|
|
1386
1674
|
audioSkill: () => audioSkill,
|
|
1387
1675
|
campaignSkill: () => campaignSkill,
|
|
1388
1676
|
campaignStatusSkill: () => campaignStatusSkill,
|
|
@@ -1414,6 +1702,7 @@ var init_skills = __esm({
|
|
|
1414
1702
|
init_upscale();
|
|
1415
1703
|
init_status();
|
|
1416
1704
|
init_from_url();
|
|
1705
|
+
init_ad();
|
|
1417
1706
|
init_campaign();
|
|
1418
1707
|
init_campaign_status();
|
|
1419
1708
|
init_upload();
|
|
@@ -1436,6 +1725,7 @@ var init_skills = __esm({
|
|
|
1436
1725
|
statusSkill,
|
|
1437
1726
|
fromUrlSkill,
|
|
1438
1727
|
uploadSkill,
|
|
1728
|
+
adSkill,
|
|
1439
1729
|
campaignSkill,
|
|
1440
1730
|
campaignStatusSkill
|
|
1441
1731
|
];
|
|
@@ -1492,7 +1782,7 @@ function makeRedactedLogger(target = console) {
|
|
|
1492
1782
|
}
|
|
1493
1783
|
|
|
1494
1784
|
// src/server.ts
|
|
1495
|
-
var PACKAGE_VERSION = "0.
|
|
1785
|
+
var PACKAGE_VERSION = "0.8.0" ;
|
|
1496
1786
|
function buildServer(options) {
|
|
1497
1787
|
if (!options.apiKey) {
|
|
1498
1788
|
throw new Error(
|