@pixeldojo/mcp 0.3.0 → 0.4.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 +862 -404
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +862 -404
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +871 -408
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -66
- package/dist/index.d.ts +85 -66
- package/dist/index.js +867 -405
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,33 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var promises = require('fs/promises');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var zod = require('zod');
|
|
3
6
|
var index_js = require('@modelcontextprotocol/sdk/server/index.js');
|
|
4
7
|
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
5
8
|
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
6
9
|
var sdk = require('@pixeldojo/sdk');
|
|
7
|
-
var zod = require('zod');
|
|
8
|
-
var promises = require('fs/promises');
|
|
9
|
-
var path = require('path');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
};
|
|
21
|
-
return new sdk.PixelDojoClient({
|
|
22
|
-
...sdkOptions,
|
|
23
|
-
fetch: wrappedFetch
|
|
24
|
-
});
|
|
25
|
-
}
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __esm = (fn, res) => function __init() {
|
|
14
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
15
|
+
};
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
26
20
|
|
|
27
21
|
// src/poll.ts
|
|
28
|
-
var DEFAULT_BACKOFF = [1e3, 2e3, 4e3, 8e3];
|
|
29
|
-
var DEFAULT_MAX_INTERVAL = 8e3;
|
|
30
|
-
var DEFAULT_SYNC_BUDGET_MS = 3e4;
|
|
31
22
|
function defaultSleep(ms, signal) {
|
|
32
23
|
return new Promise((resolve, reject) => {
|
|
33
24
|
if (signal?.aborted) {
|
|
@@ -76,6 +67,14 @@ async function pollJobUntilDoneOrHandoff(jobId, fetchJob, buildStatusUrl, option
|
|
|
76
67
|
attempt++;
|
|
77
68
|
}
|
|
78
69
|
}
|
|
70
|
+
var DEFAULT_BACKOFF, DEFAULT_MAX_INTERVAL, DEFAULT_SYNC_BUDGET_MS;
|
|
71
|
+
var init_poll = __esm({
|
|
72
|
+
"src/poll.ts"() {
|
|
73
|
+
DEFAULT_BACKOFF = [1e3, 2e3, 4e3, 8e3];
|
|
74
|
+
DEFAULT_MAX_INTERVAL = 8e3;
|
|
75
|
+
DEFAULT_SYNC_BUDGET_MS = 3e4;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
79
78
|
|
|
80
79
|
// src/skills/types.ts
|
|
81
80
|
function pollResultToSkillResult(result, successText) {
|
|
@@ -110,26 +109,10 @@ function extractAssetUrls(job) {
|
|
|
110
109
|
if (output?.video) return [output.video];
|
|
111
110
|
return [];
|
|
112
111
|
}
|
|
113
|
-
var
|
|
114
|
-
|
|
115
|
-
var EXT_TO_MIME = {
|
|
116
|
-
".jpg": "image/jpeg",
|
|
117
|
-
".jpeg": "image/jpeg",
|
|
118
|
-
".png": "image/png",
|
|
119
|
-
".webp": "image/webp",
|
|
120
|
-
".gif": "image/gif",
|
|
121
|
-
".mp4": "video/mp4",
|
|
122
|
-
".webm": "video/webm",
|
|
123
|
-
".mov": "video/quicktime"
|
|
124
|
-
};
|
|
125
|
-
var SkillUploadError = class extends Error {
|
|
126
|
-
constructor(userMessage) {
|
|
127
|
-
super(userMessage);
|
|
128
|
-
this.userMessage = userMessage;
|
|
129
|
-
this.name = "SkillUploadError";
|
|
112
|
+
var init_types = __esm({
|
|
113
|
+
"src/skills/types.ts"() {
|
|
130
114
|
}
|
|
131
|
-
|
|
132
|
-
};
|
|
115
|
+
});
|
|
133
116
|
async function uploadLocalFile(path$1, client) {
|
|
134
117
|
const ext = path.extname(path$1).toLowerCase();
|
|
135
118
|
const mime = EXT_TO_MIME[ext];
|
|
@@ -175,46 +158,31 @@ async function uploadLocalFile(path$1, client) {
|
|
|
175
158
|
async function uploadLocalFiles(paths, client) {
|
|
176
159
|
return Promise.all(paths.map((p) => uploadLocalFile(p, client)));
|
|
177
160
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
161
|
+
var MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, EXT_TO_MIME, SkillUploadError;
|
|
162
|
+
var init_upload_helpers = __esm({
|
|
163
|
+
"src/skills/upload-helpers.ts"() {
|
|
164
|
+
MAX_IMAGE_BYTES = 50 * 1024 * 1024;
|
|
165
|
+
MAX_VIDEO_BYTES = 200 * 1024 * 1024;
|
|
166
|
+
EXT_TO_MIME = {
|
|
167
|
+
".jpg": "image/jpeg",
|
|
168
|
+
".jpeg": "image/jpeg",
|
|
169
|
+
".png": "image/png",
|
|
170
|
+
".webp": "image/webp",
|
|
171
|
+
".gif": "image/gif",
|
|
172
|
+
".mp4": "video/mp4",
|
|
173
|
+
".webm": "video/webm",
|
|
174
|
+
".mov": "video/quicktime"
|
|
175
|
+
};
|
|
176
|
+
SkillUploadError = class extends Error {
|
|
177
|
+
constructor(userMessage) {
|
|
178
|
+
super(userMessage);
|
|
179
|
+
this.userMessage = userMessage;
|
|
180
|
+
this.name = "SkillUploadError";
|
|
181
|
+
}
|
|
182
|
+
userMessage;
|
|
183
|
+
};
|
|
184
|
+
}
|
|
194
185
|
});
|
|
195
|
-
var DEFAULT_MODEL = "google-nano-banana";
|
|
196
|
-
var InputJsonSchema = {
|
|
197
|
-
type: "object",
|
|
198
|
-
properties: {
|
|
199
|
-
prompt: { type: "string", description: "Prompt describing what to generate." },
|
|
200
|
-
model: {
|
|
201
|
-
type: "string",
|
|
202
|
-
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.'
|
|
203
|
-
},
|
|
204
|
-
preset: {
|
|
205
|
-
type: "string",
|
|
206
|
-
description: 'Preset slug to seed the params (e.g. "cinematic-portrait", "product-floating-clean"). Explicit fields override preset values.'
|
|
207
|
-
},
|
|
208
|
-
aspect_ratio: { type: "string" },
|
|
209
|
-
duration: { type: "integer" },
|
|
210
|
-
image_url: { type: "string", format: "uri" },
|
|
211
|
-
image_path: {
|
|
212
|
-
type: "string",
|
|
213
|
-
description: "Absolute local file path. The skill uploads it to PixelDojo (24h temp storage) and uses the resulting URL as the reference image. Prefer this over image_url when the user has a local file."
|
|
214
|
-
}
|
|
215
|
-
},
|
|
216
|
-
required: ["prompt"]
|
|
217
|
-
};
|
|
218
186
|
function buildPayload(apiId, input) {
|
|
219
187
|
const body = { prompt: input.prompt };
|
|
220
188
|
if (input.aspect_ratio) body.aspect_ratio = input.aspect_ratio;
|
|
@@ -283,77 +251,61 @@ async function run(input, ctx) {
|
|
|
283
251
|
(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(", ")}`
|
|
284
252
|
);
|
|
285
253
|
}
|
|
286
|
-
var
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
254
|
+
var InputSchema, DEFAULT_MODEL, InputJsonSchema, generateSkill;
|
|
255
|
+
var init_generate = __esm({
|
|
256
|
+
"src/skills/generate.ts"() {
|
|
257
|
+
init_poll();
|
|
258
|
+
init_types();
|
|
259
|
+
init_upload_helpers();
|
|
260
|
+
InputSchema = zod.z.object({
|
|
261
|
+
prompt: zod.z.string().min(1).max(8e3).describe("Prompt describing what to generate."),
|
|
262
|
+
model: zod.z.string().optional().describe(
|
|
263
|
+
'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.'
|
|
264
|
+
),
|
|
265
|
+
preset: zod.z.string().optional().describe(
|
|
266
|
+
'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.'
|
|
267
|
+
),
|
|
268
|
+
aspect_ratio: zod.z.string().optional().describe('Aspect ratio supported by the chosen model (e.g. "1:1", "16:9", "9:16").'),
|
|
269
|
+
duration: zod.z.number().int().positive().optional().describe("Video duration in seconds, when applicable."),
|
|
270
|
+
image_url: zod.z.string().url().optional().describe("Reference image URL for image-to-image / image-to-video tools."),
|
|
271
|
+
image_path: zod.z.string().min(1).optional().describe(
|
|
272
|
+
"Absolute local file path to a reference image/video. The skill uploads it to PixelDojo first (24h temp storage) and then dispatches. Prefer this over image_url when the user has the file on disk."
|
|
273
|
+
)
|
|
274
|
+
});
|
|
275
|
+
DEFAULT_MODEL = "google-nano-banana";
|
|
276
|
+
InputJsonSchema = {
|
|
277
|
+
type: "object",
|
|
278
|
+
properties: {
|
|
279
|
+
prompt: { type: "string", description: "Prompt describing what to generate." },
|
|
280
|
+
model: {
|
|
281
|
+
type: "string",
|
|
282
|
+
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.'
|
|
283
|
+
},
|
|
284
|
+
preset: {
|
|
285
|
+
type: "string",
|
|
286
|
+
description: 'Preset slug to seed the params (e.g. "cinematic-portrait", "product-floating-clean"). Explicit fields override preset values.'
|
|
287
|
+
},
|
|
288
|
+
aspect_ratio: { type: "string" },
|
|
289
|
+
duration: { type: "integer" },
|
|
290
|
+
image_url: { type: "string", format: "uri" },
|
|
291
|
+
image_path: {
|
|
292
|
+
type: "string",
|
|
293
|
+
description: "Absolute local file path. The skill uploads it to PixelDojo (24h temp storage) and uses the resulting URL as the reference image. Prefer this over image_url when the user has a local file."
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
required: ["prompt"]
|
|
297
|
+
};
|
|
298
|
+
generateSkill = {
|
|
299
|
+
name: "pixeldojo:generate",
|
|
300
|
+
description: "Generate any image or video from a prompt. Auto-routes to a sensible default model; pass `model` to pick a specific apiId from the catalog. For reference-image / image-to-video flows: pass `image_url` if you already have a URL, or `image_path` (absolute local path) and the skill uploads it to 24h temp storage automatically.",
|
|
301
|
+
inputZod: InputSchema,
|
|
302
|
+
inputJsonSchema: InputJsonSchema,
|
|
303
|
+
allowedModels: null,
|
|
304
|
+
defaultModel: DEFAULT_MODEL,
|
|
305
|
+
run
|
|
306
|
+
};
|
|
307
|
+
}
|
|
320
308
|
});
|
|
321
|
-
var InputJsonSchema2 = {
|
|
322
|
-
type: "object",
|
|
323
|
-
properties: {
|
|
324
|
-
prompt: { type: "string", description: "Edit instruction." },
|
|
325
|
-
image_url: {
|
|
326
|
-
type: "string",
|
|
327
|
-
format: "uri",
|
|
328
|
-
description: "Single reference image. Pass image_urls for multi-image edits."
|
|
329
|
-
},
|
|
330
|
-
image_urls: {
|
|
331
|
-
type: "array",
|
|
332
|
-
items: { type: "string", format: "uri" },
|
|
333
|
-
minItems: 1,
|
|
334
|
-
maxItems: 9,
|
|
335
|
-
description: "Multiple reference images (1-9)."
|
|
336
|
-
},
|
|
337
|
-
image_path: {
|
|
338
|
-
type: "string",
|
|
339
|
-
description: "Absolute local file path. Skill uploads it (24h temp storage) and edits the resulting URL. Prefer over image_url when the user has a local file."
|
|
340
|
-
},
|
|
341
|
-
image_paths: {
|
|
342
|
-
type: "array",
|
|
343
|
-
items: { type: "string" },
|
|
344
|
-
minItems: 1,
|
|
345
|
-
maxItems: 9,
|
|
346
|
-
description: "Multiple absolute local file paths (1-9). Each uploaded before dispatch."
|
|
347
|
-
},
|
|
348
|
-
model: {
|
|
349
|
-
type: "string",
|
|
350
|
-
enum: [...ALLOWED_MODELS],
|
|
351
|
-
description: "Override edit model. Default: wan-2.7-image-edit."
|
|
352
|
-
},
|
|
353
|
-
aspect_ratio: { type: "string" }
|
|
354
|
-
},
|
|
355
|
-
required: ["prompt"]
|
|
356
|
-
};
|
|
357
309
|
function buildPayload2(apiId, input) {
|
|
358
310
|
const urls = input.image_urls && input.image_urls.length > 0 ? input.image_urls : input.image_url ? [input.image_url] : [];
|
|
359
311
|
switch (apiId) {
|
|
@@ -373,7 +325,6 @@ function buildPayload2(apiId, input) {
|
|
|
373
325
|
case "flux-edit":
|
|
374
326
|
case "xai-image-edit":
|
|
375
327
|
case "gpt-image-2-edit":
|
|
376
|
-
case "hidream-edit":
|
|
377
328
|
return {
|
|
378
329
|
prompt: input.prompt,
|
|
379
330
|
image_url: urls[0],
|
|
@@ -435,39 +386,84 @@ async function run2(input, ctx) {
|
|
|
435
386
|
(urls) => urls.length === 0 ? `Edit job ${submitted.jobId} completed but returned no assets.` : urls.length === 1 ? `Edit complete. Asset: ${urls[0]}` : `Edit produced ${urls.length} assets. URLs: ${urls.join(", ")}`
|
|
436
387
|
);
|
|
437
388
|
}
|
|
438
|
-
var
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
389
|
+
var DEFAULT_MODEL2, ALLOWED_MODELS, InputSchema2, InputJsonSchema2, editSkill;
|
|
390
|
+
var init_edit = __esm({
|
|
391
|
+
"src/skills/edit.ts"() {
|
|
392
|
+
init_poll();
|
|
393
|
+
init_types();
|
|
394
|
+
init_upload_helpers();
|
|
395
|
+
DEFAULT_MODEL2 = "wan-2.7-image-edit";
|
|
396
|
+
ALLOWED_MODELS = [
|
|
397
|
+
"wan-2.7-image-edit",
|
|
398
|
+
"wan-2.6-image-edit",
|
|
399
|
+
"flux-edit",
|
|
400
|
+
"xai-image-edit",
|
|
401
|
+
"p-image-edit",
|
|
402
|
+
"gpt-image-2-edit",
|
|
403
|
+
"google-nano-banana"
|
|
404
|
+
];
|
|
405
|
+
InputSchema2 = zod.z.object({
|
|
406
|
+
prompt: zod.z.string().min(1).max(5e3).describe("Edit instruction."),
|
|
407
|
+
image_url: zod.z.string().url().optional().describe("Single reference image to edit. Pass image_urls for multi-image edits."),
|
|
408
|
+
image_urls: zod.z.array(zod.z.string().url()).min(1).max(9).optional().describe("Multiple reference images (1-9). Used for composition/multi-ref edits."),
|
|
409
|
+
image_path: zod.z.string().min(1).optional().describe(
|
|
410
|
+
"Absolute local file path. Skill uploads it (24h temp storage) and edits it. Prefer over image_url when the user has the file on disk."
|
|
411
|
+
),
|
|
412
|
+
image_paths: zod.z.array(zod.z.string().min(1)).min(1).max(9).optional().describe(
|
|
413
|
+
"Multiple absolute local file paths (1-9) for multi-image edits. Each uploaded to 24h temp storage before dispatch."
|
|
414
|
+
),
|
|
415
|
+
model: zod.z.enum(ALLOWED_MODELS).optional().describe(
|
|
416
|
+
"Override the default edit model. Defaults to wan-2.7-image-edit (most popular)."
|
|
417
|
+
),
|
|
418
|
+
aspect_ratio: zod.z.string().optional().describe('Aspect ratio when supported (e.g. "1:1", "16:9", "match_input_image").')
|
|
419
|
+
});
|
|
420
|
+
InputJsonSchema2 = {
|
|
421
|
+
type: "object",
|
|
422
|
+
properties: {
|
|
423
|
+
prompt: { type: "string", description: "Edit instruction." },
|
|
424
|
+
image_url: {
|
|
425
|
+
type: "string",
|
|
426
|
+
format: "uri",
|
|
427
|
+
description: "Single reference image. Pass image_urls for multi-image edits."
|
|
428
|
+
},
|
|
429
|
+
image_urls: {
|
|
430
|
+
type: "array",
|
|
431
|
+
items: { type: "string", format: "uri" },
|
|
432
|
+
minItems: 1,
|
|
433
|
+
maxItems: 9,
|
|
434
|
+
description: "Multiple reference images (1-9)."
|
|
435
|
+
},
|
|
436
|
+
image_path: {
|
|
437
|
+
type: "string",
|
|
438
|
+
description: "Absolute local file path. Skill uploads it (24h temp storage) and edits the resulting URL. Prefer over image_url when the user has a local file."
|
|
439
|
+
},
|
|
440
|
+
image_paths: {
|
|
441
|
+
type: "array",
|
|
442
|
+
items: { type: "string" },
|
|
443
|
+
minItems: 1,
|
|
444
|
+
maxItems: 9,
|
|
445
|
+
description: "Multiple absolute local file paths (1-9). Each uploaded before dispatch."
|
|
446
|
+
},
|
|
447
|
+
model: {
|
|
448
|
+
type: "string",
|
|
449
|
+
enum: [...ALLOWED_MODELS],
|
|
450
|
+
description: "Override edit model. Default: wan-2.7-image-edit."
|
|
451
|
+
},
|
|
452
|
+
aspect_ratio: { type: "string" }
|
|
453
|
+
},
|
|
454
|
+
required: ["prompt"]
|
|
455
|
+
};
|
|
456
|
+
editSkill = {
|
|
457
|
+
name: "pixeldojo:edit",
|
|
458
|
+
description: "Edit an existing image with a text instruction. Defaults to wan-2.7-image-edit; pass `model` to pick another edit-capable apiId. Supports up to 9 reference images for multi-image composition. For reference images: pass image_url(s) for hosted URLs or image_path(s) for absolute local file paths (skill uploads to 24h temp storage automatically).",
|
|
459
|
+
inputZod: InputSchema2,
|
|
460
|
+
inputJsonSchema: InputJsonSchema2,
|
|
461
|
+
allowedModels: [...ALLOWED_MODELS],
|
|
462
|
+
defaultModel: DEFAULT_MODEL2,
|
|
463
|
+
run: run2
|
|
464
|
+
};
|
|
465
|
+
}
|
|
456
466
|
});
|
|
457
|
-
var InputJsonSchema3 = {
|
|
458
|
-
type: "object",
|
|
459
|
-
properties: {
|
|
460
|
-
prompt: { type: "string" },
|
|
461
|
-
model: {
|
|
462
|
-
type: "string",
|
|
463
|
-
enum: ALLOWED,
|
|
464
|
-
description: `One of: ${ALLOWED.join(", ")}. Defaults to ${DEFAULT_MODEL3}.`
|
|
465
|
-
},
|
|
466
|
-
reference_image_url: { type: "string", format: "uri" },
|
|
467
|
-
aspect_ratio: { type: "string" }
|
|
468
|
-
},
|
|
469
|
-
required: ["prompt"]
|
|
470
|
-
};
|
|
471
467
|
async function run3(input, ctx) {
|
|
472
468
|
const requested = input.model ?? DEFAULT_MODEL3;
|
|
473
469
|
if (!ALLOWED.includes(requested)) {
|
|
@@ -504,40 +500,46 @@ async function run3(input, ctx) {
|
|
|
504
500
|
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Character shot ready. Asset: ${urls[0]}`
|
|
505
501
|
);
|
|
506
502
|
}
|
|
507
|
-
var
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
503
|
+
var ALLOWED, DEFAULT_MODEL3, InputSchema3, InputJsonSchema3, characterSkill;
|
|
504
|
+
var init_character = __esm({
|
|
505
|
+
"src/skills/character.ts"() {
|
|
506
|
+
init_poll();
|
|
507
|
+
init_types();
|
|
508
|
+
ALLOWED = ["ideogram-character", "flux-edit", "gpt-image-2-edit"];
|
|
509
|
+
DEFAULT_MODEL3 = "ideogram-character";
|
|
510
|
+
InputSchema3 = zod.z.object({
|
|
511
|
+
prompt: zod.z.string().min(1).max(8e3),
|
|
512
|
+
model: zod.z.string().optional().describe(`One of: ${ALLOWED.join(", ")}. Defaults to ${DEFAULT_MODEL3}.`),
|
|
513
|
+
reference_image_url: zod.z.string().url().optional().describe(
|
|
514
|
+
"Reference image of the character. Required by flux-edit and gpt-image-2-edit; optional for ideogram-character."
|
|
515
|
+
),
|
|
516
|
+
aspect_ratio: zod.z.string().optional()
|
|
517
|
+
});
|
|
518
|
+
InputJsonSchema3 = {
|
|
519
|
+
type: "object",
|
|
520
|
+
properties: {
|
|
521
|
+
prompt: { type: "string" },
|
|
522
|
+
model: {
|
|
523
|
+
type: "string",
|
|
524
|
+
enum: ALLOWED,
|
|
525
|
+
description: `One of: ${ALLOWED.join(", ")}. Defaults to ${DEFAULT_MODEL3}.`
|
|
526
|
+
},
|
|
527
|
+
reference_image_url: { type: "string", format: "uri" },
|
|
528
|
+
aspect_ratio: { type: "string" }
|
|
529
|
+
},
|
|
530
|
+
required: ["prompt"]
|
|
531
|
+
};
|
|
532
|
+
characterSkill = {
|
|
533
|
+
name: "pixeldojo:character",
|
|
534
|
+
description: "Generate or edit consistent characters across shots. Pass a reference_image_url for edit-style models.",
|
|
535
|
+
inputZod: InputSchema3,
|
|
536
|
+
inputJsonSchema: InputJsonSchema3,
|
|
537
|
+
allowedModels: [...ALLOWED],
|
|
538
|
+
defaultModel: DEFAULT_MODEL3,
|
|
539
|
+
run: run3
|
|
540
|
+
};
|
|
541
|
+
}
|
|
523
542
|
});
|
|
524
|
-
var InputJsonSchema4 = {
|
|
525
|
-
type: "object",
|
|
526
|
-
properties: {
|
|
527
|
-
brief: {
|
|
528
|
-
type: "string",
|
|
529
|
-
description: "Storyboard brief: scene, shots, mood, action."
|
|
530
|
-
},
|
|
531
|
-
model: {
|
|
532
|
-
type: "string",
|
|
533
|
-
enum: ALLOWED2,
|
|
534
|
-
description: `One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}.`
|
|
535
|
-
},
|
|
536
|
-
aspect_ratio: { type: "string" },
|
|
537
|
-
duration: { type: "integer" }
|
|
538
|
-
},
|
|
539
|
-
required: ["brief"]
|
|
540
|
-
};
|
|
541
543
|
async function run4(input, ctx) {
|
|
542
544
|
const requested = input.model ?? DEFAULT_MODEL4;
|
|
543
545
|
if (!ALLOWED2.includes(requested)) {
|
|
@@ -565,33 +567,47 @@ async function run4(input, ctx) {
|
|
|
565
567
|
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Storyboard preview ready. Asset: ${urls[0]}`
|
|
566
568
|
);
|
|
567
569
|
}
|
|
568
|
-
var
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
570
|
+
var ALLOWED2, DEFAULT_MODEL4, InputSchema4, InputJsonSchema4, storyboardSkill;
|
|
571
|
+
var init_storyboard = __esm({
|
|
572
|
+
"src/skills/storyboard.ts"() {
|
|
573
|
+
init_poll();
|
|
574
|
+
init_types();
|
|
575
|
+
ALLOWED2 = ["veo-3.1", "kling-video", "seedance-2"];
|
|
576
|
+
DEFAULT_MODEL4 = "veo-3.1";
|
|
577
|
+
InputSchema4 = zod.z.object({
|
|
578
|
+
brief: zod.z.string().min(1).max(8e3).describe("Storyboard brief: scene, shots, mood, action."),
|
|
579
|
+
model: zod.z.string().optional().describe(`One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}.`),
|
|
580
|
+
aspect_ratio: zod.z.string().optional(),
|
|
581
|
+
duration: zod.z.number().int().positive().optional()
|
|
582
|
+
});
|
|
583
|
+
InputJsonSchema4 = {
|
|
584
|
+
type: "object",
|
|
585
|
+
properties: {
|
|
586
|
+
brief: {
|
|
587
|
+
type: "string",
|
|
588
|
+
description: "Storyboard brief: scene, shots, mood, action."
|
|
589
|
+
},
|
|
590
|
+
model: {
|
|
591
|
+
type: "string",
|
|
592
|
+
enum: ALLOWED2,
|
|
593
|
+
description: `One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}.`
|
|
594
|
+
},
|
|
595
|
+
aspect_ratio: { type: "string" },
|
|
596
|
+
duration: { type: "integer" }
|
|
597
|
+
},
|
|
598
|
+
required: ["brief"]
|
|
599
|
+
};
|
|
600
|
+
storyboardSkill = {
|
|
601
|
+
name: "pixeldojo:storyboard",
|
|
602
|
+
description: "Generate a video storyboard preview from a single brief. v1: single-shot preview; multi-shot orchestration coming.",
|
|
603
|
+
inputZod: InputSchema4,
|
|
604
|
+
inputJsonSchema: InputJsonSchema4,
|
|
605
|
+
allowedModels: [...ALLOWED2],
|
|
606
|
+
defaultModel: DEFAULT_MODEL4,
|
|
607
|
+
run: run4
|
|
608
|
+
};
|
|
609
|
+
}
|
|
584
610
|
});
|
|
585
|
-
var InputJsonSchema5 = {
|
|
586
|
-
type: "object",
|
|
587
|
-
properties: {
|
|
588
|
-
image_url: { type: "string", format: "uri" },
|
|
589
|
-
model: { type: "string", enum: ALLOWED3 },
|
|
590
|
-
scale_factor: { type: "integer", minimum: 1, maximum: 4 },
|
|
591
|
-
creativity: { type: "number", minimum: 0, maximum: 1 }
|
|
592
|
-
},
|
|
593
|
-
required: ["image_url"]
|
|
594
|
-
};
|
|
595
611
|
async function run5(input, ctx) {
|
|
596
612
|
const requested = input.model ?? DEFAULT_MODEL5;
|
|
597
613
|
if (!ALLOWED3.includes(requested)) {
|
|
@@ -624,30 +640,40 @@ async function run5(input, ctx) {
|
|
|
624
640
|
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Upscaled. Asset: ${urls[0]}`
|
|
625
641
|
);
|
|
626
642
|
}
|
|
627
|
-
var
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
643
|
+
var ALLOWED3, DEFAULT_MODEL5, InputSchema5, InputJsonSchema5, upscaleSkill;
|
|
644
|
+
var init_upscale = __esm({
|
|
645
|
+
"src/skills/upscale.ts"() {
|
|
646
|
+
init_poll();
|
|
647
|
+
init_types();
|
|
648
|
+
ALLOWED3 = ["magnific-upscaler", "creative-upscale", "face-enhance"];
|
|
649
|
+
DEFAULT_MODEL5 = "magnific-upscaler";
|
|
650
|
+
InputSchema5 = zod.z.object({
|
|
651
|
+
image_url: zod.z.string().url().describe("URL of the source image to upscale."),
|
|
652
|
+
model: zod.z.string().optional().describe(`One of: ${ALLOWED3.join(", ")}. Defaults to ${DEFAULT_MODEL5}.`),
|
|
653
|
+
scale_factor: zod.z.number().int().min(1).max(4).optional().describe("Magnific only: 1, 2, or 4. Defaults to 2."),
|
|
654
|
+
creativity: zod.z.number().min(0).max(1).optional().describe("Magnific only: 0 (preserve) \u2192 1 (creative). Defaults to 0.")
|
|
655
|
+
});
|
|
656
|
+
InputJsonSchema5 = {
|
|
657
|
+
type: "object",
|
|
658
|
+
properties: {
|
|
659
|
+
image_url: { type: "string", format: "uri" },
|
|
660
|
+
model: { type: "string", enum: ALLOWED3 },
|
|
661
|
+
scale_factor: { type: "integer", minimum: 1, maximum: 4 },
|
|
662
|
+
creativity: { type: "number", minimum: 0, maximum: 1 }
|
|
663
|
+
},
|
|
664
|
+
required: ["image_url"]
|
|
665
|
+
};
|
|
666
|
+
upscaleSkill = {
|
|
667
|
+
name: "pixeldojo:upscale",
|
|
668
|
+
description: "Enhance an image. Magnific (default) supports configurable scale_factor and creativity; face-enhance for portraits.",
|
|
669
|
+
inputZod: InputSchema5,
|
|
670
|
+
inputJsonSchema: InputJsonSchema5,
|
|
671
|
+
allowedModels: [...ALLOWED3],
|
|
672
|
+
defaultModel: DEFAULT_MODEL5,
|
|
673
|
+
run: run5
|
|
674
|
+
};
|
|
675
|
+
}
|
|
638
676
|
});
|
|
639
|
-
var InputJsonSchema6 = {
|
|
640
|
-
type: "object",
|
|
641
|
-
properties: {
|
|
642
|
-
jobId: {
|
|
643
|
-
type: "string",
|
|
644
|
-
description: "Job id returned from a prior pixeldojo:* skill handoff."
|
|
645
|
-
}
|
|
646
|
-
},
|
|
647
|
-
required: ["jobId"]
|
|
648
|
-
};
|
|
649
|
-
var STUCK_HINT_MS = 5 * 60 * 1e3;
|
|
650
|
-
var ABANDON_HINT_MS = 12 * 60 * 1e3;
|
|
651
677
|
async function run6(input, ctx) {
|
|
652
678
|
const job = await ctx.client.getJob(input.jobId);
|
|
653
679
|
if (job.status === "completed") {
|
|
@@ -712,29 +738,36 @@ function extractAssetUrls2(job) {
|
|
|
712
738
|
if (output?.video) return [output.video];
|
|
713
739
|
return [];
|
|
714
740
|
}
|
|
715
|
-
var
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
741
|
+
var InputSchema6, InputJsonSchema6, STUCK_HINT_MS, ABANDON_HINT_MS, statusSkill;
|
|
742
|
+
var init_status = __esm({
|
|
743
|
+
"src/skills/status.ts"() {
|
|
744
|
+
InputSchema6 = zod.z.object({
|
|
745
|
+
jobId: zod.z.string().min(1).max(200).describe("Job id returned from a prior pixeldojo:* skill handoff.")
|
|
746
|
+
});
|
|
747
|
+
InputJsonSchema6 = {
|
|
748
|
+
type: "object",
|
|
749
|
+
properties: {
|
|
750
|
+
jobId: {
|
|
751
|
+
type: "string",
|
|
752
|
+
description: "Job id returned from a prior pixeldojo:* skill handoff."
|
|
753
|
+
}
|
|
754
|
+
},
|
|
755
|
+
required: ["jobId"]
|
|
756
|
+
};
|
|
757
|
+
STUCK_HINT_MS = 5 * 60 * 1e3;
|
|
758
|
+
ABANDON_HINT_MS = 12 * 60 * 1e3;
|
|
759
|
+
statusSkill = {
|
|
760
|
+
name: "pixeldojo:status",
|
|
761
|
+
description: "Check the status of a long-running job after a 30s sync handoff. Returns assets when ready, failure reason if failed, or current state if still running.",
|
|
762
|
+
inputZod: InputSchema6,
|
|
763
|
+
inputJsonSchema: InputJsonSchema6,
|
|
764
|
+
// status is special — it doesn't dispatch to a model
|
|
765
|
+
allowedModels: [],
|
|
766
|
+
defaultModel: "",
|
|
767
|
+
run: run6
|
|
768
|
+
};
|
|
769
|
+
}
|
|
727
770
|
});
|
|
728
|
-
var InputJsonSchema7 = {
|
|
729
|
-
type: "object",
|
|
730
|
-
properties: {
|
|
731
|
-
url: {
|
|
732
|
-
type: "string",
|
|
733
|
-
description: "Product page URL. Shopify, BigCommerce, WooCommerce, or any page with JSON-LD / OpenGraph product metadata."
|
|
734
|
-
}
|
|
735
|
-
},
|
|
736
|
-
required: ["url"]
|
|
737
|
-
};
|
|
738
771
|
async function run7(input, ctx) {
|
|
739
772
|
const product = await ctx.client.extractProduct(input.url);
|
|
740
773
|
const summary = [
|
|
@@ -752,60 +785,34 @@ function truncate(input, max) {
|
|
|
752
785
|
if (input.length <= max) return input;
|
|
753
786
|
return input.slice(0, max - 3) + "...";
|
|
754
787
|
}
|
|
755
|
-
var
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
defaultModel: "",
|
|
763
|
-
run: run7
|
|
764
|
-
};
|
|
765
|
-
var InputSchema8 = zod.z.object({
|
|
766
|
-
productUrl: zod.z.string().url().optional().describe("Product page URL. We extract name + description + images automatically."),
|
|
767
|
-
product: zod.z.object({
|
|
768
|
-
name: zod.z.string().min(1).max(200),
|
|
769
|
-
description: zod.z.string().max(2e3).optional(),
|
|
770
|
-
images: zod.z.array(zod.z.string().url()).max(5).optional()
|
|
771
|
-
}).optional().describe("Manual product fields, used when productUrl is omitted."),
|
|
772
|
-
tone: zod.z.string().max(120).optional().describe('Optional creative direction ("premium minimalist", "playful Y2K"). Threaded through every prompt.'),
|
|
773
|
-
variants: zod.z.number().int().min(1).max(8).optional().describe("Lifestyle shots in addition to the hero (default 4, max 8)."),
|
|
774
|
-
includeVideo: zod.z.boolean().optional().describe("Whether to also generate a vertical launch video (default true)."),
|
|
775
|
-
videoAspectRatio: zod.z.enum(["9:16", "16:9", "1:1"]).optional().describe("Aspect ratio of the launch video (default 9:16 for Reels/TikTok)."),
|
|
776
|
-
videoMode: zod.z.enum(["lifestyle", "cgi", "ugc", "skip"]).optional().describe("Video styling \u2014 lifestyle (default), cgi, ugc, or skip to omit video.")
|
|
777
|
-
}).refine((v) => v.productUrl || v.product, {
|
|
778
|
-
message: "productUrl or product is required",
|
|
779
|
-
path: ["productUrl"]
|
|
780
|
-
});
|
|
781
|
-
var InputJsonSchema8 = {
|
|
782
|
-
type: "object",
|
|
783
|
-
properties: {
|
|
784
|
-
productUrl: {
|
|
785
|
-
type: "string",
|
|
786
|
-
format: "uri",
|
|
787
|
-
description: "Product page URL. We extract name + description + images automatically."
|
|
788
|
-
},
|
|
789
|
-
product: {
|
|
788
|
+
var InputSchema7, InputJsonSchema7, fromUrlSkill;
|
|
789
|
+
var init_from_url = __esm({
|
|
790
|
+
"src/skills/from-url.ts"() {
|
|
791
|
+
InputSchema7 = zod.z.object({
|
|
792
|
+
url: zod.z.string().min(1).max(2048).describe("Product page URL. Shopify, BigCommerce, WooCommerce, or any page with JSON-LD / OpenGraph product metadata.")
|
|
793
|
+
});
|
|
794
|
+
InputJsonSchema7 = {
|
|
790
795
|
type: "object",
|
|
791
796
|
properties: {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
797
|
+
url: {
|
|
798
|
+
type: "string",
|
|
799
|
+
description: "Product page URL. Shopify, BigCommerce, WooCommerce, or any page with JSON-LD / OpenGraph product metadata."
|
|
800
|
+
}
|
|
795
801
|
},
|
|
796
|
-
required: ["
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
description: "
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
}
|
|
802
|
+
required: ["url"]
|
|
803
|
+
};
|
|
804
|
+
fromUrlSkill = {
|
|
805
|
+
name: "pixeldojo:from_url",
|
|
806
|
+
description: "Extract product info (name, description, images) from any product page URL. Use this as the first step before pixeldojo:campaign / :ad / :lookbook so the agent has structured product data instead of a free-text description.",
|
|
807
|
+
inputZod: InputSchema7,
|
|
808
|
+
inputJsonSchema: InputJsonSchema7,
|
|
809
|
+
// No model dispatch — this skill calls a server-side scrape, not a generation.
|
|
810
|
+
allowedModels: [],
|
|
811
|
+
defaultModel: "",
|
|
812
|
+
run: run7
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
});
|
|
809
816
|
async function run8(input, ctx) {
|
|
810
817
|
const client = ctx.client;
|
|
811
818
|
const result = await client.runCampaign(input);
|
|
@@ -833,30 +840,66 @@ async function run8(input, ctx) {
|
|
|
833
840
|
statusUrl: result.statusUrl ?? ctx.buildStatusUrl(result.campaignId)
|
|
834
841
|
};
|
|
835
842
|
}
|
|
836
|
-
var
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
843
|
+
var InputSchema8, InputJsonSchema8, campaignSkill;
|
|
844
|
+
var init_campaign = __esm({
|
|
845
|
+
"src/skills/campaign.ts"() {
|
|
846
|
+
InputSchema8 = zod.z.object({
|
|
847
|
+
productUrl: zod.z.string().url().optional().describe("Product page URL. We extract name + description + images automatically."),
|
|
848
|
+
product: zod.z.object({
|
|
849
|
+
name: zod.z.string().min(1).max(200),
|
|
850
|
+
description: zod.z.string().max(2e3).optional(),
|
|
851
|
+
images: zod.z.array(zod.z.string().url()).max(5).optional()
|
|
852
|
+
}).optional().describe("Manual product fields, used when productUrl is omitted."),
|
|
853
|
+
tone: zod.z.string().max(120).optional().describe('Optional creative direction ("premium minimalist", "playful Y2K"). Threaded through every prompt.'),
|
|
854
|
+
variants: zod.z.number().int().min(1).max(8).optional().describe("Lifestyle shots in addition to the hero (default 4, max 8)."),
|
|
855
|
+
includeVideo: zod.z.boolean().optional().describe("Whether to also generate a vertical launch video (default true)."),
|
|
856
|
+
videoAspectRatio: zod.z.enum(["9:16", "16:9", "1:1"]).optional().describe("Aspect ratio of the launch video (default 9:16 for Reels/TikTok)."),
|
|
857
|
+
videoMode: zod.z.enum(["lifestyle", "cgi", "ugc", "skip"]).optional().describe("Video styling \u2014 lifestyle (default), cgi, ugc, or skip to omit video.")
|
|
858
|
+
}).refine((v) => v.productUrl || v.product, {
|
|
859
|
+
message: "productUrl or product is required",
|
|
860
|
+
path: ["productUrl"]
|
|
861
|
+
});
|
|
862
|
+
InputJsonSchema8 = {
|
|
863
|
+
type: "object",
|
|
864
|
+
properties: {
|
|
865
|
+
productUrl: {
|
|
866
|
+
type: "string",
|
|
867
|
+
format: "uri",
|
|
868
|
+
description: "Product page URL. We extract name + description + images automatically."
|
|
869
|
+
},
|
|
870
|
+
product: {
|
|
871
|
+
type: "object",
|
|
872
|
+
properties: {
|
|
873
|
+
name: { type: "string" },
|
|
874
|
+
description: { type: "string" },
|
|
875
|
+
images: { type: "array", items: { type: "string", format: "uri" } }
|
|
876
|
+
},
|
|
877
|
+
required: ["name"]
|
|
878
|
+
},
|
|
879
|
+
tone: {
|
|
880
|
+
type: "string",
|
|
881
|
+
description: "Creative direction threaded through every prompt."
|
|
882
|
+
},
|
|
883
|
+
variants: { type: "integer", minimum: 1, maximum: 8 },
|
|
884
|
+
includeVideo: { type: "boolean" },
|
|
885
|
+
videoAspectRatio: { type: "string", enum: ["9:16", "16:9", "1:1"] },
|
|
886
|
+
videoMode: { type: "string", enum: ["lifestyle", "cgi", "ugc", "skip"] }
|
|
887
|
+
},
|
|
888
|
+
oneOf: [{ required: ["productUrl"] }, { required: ["product"] }]
|
|
889
|
+
};
|
|
890
|
+
campaignSkill = {
|
|
891
|
+
name: "pixeldojo:campaign",
|
|
892
|
+
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.",
|
|
893
|
+
inputZod: InputSchema8,
|
|
894
|
+
inputJsonSchema: InputJsonSchema8,
|
|
895
|
+
// Composition skill — internal sub-jobs route to per-tool models, no
|
|
896
|
+
// single allowed-models list applies here.
|
|
897
|
+
allowedModels: [],
|
|
898
|
+
defaultModel: "",
|
|
899
|
+
run: run8
|
|
900
|
+
};
|
|
901
|
+
}
|
|
849
902
|
});
|
|
850
|
-
var InputJsonSchema9 = {
|
|
851
|
-
type: "object",
|
|
852
|
-
properties: {
|
|
853
|
-
campaignId: {
|
|
854
|
-
type: "string",
|
|
855
|
-
description: "Campaign id returned from a prior pixeldojo:campaign handoff."
|
|
856
|
-
}
|
|
857
|
-
},
|
|
858
|
-
required: ["campaignId"]
|
|
859
|
-
};
|
|
860
903
|
async function run9(input, ctx) {
|
|
861
904
|
const client = ctx.client;
|
|
862
905
|
const result = await client.getCampaign(input.campaignId);
|
|
@@ -887,30 +930,33 @@ async function run9(input, ctx) {
|
|
|
887
930
|
statusUrl: result.statusUrl ?? ctx.buildStatusUrl(result.campaignId)
|
|
888
931
|
};
|
|
889
932
|
}
|
|
890
|
-
var
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
933
|
+
var InputSchema9, InputJsonSchema9, campaignStatusSkill;
|
|
934
|
+
var init_campaign_status = __esm({
|
|
935
|
+
"src/skills/campaign-status.ts"() {
|
|
936
|
+
InputSchema9 = zod.z.object({
|
|
937
|
+
campaignId: zod.z.string().min(1).max(200).describe("Campaign id returned from a prior pixeldojo:campaign handoff.")
|
|
938
|
+
});
|
|
939
|
+
InputJsonSchema9 = {
|
|
940
|
+
type: "object",
|
|
941
|
+
properties: {
|
|
942
|
+
campaignId: {
|
|
943
|
+
type: "string",
|
|
944
|
+
description: "Campaign id returned from a prior pixeldojo:campaign handoff."
|
|
945
|
+
}
|
|
946
|
+
},
|
|
947
|
+
required: ["campaignId"]
|
|
948
|
+
};
|
|
949
|
+
campaignStatusSkill = {
|
|
950
|
+
name: "pixeldojo:campaign_status",
|
|
951
|
+
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.",
|
|
952
|
+
inputZod: InputSchema9,
|
|
953
|
+
inputJsonSchema: InputJsonSchema9,
|
|
954
|
+
allowedModels: [],
|
|
955
|
+
defaultModel: "",
|
|
956
|
+
run: run9
|
|
957
|
+
};
|
|
958
|
+
}
|
|
903
959
|
});
|
|
904
|
-
var InputJsonSchema10 = {
|
|
905
|
-
type: "object",
|
|
906
|
-
properties: {
|
|
907
|
-
path: {
|
|
908
|
-
type: "string",
|
|
909
|
-
description: "Absolute local file path. Allowed: JPEG, PNG, WebP, GIF (\u226450MB) or MP4, WebM, MOV (\u2264200MB). Returns a public URL on the temp CDN; auto-expires after 24h."
|
|
910
|
-
}
|
|
911
|
-
},
|
|
912
|
-
required: ["path"]
|
|
913
|
-
};
|
|
914
960
|
async function run10(input, ctx) {
|
|
915
961
|
let url;
|
|
916
962
|
try {
|
|
@@ -927,32 +973,444 @@ async function run10(input, ctx) {
|
|
|
927
973
|
(temp storage; auto-deletes in ~24h \u2014 pass this URL as image_url to :generate or :edit)`
|
|
928
974
|
};
|
|
929
975
|
}
|
|
930
|
-
var
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
};
|
|
976
|
+
var InputSchema10, InputJsonSchema10, uploadSkill;
|
|
977
|
+
var init_upload = __esm({
|
|
978
|
+
"src/skills/upload.ts"() {
|
|
979
|
+
init_upload_helpers();
|
|
980
|
+
InputSchema10 = zod.z.object({
|
|
981
|
+
path: zod.z.string().min(1).max(4096).describe(
|
|
982
|
+
"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."
|
|
983
|
+
)
|
|
984
|
+
});
|
|
985
|
+
InputJsonSchema10 = {
|
|
986
|
+
type: "object",
|
|
987
|
+
properties: {
|
|
988
|
+
path: {
|
|
989
|
+
type: "string",
|
|
990
|
+
description: "Absolute local file path. Allowed: JPEG, PNG, WebP, GIF (\u226450MB) or MP4, WebM, MOV (\u2264200MB). Returns a public URL on the temp CDN; auto-expires after 24h."
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
required: ["path"]
|
|
994
|
+
};
|
|
995
|
+
uploadSkill = {
|
|
996
|
+
name: "pixeldojo:upload",
|
|
997
|
+
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.",
|
|
998
|
+
inputZod: InputSchema10,
|
|
999
|
+
inputJsonSchema: InputJsonSchema10,
|
|
1000
|
+
allowedModels: [],
|
|
1001
|
+
defaultModel: "",
|
|
1002
|
+
run: run10
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
async function run11(input, ctx) {
|
|
1007
|
+
const requested = input.model ?? DEFAULT_MODEL6;
|
|
1008
|
+
if (!ALLOWED4.includes(requested)) {
|
|
1009
|
+
return {
|
|
1010
|
+
kind: "text",
|
|
1011
|
+
text: `Unknown model "${requested}" for pixeldojo:audio. Allowed: ${ALLOWED4.join(", ")}.`
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
const apiId = requested;
|
|
1015
|
+
let audioUrls = input.audio_urls ?? [];
|
|
1016
|
+
if (input.audio_paths?.length) {
|
|
1017
|
+
try {
|
|
1018
|
+
const uploaded = await uploadLocalFiles(input.audio_paths, ctx.client);
|
|
1019
|
+
audioUrls = [...audioUrls, ...uploaded].slice(0, 3);
|
|
1020
|
+
} catch (err) {
|
|
1021
|
+
if (err instanceof SkillUploadError) {
|
|
1022
|
+
return { kind: "text", text: `pixeldojo:audio (upload): ${err.userMessage}` };
|
|
1023
|
+
}
|
|
1024
|
+
throw err;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
const body = { prompt: input.prompt };
|
|
1028
|
+
if (apiId === "seed-audio") {
|
|
1029
|
+
if (input.voice) body.voice = input.voice;
|
|
1030
|
+
if (audioUrls.length) body.audio_urls = audioUrls;
|
|
1031
|
+
if (input.output_format) body.output_format = input.output_format;
|
|
1032
|
+
if (input.speed !== void 0) body.speed = input.speed;
|
|
1033
|
+
} else {
|
|
1034
|
+
body.text = input.prompt;
|
|
1035
|
+
delete body.prompt;
|
|
1036
|
+
if (input.voice) body.voice_id = input.voice;
|
|
1037
|
+
if (input.output_format) body.audio_format = input.output_format;
|
|
1038
|
+
if (input.speed !== void 0) body.speed = input.speed;
|
|
1039
|
+
}
|
|
1040
|
+
const submitted = await ctx.client.run(apiId, body);
|
|
1041
|
+
const result = await pollJobUntilDoneOrHandoff(
|
|
1042
|
+
submitted.jobId,
|
|
1043
|
+
(id) => ctx.client.getJob(id),
|
|
1044
|
+
ctx.buildStatusUrl,
|
|
1045
|
+
{
|
|
1046
|
+
now: ctx.pollOverrides?.now,
|
|
1047
|
+
sleep: ctx.pollOverrides?.sleep
|
|
1048
|
+
}
|
|
1049
|
+
);
|
|
1050
|
+
return pollResultToSkillResult(
|
|
1051
|
+
result,
|
|
1052
|
+
(urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Audio ready. Asset: ${urls[0]}`
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
var ALLOWED4, DEFAULT_MODEL6, InputSchema11, InputJsonSchema11, audioSkill;
|
|
1056
|
+
var init_audio = __esm({
|
|
1057
|
+
"src/skills/audio.ts"() {
|
|
1058
|
+
init_poll();
|
|
1059
|
+
init_upload_helpers();
|
|
1060
|
+
init_types();
|
|
1061
|
+
ALLOWED4 = ["seed-audio", "text-to-speech"];
|
|
1062
|
+
DEFAULT_MODEL6 = "seed-audio";
|
|
1063
|
+
InputSchema11 = zod.z.object({
|
|
1064
|
+
prompt: zod.z.string().min(1).describe(
|
|
1065
|
+
"A script for speech, or a scene description for cinematic audio (dialogue + effects + music). Reference uploaded clips as @Audio1..@Audio3."
|
|
1066
|
+
),
|
|
1067
|
+
model: zod.z.string().optional().describe(`One of: ${ALLOWED4.join(", ")}. Defaults to ${DEFAULT_MODEL6}.`),
|
|
1068
|
+
voice: zod.z.string().optional().describe("Optional voice preset name or cloned-voice id (seed-audio) / voice_id (text-to-speech)."),
|
|
1069
|
+
audio_urls: zod.z.array(zod.z.string().url()).max(3).optional().describe("seed-audio only: up to 3 reference audio URLs (30s / 10MB max each)."),
|
|
1070
|
+
audio_paths: zod.z.array(zod.z.string()).max(3).optional().describe("seed-audio only: absolute local paths to reference clips; uploaded automatically (24h temp storage)."),
|
|
1071
|
+
output_format: zod.z.string().optional().describe("seed-audio: mp3 (default), wav, pcm, ogg_opus. text-to-speech: mp3, wav, flac, pcm."),
|
|
1072
|
+
speed: zod.z.number().min(0.5).max(2).optional().describe("Speech speed multiplier (0.5\u20132).")
|
|
1073
|
+
});
|
|
1074
|
+
InputJsonSchema11 = {
|
|
1075
|
+
type: "object",
|
|
1076
|
+
properties: {
|
|
1077
|
+
prompt: { type: "string" },
|
|
1078
|
+
model: { type: "string", enum: ALLOWED4 },
|
|
1079
|
+
voice: { type: "string" },
|
|
1080
|
+
audio_urls: { type: "array", items: { type: "string", format: "uri" }, maxItems: 3 },
|
|
1081
|
+
audio_paths: { type: "array", items: { type: "string" }, maxItems: 3 },
|
|
1082
|
+
output_format: { type: "string" },
|
|
1083
|
+
speed: { type: "number", minimum: 0.5, maximum: 2 }
|
|
1084
|
+
},
|
|
1085
|
+
required: ["prompt"]
|
|
1086
|
+
};
|
|
1087
|
+
audioSkill = {
|
|
1088
|
+
name: "pixeldojo:audio",
|
|
1089
|
+
description: "Generate audio: speech, multi-character dialogue, sound effects, and background music from one prompt (Seed Audio 1.0 by default; plain TTS available).",
|
|
1090
|
+
inputZod: InputSchema11,
|
|
1091
|
+
inputJsonSchema: InputJsonSchema11,
|
|
1092
|
+
allowedModels: [...ALLOWED4],
|
|
1093
|
+
defaultModel: DEFAULT_MODEL6,
|
|
1094
|
+
run: run11
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
});
|
|
1098
|
+
async function run12(input, ctx) {
|
|
1099
|
+
const res = await ctx.client.listLibrary({
|
|
1100
|
+
q: input.q,
|
|
1101
|
+
model: input.model,
|
|
1102
|
+
modality: input.modality,
|
|
1103
|
+
limit: input.limit ?? 10
|
|
1104
|
+
});
|
|
1105
|
+
if (res.items.length === 0) {
|
|
1106
|
+
return {
|
|
1107
|
+
kind: "text",
|
|
1108
|
+
text: input.q ? `No library items match "${input.q}". Try a broader query, or omit q to list recent generations.` : "Your library is empty. Generate something with pixeldojo:generate first."
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
const lines = res.items.map((it) => {
|
|
1112
|
+
const parts = [
|
|
1113
|
+
`- ${it.url}`,
|
|
1114
|
+
it.modality ? `[${it.modality}]` : null,
|
|
1115
|
+
it.model ? `model=${it.model}` : null,
|
|
1116
|
+
`(${it.source}, ${it.createdAt.slice(0, 10)})`,
|
|
1117
|
+
it.prompt ? `"${it.prompt.slice(0, 90)}${it.prompt.length > 90 ? "\u2026" : ""}"` : null
|
|
1118
|
+
].filter(Boolean);
|
|
1119
|
+
return parts.join(" ");
|
|
1120
|
+
});
|
|
1121
|
+
return {
|
|
1122
|
+
kind: "text",
|
|
1123
|
+
text: `${res.items.length} library item(s):
|
|
1124
|
+
${lines.join("\n")}
|
|
1125
|
+
|
|
1126
|
+
Pass any URL back into :generate, :edit, :character, or :upscale as a reference input.`
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
var InputSchema12, InputJsonSchema12, librarySkill;
|
|
1130
|
+
var init_library = __esm({
|
|
1131
|
+
"src/skills/library.ts"() {
|
|
1132
|
+
InputSchema12 = zod.z.object({
|
|
1133
|
+
q: zod.z.string().optional().describe("Substring match against the prompt that produced the asset."),
|
|
1134
|
+
model: zod.z.string().optional().describe("Restrict to a single model (apiId)."),
|
|
1135
|
+
modality: zod.z.enum(["image", "video", "audio"]).optional().describe("Restrict to one output type."),
|
|
1136
|
+
limit: zod.z.number().int().min(1).max(50).optional().describe("Max results (default 10).")
|
|
1137
|
+
});
|
|
1138
|
+
InputJsonSchema12 = {
|
|
1139
|
+
type: "object",
|
|
1140
|
+
properties: {
|
|
1141
|
+
q: { type: "string" },
|
|
1142
|
+
model: { type: "string" },
|
|
1143
|
+
modality: { type: "string", enum: ["image", "video", "audio"] },
|
|
1144
|
+
limit: { type: "integer", minimum: 1, maximum: 50 }
|
|
1145
|
+
},
|
|
1146
|
+
required: []
|
|
1147
|
+
};
|
|
1148
|
+
librarySkill = {
|
|
1149
|
+
name: "pixeldojo:library",
|
|
1150
|
+
description: "Search your own generation history (API/MCP outputs + results kept in the web app). Returns asset URLs to reuse as reference inputs.",
|
|
1151
|
+
inputZod: InputSchema12,
|
|
1152
|
+
inputJsonSchema: InputJsonSchema12,
|
|
1153
|
+
allowedModels: [],
|
|
1154
|
+
defaultModel: "",
|
|
1155
|
+
run: run12
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
1159
|
+
function substitutePlaceholders(args, inputs, prevUrl) {
|
|
1160
|
+
const missing = [];
|
|
1161
|
+
const fill = (value) => {
|
|
1162
|
+
if (typeof value === "string") {
|
|
1163
|
+
return value.replace(/\{\{(prev|input\.[a-zA-Z0-9_-]+)\}\}/g, (_, token) => {
|
|
1164
|
+
if (token === "prev") {
|
|
1165
|
+
if (!prevUrl) missing.push("{{prev}}");
|
|
1166
|
+
return prevUrl ?? "";
|
|
1167
|
+
}
|
|
1168
|
+
const key = token.slice("input.".length);
|
|
1169
|
+
if (!(key in inputs)) missing.push(`{{${token}}}`);
|
|
1170
|
+
return inputs[key] ?? "";
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
if (Array.isArray(value)) return value.map(fill);
|
|
1174
|
+
if (value && typeof value === "object") {
|
|
1175
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, fill(v)]));
|
|
1176
|
+
}
|
|
1177
|
+
return value;
|
|
1178
|
+
};
|
|
1179
|
+
return { resolved: fill(args), missing };
|
|
1180
|
+
}
|
|
1181
|
+
function firstUrl(result) {
|
|
1182
|
+
if (result.kind === "assets" && result.assetUrls.length > 0) return result.assetUrls[0];
|
|
1183
|
+
if (result.kind === "text") {
|
|
1184
|
+
const m = result.text.match(/https?:\/\/\S+/);
|
|
1185
|
+
return m?.[0].replace(/[).,]+$/, "");
|
|
1186
|
+
}
|
|
1187
|
+
return void 0;
|
|
1188
|
+
}
|
|
1189
|
+
async function runSave(input, ctx) {
|
|
1190
|
+
const res = await ctx.client.saveWorkflow({
|
|
1191
|
+
name: input.name,
|
|
1192
|
+
description: input.description,
|
|
1193
|
+
steps: input.steps.map((s) => ({ skill: s.skill, args: s.args ?? {} }))
|
|
1194
|
+
});
|
|
1195
|
+
return {
|
|
1196
|
+
kind: "text",
|
|
1197
|
+
text: res.created ? `Saved workflow "${res.name}" (${res.steps} step${res.steps === 1 ? "" : "s"}). Run it with pixeldojo:run_workflow { name: "${res.name}" }.` : `Overwrote workflow "${res.name}" (${res.steps} step${res.steps === 1 ? "" : "s"}).`
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
async function runList(_input, ctx) {
|
|
1201
|
+
const res = await ctx.client.listWorkflows();
|
|
1202
|
+
if (res.count === 0) {
|
|
1203
|
+
return {
|
|
1204
|
+
kind: "text",
|
|
1205
|
+
text: "No saved workflows yet. Save one with pixeldojo:save_workflow { name, steps: [{ skill, args }] }."
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
const lines = res.workflows.map(
|
|
1209
|
+
(w) => `- ${w.name} (${w.steps.length} steps, ${w.runs} runs)${w.description ? `: ${w.description}` : ""}`
|
|
1210
|
+
);
|
|
1211
|
+
return { kind: "text", text: `${res.count} saved workflow(s):
|
|
1212
|
+
${lines.join("\n")}` };
|
|
1213
|
+
}
|
|
1214
|
+
async function runWorkflow(input, ctx) {
|
|
1215
|
+
const workflow = await ctx.client.getWorkflow(input.name.toLowerCase(), { countRun: true });
|
|
1216
|
+
const { findSkill: findSkill2 } = await Promise.resolve().then(() => (init_skills(), skills_exports));
|
|
1217
|
+
const inputs = input.inputs ?? {};
|
|
1218
|
+
const outputs = [];
|
|
1219
|
+
let prevUrl;
|
|
1220
|
+
for (let i = 0; i < workflow.steps.length; i++) {
|
|
1221
|
+
const step = workflow.steps[i];
|
|
1222
|
+
const skill = findSkill2(step.skill);
|
|
1223
|
+
if (!skill) {
|
|
1224
|
+
return {
|
|
1225
|
+
kind: "text",
|
|
1226
|
+
text: `Step ${i + 1} names unknown skill "${step.skill}". Re-save the workflow.`
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
const { resolved, missing } = substitutePlaceholders(step.args, inputs, prevUrl);
|
|
1230
|
+
if (missing.length > 0) {
|
|
1231
|
+
return {
|
|
1232
|
+
kind: "text",
|
|
1233
|
+
text: `Step ${i + 1} (${step.skill}) is missing ${Array.from(new Set(missing)).join(", ")}. ${missing.some((m) => m.includes("input.")) ? "Pass the value via run_workflow inputs." : "A previous step produced no asset URL."}`
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
const parsed = skill.inputZod.safeParse(resolved);
|
|
1237
|
+
if (!parsed.success) {
|
|
1238
|
+
const issue = parsed.error.issues[0];
|
|
1239
|
+
return {
|
|
1240
|
+
kind: "text",
|
|
1241
|
+
text: `Step ${i + 1} (${step.skill}) has invalid args: ${issue?.path.join(".") || "input"} ${issue?.message || "invalid"}.`
|
|
1242
|
+
};
|
|
1243
|
+
}
|
|
1244
|
+
const result = await skill.run(parsed.data, ctx);
|
|
1245
|
+
const url = firstUrl(result);
|
|
1246
|
+
if (url) {
|
|
1247
|
+
prevUrl = url;
|
|
1248
|
+
outputs.push(`step ${i + 1} (${step.skill}): ${url}`);
|
|
1249
|
+
} else if (result.kind === "text" && /fail|error|invalid|unknown/i.test(result.text)) {
|
|
1250
|
+
return {
|
|
1251
|
+
kind: "text",
|
|
1252
|
+
text: `Workflow "${workflow.name}" stopped at step ${i + 1} (${step.skill}): ${result.text}`
|
|
1253
|
+
};
|
|
1254
|
+
} else {
|
|
1255
|
+
outputs.push(`step ${i + 1} (${step.skill}): done (no asset URL)`);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
return {
|
|
1259
|
+
kind: "text",
|
|
1260
|
+
text: `Workflow "${workflow.name}" completed ${workflow.steps.length} step(s):
|
|
1261
|
+
${outputs.join("\n")}`
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
var StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
|
|
1265
|
+
var init_workflows = __esm({
|
|
1266
|
+
"src/skills/workflows.ts"() {
|
|
1267
|
+
StepSchema = zod.z.object({
|
|
1268
|
+
skill: zod.z.string().regex(/^pixeldojo:(generate|edit|character|storyboard|upscale|audio|upload|from_url)$/, {
|
|
1269
|
+
message: "Runnable skills only: generate, edit, character, storyboard, upscale, audio, upload, from_url."
|
|
1270
|
+
}),
|
|
1271
|
+
args: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
1272
|
+
});
|
|
1273
|
+
SaveInputSchema = zod.z.object({
|
|
1274
|
+
name: zod.z.string().regex(/^[a-z0-9][a-z0-9-]{1,40}$/, {
|
|
1275
|
+
message: 'Kebab-case, 2-41 chars, e.g. "product-launch-pack".'
|
|
1276
|
+
}).describe("Workflow handle. Saving to an existing name overwrites it."),
|
|
1277
|
+
description: zod.z.string().max(500).optional(),
|
|
1278
|
+
steps: zod.z.array(StepSchema).min(1).max(8)
|
|
1279
|
+
});
|
|
1280
|
+
RunInputSchema = zod.z.object({
|
|
1281
|
+
name: zod.z.string().describe("Saved workflow name."),
|
|
1282
|
+
inputs: zod.z.record(zod.z.string(), zod.z.string()).optional().describe("Values for {{input.<key>}} placeholders in the workflow steps.")
|
|
1283
|
+
});
|
|
1284
|
+
ListInputSchema = zod.z.object({});
|
|
1285
|
+
stepJson = {
|
|
1286
|
+
type: "object",
|
|
1287
|
+
properties: {
|
|
1288
|
+
skill: { type: "string" },
|
|
1289
|
+
args: { type: "object" }
|
|
1290
|
+
},
|
|
1291
|
+
required: ["skill"]
|
|
1292
|
+
};
|
|
1293
|
+
saveWorkflowSkill = {
|
|
1294
|
+
name: "pixeldojo:save_workflow",
|
|
1295
|
+
description: "Save a named multi-step skill chain (generate \u2192 edit \u2192 upscale \u2026). String args may contain {{input.<key>}} and {{prev}} placeholders. Saving to an existing name overwrites it.",
|
|
1296
|
+
inputZod: SaveInputSchema,
|
|
1297
|
+
inputJsonSchema: {
|
|
1298
|
+
type: "object",
|
|
1299
|
+
properties: {
|
|
1300
|
+
name: { type: "string", pattern: "^[a-z0-9][a-z0-9-]{1,40}$" },
|
|
1301
|
+
description: { type: "string" },
|
|
1302
|
+
steps: { type: "array", items: stepJson, minItems: 1, maxItems: 8 }
|
|
1303
|
+
},
|
|
1304
|
+
required: ["name", "steps"]
|
|
1305
|
+
},
|
|
1306
|
+
allowedModels: [],
|
|
1307
|
+
defaultModel: "",
|
|
1308
|
+
run: runSave
|
|
1309
|
+
};
|
|
1310
|
+
runWorkflowSkill = {
|
|
1311
|
+
name: "pixeldojo:run_workflow",
|
|
1312
|
+
description: "Run a saved workflow by name. Pass inputs for its {{input.<key>}} placeholders; each step feeds the next via {{prev}}.",
|
|
1313
|
+
inputZod: RunInputSchema,
|
|
1314
|
+
inputJsonSchema: {
|
|
1315
|
+
type: "object",
|
|
1316
|
+
properties: {
|
|
1317
|
+
name: { type: "string" },
|
|
1318
|
+
inputs: { type: "object", additionalProperties: { type: "string" } }
|
|
1319
|
+
},
|
|
1320
|
+
required: ["name"]
|
|
1321
|
+
},
|
|
1322
|
+
allowedModels: [],
|
|
1323
|
+
defaultModel: "",
|
|
1324
|
+
run: runWorkflow
|
|
1325
|
+
};
|
|
1326
|
+
listWorkflowsSkill = {
|
|
1327
|
+
name: "pixeldojo:list_workflows",
|
|
1328
|
+
description: "List your saved workflows with step counts and run totals.",
|
|
1329
|
+
inputZod: ListInputSchema,
|
|
1330
|
+
inputJsonSchema: { type: "object", properties: {}, required: [] },
|
|
1331
|
+
allowedModels: [],
|
|
1332
|
+
defaultModel: "",
|
|
1333
|
+
run: runList
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
});
|
|
939
1337
|
|
|
940
1338
|
// src/skills/index.ts
|
|
941
|
-
var
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1339
|
+
var skills_exports = {};
|
|
1340
|
+
__export(skills_exports, {
|
|
1341
|
+
ALL_SKILLS: () => exports.ALL_SKILLS,
|
|
1342
|
+
audioSkill: () => audioSkill,
|
|
1343
|
+
campaignSkill: () => campaignSkill,
|
|
1344
|
+
campaignStatusSkill: () => campaignStatusSkill,
|
|
1345
|
+
characterSkill: () => characterSkill,
|
|
1346
|
+
editSkill: () => editSkill,
|
|
1347
|
+
findSkill: () => findSkill,
|
|
1348
|
+
fromUrlSkill: () => fromUrlSkill,
|
|
1349
|
+
generateSkill: () => generateSkill,
|
|
1350
|
+
librarySkill: () => librarySkill,
|
|
1351
|
+
listWorkflowsSkill: () => listWorkflowsSkill,
|
|
1352
|
+
runWorkflowSkill: () => runWorkflowSkill,
|
|
1353
|
+
saveWorkflowSkill: () => saveWorkflowSkill,
|
|
1354
|
+
statusSkill: () => statusSkill,
|
|
1355
|
+
storyboardSkill: () => storyboardSkill,
|
|
1356
|
+
uploadSkill: () => uploadSkill,
|
|
1357
|
+
upscaleSkill: () => upscaleSkill
|
|
1358
|
+
});
|
|
953
1359
|
function findSkill(name) {
|
|
954
|
-
return ALL_SKILLS.find((s) => s.name === name);
|
|
1360
|
+
return exports.ALL_SKILLS.find((s) => s.name === name);
|
|
955
1361
|
}
|
|
1362
|
+
exports.ALL_SKILLS = void 0;
|
|
1363
|
+
var init_skills = __esm({
|
|
1364
|
+
"src/skills/index.ts"() {
|
|
1365
|
+
init_generate();
|
|
1366
|
+
init_edit();
|
|
1367
|
+
init_character();
|
|
1368
|
+
init_storyboard();
|
|
1369
|
+
init_upscale();
|
|
1370
|
+
init_status();
|
|
1371
|
+
init_from_url();
|
|
1372
|
+
init_campaign();
|
|
1373
|
+
init_campaign_status();
|
|
1374
|
+
init_upload();
|
|
1375
|
+
init_audio();
|
|
1376
|
+
init_library();
|
|
1377
|
+
init_workflows();
|
|
1378
|
+
exports.ALL_SKILLS = [
|
|
1379
|
+
generateSkill,
|
|
1380
|
+
editSkill,
|
|
1381
|
+
characterSkill,
|
|
1382
|
+
storyboardSkill,
|
|
1383
|
+
upscaleSkill,
|
|
1384
|
+
audioSkill,
|
|
1385
|
+
librarySkill,
|
|
1386
|
+
saveWorkflowSkill,
|
|
1387
|
+
runWorkflowSkill,
|
|
1388
|
+
listWorkflowsSkill,
|
|
1389
|
+
statusSkill,
|
|
1390
|
+
fromUrlSkill,
|
|
1391
|
+
uploadSkill,
|
|
1392
|
+
campaignSkill,
|
|
1393
|
+
campaignStatusSkill
|
|
1394
|
+
];
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
function makeAttributedClient(options) {
|
|
1398
|
+
const { mcpVersion, skillName, baseFetch, ...sdkOptions } = options;
|
|
1399
|
+
const real = baseFetch ?? globalThis.fetch.bind(globalThis);
|
|
1400
|
+
const wrappedFetch = (input, init) => {
|
|
1401
|
+
const headers = new Headers(init?.headers);
|
|
1402
|
+
headers.set("x-pixeldojo-source", `mcp/${mcpVersion}`);
|
|
1403
|
+
if (skillName) headers.set("x-pixeldojo-skill", skillName);
|
|
1404
|
+
return real(input, { ...init, headers });
|
|
1405
|
+
};
|
|
1406
|
+
return new sdk.PixelDojoClient({
|
|
1407
|
+
...sdkOptions,
|
|
1408
|
+
fetch: wrappedFetch
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
// src/server.ts
|
|
1413
|
+
init_skills();
|
|
956
1414
|
|
|
957
1415
|
// src/redact.ts
|
|
958
1416
|
var PD_KEY_RE = /pd_[A-Za-z0-9_-]{8,}/g;
|
|
@@ -1010,7 +1468,7 @@ function buildServer(options) {
|
|
|
1010
1468
|
);
|
|
1011
1469
|
server.setRequestHandler(types_js.ListToolsRequestSchema, async () => {
|
|
1012
1470
|
return {
|
|
1013
|
-
tools: ALL_SKILLS.map((skill) => ({
|
|
1471
|
+
tools: exports.ALL_SKILLS.map((skill) => ({
|
|
1014
1472
|
name: skill.name,
|
|
1015
1473
|
description: skill.description,
|
|
1016
1474
|
inputSchema: skill.inputJsonSchema
|
|
@@ -1021,7 +1479,7 @@ function buildServer(options) {
|
|
|
1021
1479
|
const skillName = req.params.name;
|
|
1022
1480
|
const skill = findSkill(skillName);
|
|
1023
1481
|
if (!skill) {
|
|
1024
|
-
const available = ALL_SKILLS.map((s) => s.name).join(", ");
|
|
1482
|
+
const available = exports.ALL_SKILLS.map((s) => s.name).join(", ");
|
|
1025
1483
|
return {
|
|
1026
1484
|
isError: true,
|
|
1027
1485
|
content: [
|
|
@@ -1122,9 +1580,13 @@ async function runStdio(options) {
|
|
|
1122
1580
|
await server.connect(transport);
|
|
1123
1581
|
}
|
|
1124
1582
|
|
|
1125
|
-
|
|
1583
|
+
// src/index.ts
|
|
1584
|
+
init_skills();
|
|
1585
|
+
init_poll();
|
|
1586
|
+
|
|
1126
1587
|
exports.PACKAGE_VERSION = PACKAGE_VERSION;
|
|
1127
1588
|
exports.buildServer = buildServer;
|
|
1589
|
+
exports.errorToActionableMessage = errorToActionableMessage;
|
|
1128
1590
|
exports.findSkill = findSkill;
|
|
1129
1591
|
exports.makeAttributedClient = makeAttributedClient;
|
|
1130
1592
|
exports.makeRedactedLogger = makeRedactedLogger;
|
|
@@ -1132,5 +1594,6 @@ exports.pollJobUntilDoneOrHandoff = pollJobUntilDoneOrHandoff;
|
|
|
1132
1594
|
exports.redactKeys = redactKeys;
|
|
1133
1595
|
exports.redactValue = redactValue;
|
|
1134
1596
|
exports.runStdio = runStdio;
|
|
1597
|
+
exports.skillResultToMcpResponse = skillResultToMcpResponse;
|
|
1135
1598
|
//# sourceMappingURL=index.cjs.map
|
|
1136
1599
|
//# sourceMappingURL=index.cjs.map
|