@pixeldojo/mcp 0.11.0 → 0.13.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/README.md +4 -5
- package/dist/cli.cjs +315 -185
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +315 -185
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +317 -184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +316 -185
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -113,7 +113,8 @@ var init_types = __esm({
|
|
|
113
113
|
"src/skills/types.ts"() {
|
|
114
114
|
}
|
|
115
115
|
});
|
|
116
|
-
async function uploadLocalFile(path$1,
|
|
116
|
+
async function uploadLocalFile(path$1, ctx) {
|
|
117
|
+
if (ctx.localFiles !== true) throw new SkillUploadError(HOSTED_LOCAL_PATH_MESSAGE);
|
|
117
118
|
const ext = path.extname(path$1).toLowerCase();
|
|
118
119
|
const mime = EXT_TO_MIME[ext];
|
|
119
120
|
if (!mime) {
|
|
@@ -152,13 +153,13 @@ async function uploadLocalFile(path$1, client) {
|
|
|
152
153
|
const buffer = await promises.readFile(path$1);
|
|
153
154
|
const blob = new Blob([new Uint8Array(buffer)], { type: mime });
|
|
154
155
|
const filename = path.basename(path$1);
|
|
155
|
-
const response = await client.uploadImage(blob, filename);
|
|
156
|
+
const response = await ctx.client.uploadImage(blob, filename);
|
|
156
157
|
return response.url;
|
|
157
158
|
}
|
|
158
|
-
async function uploadLocalFiles(paths,
|
|
159
|
-
return Promise.all(paths.map((p) => uploadLocalFile(p,
|
|
159
|
+
async function uploadLocalFiles(paths, ctx) {
|
|
160
|
+
return Promise.all(paths.map((p) => uploadLocalFile(p, ctx)));
|
|
160
161
|
}
|
|
161
|
-
var MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, EXT_TO_MIME, SkillUploadError;
|
|
162
|
+
var MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, EXT_TO_MIME, SkillUploadError, HOSTED_LOCAL_PATH_MESSAGE;
|
|
162
163
|
var init_upload_helpers = __esm({
|
|
163
164
|
"src/skills/upload-helpers.ts"() {
|
|
164
165
|
MAX_IMAGE_BYTES = 50 * 1024 * 1024;
|
|
@@ -181,6 +182,7 @@ var init_upload_helpers = __esm({
|
|
|
181
182
|
}
|
|
182
183
|
userMessage;
|
|
183
184
|
};
|
|
185
|
+
HOSTED_LOCAL_PATH_MESSAGE = "Local file paths are not available on the hosted PixelDojo MCP server (it cannot see your disk). Pass a public http(s) URL instead (image_url / image_urls / video_url / audio_urls / product_image_urls), or install the local server (npx @pixeldojo/mcp init) to use files on your machine.";
|
|
184
186
|
}
|
|
185
187
|
});
|
|
186
188
|
|
|
@@ -452,10 +454,10 @@ async function run(input, ctx) {
|
|
|
452
454
|
let resolved = input;
|
|
453
455
|
let referenceUrls = [];
|
|
454
456
|
try {
|
|
455
|
-
const singleUrl = input.image_url ?? (input.image_path ? await uploadLocalFile(input.image_path, ctx
|
|
457
|
+
const singleUrl = input.image_url ?? (input.image_path ? await uploadLocalFile(input.image_path, ctx) : void 0);
|
|
456
458
|
const manyUrls = [...input.image_urls ?? []];
|
|
457
459
|
for (const p of input.image_paths ?? []) {
|
|
458
|
-
manyUrls.push(await uploadLocalFile(p, ctx
|
|
460
|
+
manyUrls.push(await uploadLocalFile(p, ctx));
|
|
459
461
|
}
|
|
460
462
|
referenceUrls = [...singleUrl ? [singleUrl] : [], ...manyUrls].filter(
|
|
461
463
|
(u, i, all) => all.indexOf(u) === i
|
|
@@ -540,19 +542,19 @@ var init_generate = __esm({
|
|
|
540
542
|
InputSchema = zod.z.object({
|
|
541
543
|
prompt: zod.z.string().min(1).max(8e3).describe("Prompt describing what to generate."),
|
|
542
544
|
model: zod.z.string().optional().describe(
|
|
543
|
-
|
|
545
|
+
`Model apiId, e.g. "flux", "google-nano-banana", "veo-3.1-fast", "kling-video-v3-standard-text". Full catalog: https://pixeldojo.ai/api/v1/models; one model's fields: https://pixeldojo.ai/llm/{apiId}.txt. Omit for google-nano-banana, which makes still images only; name a video model to get a video.`
|
|
544
546
|
),
|
|
545
547
|
preset: zod.z.string().optional().describe(
|
|
546
|
-
|
|
548
|
+
"Preset slug that seeds the running model's settings; explicit fields and params override it. Each preset belongs to one model (browse them by model at https://pixeldojo.ai/presets), so set `model` to that preset's model: a slug the running model has no preset for is rejected with a 400 before any charge."
|
|
547
549
|
),
|
|
548
|
-
aspect_ratio: zod.z.string().optional().describe('
|
|
549
|
-
duration: zod.z.number().int().positive().optional().describe("Video
|
|
550
|
+
aspect_ratio: zod.z.string().optional().describe('e.g. "1:1", "16:9", "9:16". Snapped to the nearest ratio the model supports, and dropped if the model has no aspect_ratio field.'),
|
|
551
|
+
duration: zod.z.number().int().positive().optional().describe("Video length in seconds. Snapped or clamped to what the model allows, and dropped if the model has no duration field. Required for grok-video-extend (the extension length)."),
|
|
550
552
|
resolution: zod.z.string().optional().describe(
|
|
551
553
|
'Output resolution when the model supports it (e.g. "480p", "720p", "1080p", "4k"). Lower tiers cost fewer credits. Omit to use the model default.'
|
|
552
554
|
),
|
|
553
|
-
image_url: zod.z.string().url().optional().describe("Reference
|
|
555
|
+
image_url: zod.z.string().url().optional().describe("Reference still for image-to-image / image-to-video. A clip URL (.mp4/.mov/.webm) or an audio track URL (.mp3/.wav/.m4a/...) here is detected by extension and routed as that kind of media instead."),
|
|
554
556
|
video_url: zod.z.string().url().optional().describe(
|
|
555
|
-
"Source video clip to animate / restyle / extend. Use this for videos; image_url is for still frames.
|
|
557
|
+
"Source video clip to animate / restyle / extend. Use this for videos; image_url is for still frames. With no model, a clip runs on seedance-2-reference; a named model with no clip input is swapped for it and the result says so."
|
|
556
558
|
),
|
|
557
559
|
params: ParamsInput,
|
|
558
560
|
image_path: zod.z.string().min(1).optional().describe(
|
|
@@ -579,45 +581,56 @@ var init_generate = __esm({
|
|
|
579
581
|
prompt: { type: "string", description: "Prompt describing what to generate." },
|
|
580
582
|
model: {
|
|
581
583
|
type: "string",
|
|
582
|
-
description:
|
|
584
|
+
description: `Model apiId, e.g. "flux", "google-nano-banana", "veo-3.1-fast", "kling-video-v3-standard-text". Full catalog: https://pixeldojo.ai/api/v1/models; one model's fields: https://pixeldojo.ai/llm/{apiId}.txt. Omit for google-nano-banana, which makes still images only; name a video model to get a video.`
|
|
583
585
|
},
|
|
584
586
|
preset: {
|
|
585
587
|
type: "string",
|
|
586
|
-
description:
|
|
588
|
+
description: "Preset slug that seeds the running model's settings; explicit fields and params override it. Each preset belongs to one model (browse them by model at https://pixeldojo.ai/presets), so set `model` to that preset's model: a slug the running model has no preset for is rejected with a 400 before any charge."
|
|
589
|
+
},
|
|
590
|
+
aspect_ratio: {
|
|
591
|
+
type: "string",
|
|
592
|
+
description: 'e.g. "1:1", "16:9", "9:16". Snapped to the nearest ratio the model supports, and dropped if the model has no aspect_ratio field.'
|
|
593
|
+
},
|
|
594
|
+
duration: {
|
|
595
|
+
type: "integer",
|
|
596
|
+
description: "Video length in seconds. Snapped or clamped to what the model allows, and dropped if the model has no duration field. Required for grok-video-extend (the extension length)."
|
|
587
597
|
},
|
|
588
|
-
aspect_ratio: { type: "string" },
|
|
589
|
-
duration: { type: "integer" },
|
|
590
598
|
resolution: {
|
|
591
599
|
type: "string",
|
|
592
|
-
description: 'Output resolution when
|
|
600
|
+
description: 'Output resolution when the model supports it (e.g. "480p", "720p", "1080p", "4k"). Snapped to the nearest tier the model offers, and dropped if the model has no resolution field. Lower tiers cost fewer credits.'
|
|
601
|
+
},
|
|
602
|
+
image_url: {
|
|
603
|
+
type: "string",
|
|
604
|
+
format: "uri",
|
|
605
|
+
description: "Reference still for image-to-image / image-to-video. A clip URL (.mp4/.mov/.webm) or an audio track URL (.mp3/.wav/.m4a/...) here is detected by extension and routed as that kind of media instead."
|
|
593
606
|
},
|
|
594
|
-
image_url: { type: "string", format: "uri" },
|
|
595
607
|
video_url: {
|
|
596
608
|
type: "string",
|
|
597
609
|
format: "uri",
|
|
598
|
-
description: "Source video clip to animate / restyle / extend. Use this for videos; image_url is for still frames."
|
|
610
|
+
description: "Source video clip to animate / restyle / extend. Use this for videos; image_url is for still frames. With no model, a clip runs on seedance-2-reference; a named model with no clip input is swapped for it and the result says so."
|
|
599
611
|
},
|
|
600
612
|
params: PARAMS_JSON_SCHEMA,
|
|
601
613
|
image_urls: {
|
|
602
614
|
type: "array",
|
|
603
615
|
items: { type: "string", format: "uri" },
|
|
604
|
-
description: "Multiple reference image URLs for models that accept a reference set. Single-reference models use the first."
|
|
616
|
+
description: "Multiple reference image URLs for models that accept a reference set (character + wardrobe + location, for example). Single-reference models use the first and ignore the rest."
|
|
605
617
|
},
|
|
606
618
|
image_paths: {
|
|
607
619
|
type: "array",
|
|
608
620
|
items: { type: "string" },
|
|
609
|
-
description: "Multiple absolute local file paths, each uploaded to 24h temp storage and used as a reference."
|
|
621
|
+
description: "Multiple absolute local file paths (JPEG, PNG, WebP, GIF, MP4, WebM, MOV), each uploaded to 24h temp storage and used as a reference, same rules as image_urls."
|
|
610
622
|
},
|
|
611
623
|
image_path: {
|
|
612
624
|
type: "string",
|
|
613
|
-
description: "Absolute local file path. The skill uploads it to
|
|
625
|
+
description: "Absolute local file path to a reference image or clip (JPEG, PNG, WebP, GIF, MP4, WebM, MOV; no audio). The skill uploads it to 24h temp storage and uses the URL as image_url. Ignored when image_url is also set."
|
|
614
626
|
}
|
|
615
627
|
},
|
|
616
628
|
required: ["prompt"]
|
|
617
629
|
};
|
|
618
630
|
generateSkill = {
|
|
619
631
|
name: "pixeldojo_generate",
|
|
620
|
-
description: "Generate
|
|
632
|
+
description: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a text prompt runs on google-nano-banana, which makes still images only; for a video, name a video model such as veo-3.1-fast. References: `image_url`/`image_urls` for stills, `video_url` for a source clip, `image_path`/`image_paths` for absolute local files (uploaded to 24h temp storage first). A clip or an audio track URL with no `model` runs on seedance-2-reference; a named model that cannot read a clip is swapped for it and the result says so, while a named model with no audio input drops the track. Model-specific settings go in `params` alongside an explicit `model`. Returns asset URLs, or a jobId for pixeldojo_status when the job outlasts the 30s wait.",
|
|
633
|
+
hostedDescription: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a text prompt runs on google-nano-banana, which makes still images only; for a video, name a video model such as veo-3.1-fast. References: `image_url`/`image_urls` for stills and `video_url` for a source clip, all public http(s) URLs. A clip or an audio track URL with no `model` runs on seedance-2-reference; a named model that cannot read a clip is swapped for it and the result says so, while a named model with no audio input drops the track. Model-specific settings go in `params` alongside an explicit `model`. Returns asset URLs, or a jobId for pixeldojo_status when the job outlasts the 30s wait.",
|
|
621
634
|
inputZod: InputSchema,
|
|
622
635
|
inputJsonSchema: InputJsonSchema,
|
|
623
636
|
allowedModels: null,
|
|
@@ -693,13 +706,13 @@ async function run2(input, ctx) {
|
|
|
693
706
|
let resolved = input;
|
|
694
707
|
try {
|
|
695
708
|
if (input.image_paths && input.image_paths.length > 0) {
|
|
696
|
-
const urls = await uploadLocalFiles(input.image_paths, ctx
|
|
709
|
+
const urls = await uploadLocalFiles(input.image_paths, ctx);
|
|
697
710
|
resolved = {
|
|
698
711
|
...input,
|
|
699
712
|
image_urls: [...input.image_urls ?? [], ...urls]
|
|
700
713
|
};
|
|
701
714
|
} else if (input.image_path && !input.image_url) {
|
|
702
|
-
const url = await uploadLocalFile(input.image_path, ctx
|
|
715
|
+
const url = await uploadLocalFile(input.image_path, ctx);
|
|
703
716
|
resolved = { ...input, image_url: url };
|
|
704
717
|
}
|
|
705
718
|
} catch (err) {
|
|
@@ -781,32 +794,35 @@ var init_edit = __esm({
|
|
|
781
794
|
image_url: {
|
|
782
795
|
type: "string",
|
|
783
796
|
format: "uri",
|
|
784
|
-
description: "Single
|
|
797
|
+
description: "Single image to edit. Ignored when image_urls is set; pass image_urls for multi-image edits."
|
|
785
798
|
},
|
|
786
799
|
image_urls: {
|
|
787
800
|
type: "array",
|
|
788
801
|
items: { type: "string", format: "uri" },
|
|
789
802
|
minItems: 1,
|
|
790
803
|
maxItems: 9,
|
|
791
|
-
description: "Multiple reference images (1-9)."
|
|
804
|
+
description: "Multiple reference images (1-9), most important first. Models that take fewer keep the first ones and the result says how many were dropped."
|
|
792
805
|
},
|
|
793
806
|
image_path: {
|
|
794
807
|
type: "string",
|
|
795
|
-
description: "Absolute local
|
|
808
|
+
description: "Absolute local image path (JPEG, PNG, WebP, GIF). Skill uploads it (24h temp storage) and edits the resulting URL. Ignored when image_url or image_paths is set."
|
|
796
809
|
},
|
|
797
810
|
image_paths: {
|
|
798
811
|
type: "array",
|
|
799
812
|
items: { type: "string" },
|
|
800
813
|
minItems: 1,
|
|
801
814
|
maxItems: 9,
|
|
802
|
-
description: "Multiple absolute local
|
|
815
|
+
description: "Multiple absolute local image paths (1-9). Each is uploaded to 24h temp storage and appended after any image_urls."
|
|
803
816
|
},
|
|
804
817
|
model: {
|
|
805
818
|
type: "string",
|
|
806
819
|
enum: [...ALLOWED_MODELS],
|
|
807
820
|
description: "Override edit model. Default: wan-2.7-image-edit."
|
|
808
821
|
},
|
|
809
|
-
aspect_ratio: {
|
|
822
|
+
aspect_ratio: {
|
|
823
|
+
type: "string",
|
|
824
|
+
description: 'Output aspect ratio, e.g. "1:1", "16:9", "match_input_image". Snapped to the nearest ratio the model supports, and dropped if the model has no aspect_ratio field.'
|
|
825
|
+
},
|
|
810
826
|
params: PARAMS_JSON_SCHEMA
|
|
811
827
|
},
|
|
812
828
|
required: ["prompt"]
|
|
@@ -814,6 +830,7 @@ var init_edit = __esm({
|
|
|
814
830
|
editSkill = {
|
|
815
831
|
name: "pixeldojo_edit",
|
|
816
832
|
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).",
|
|
833
|
+
hostedDescription: "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. Pass reference images as public http(s) URLs via image_url or image_urls.",
|
|
817
834
|
inputZod: InputSchema2,
|
|
818
835
|
inputJsonSchema: InputJsonSchema2,
|
|
819
836
|
allowedModels: [...ALLOWED_MODELS],
|
|
@@ -924,7 +941,7 @@ var init_character = __esm({
|
|
|
924
941
|
InputJsonSchema3 = {
|
|
925
942
|
type: "object",
|
|
926
943
|
properties: {
|
|
927
|
-
prompt: { type: "string" },
|
|
944
|
+
prompt: { type: "string", description: "The shot to render: scene, pose, wardrobe, framing. The references supply the identity." },
|
|
928
945
|
model: {
|
|
929
946
|
type: "string",
|
|
930
947
|
enum: ALLOWED,
|
|
@@ -933,16 +950,19 @@ var init_character = __esm({
|
|
|
933
950
|
reference_image_url: {
|
|
934
951
|
type: "string",
|
|
935
952
|
format: "uri",
|
|
936
|
-
description: "Single
|
|
953
|
+
description: "Single still of the character. Ignored when reference_image_urls is set; prefer that, since more angles lock the face better."
|
|
937
954
|
},
|
|
938
955
|
reference_image_urls: {
|
|
939
956
|
type: "array",
|
|
940
957
|
items: { type: "string", format: "uri" },
|
|
941
958
|
minItems: 1,
|
|
942
959
|
maxItems: MAX_REFERENCES,
|
|
943
|
-
description: "All
|
|
960
|
+
description: "All reference stills for this shot (1-9), most important first. Multiple angles of the same person lock the face far better than one photo. Models that take fewer keep the first ones and the result says how many were dropped. Required for wan-2.7-image-edit; clips and audio are refused."
|
|
961
|
+
},
|
|
962
|
+
aspect_ratio: {
|
|
963
|
+
type: "string",
|
|
964
|
+
description: 'e.g. "1:1", "16:9", "9:16". Snapped to the nearest ratio the model supports, and dropped for models with no aspect_ratio field (including the default seedream-5, which sizes by image_size: set that in params with an explicit model).'
|
|
944
965
|
},
|
|
945
|
-
aspect_ratio: { type: "string" },
|
|
946
966
|
params: PARAMS_JSON_SCHEMA
|
|
947
967
|
},
|
|
948
968
|
required: ["prompt"]
|
|
@@ -1039,24 +1059,30 @@ var init_storyboard = __esm({
|
|
|
1039
1059
|
properties: {
|
|
1040
1060
|
brief: {
|
|
1041
1061
|
type: "string",
|
|
1042
|
-
description: "
|
|
1062
|
+
description: "Scene brief: setting, action, camera, mood. Sent to the video model as its prompt."
|
|
1043
1063
|
},
|
|
1044
1064
|
model: {
|
|
1045
1065
|
type: "string",
|
|
1046
1066
|
enum: ALLOWED2,
|
|
1047
|
-
description: `One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}.`
|
|
1067
|
+
description: `One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}, or ${VIDEO_REFERENCE_MODEL} when image_url or video_url is given.`
|
|
1068
|
+
},
|
|
1069
|
+
aspect_ratio: {
|
|
1070
|
+
type: "string",
|
|
1071
|
+
description: 'e.g. "16:9", "9:16", "1:1". Snapped to the nearest ratio the model supports, and dropped if the model has no aspect_ratio field.'
|
|
1072
|
+
},
|
|
1073
|
+
duration: {
|
|
1074
|
+
type: "integer",
|
|
1075
|
+
description: "Clip length in seconds. Snapped or clamped to what the model allows."
|
|
1048
1076
|
},
|
|
1049
|
-
aspect_ratio: { type: "string" },
|
|
1050
|
-
duration: { type: "integer" },
|
|
1051
1077
|
image_url: {
|
|
1052
1078
|
type: "string",
|
|
1053
1079
|
format: "uri",
|
|
1054
|
-
description: "Reference still to build the shot from."
|
|
1080
|
+
description: "Reference still to build the shot from (character, product, location). A clip or audio URL here is detected by extension and routed as that kind of media."
|
|
1055
1081
|
},
|
|
1056
1082
|
video_url: {
|
|
1057
1083
|
type: "string",
|
|
1058
1084
|
format: "uri",
|
|
1059
|
-
description: "Source clip to work from. Use this for videos; image_url is for stills."
|
|
1085
|
+
description: "Source clip to work from. Use this for videos; image_url is for stills. A named model with no clip input is swapped for seedance-2-reference and the result says so."
|
|
1060
1086
|
},
|
|
1061
1087
|
params: PARAMS_JSON_SCHEMA
|
|
1062
1088
|
},
|
|
@@ -1064,7 +1090,7 @@ var init_storyboard = __esm({
|
|
|
1064
1090
|
};
|
|
1065
1091
|
storyboardSkill = {
|
|
1066
1092
|
name: "pixeldojo_storyboard",
|
|
1067
|
-
description: "Generate
|
|
1093
|
+
description: "Generate one short video clip (a single shot, not a multi-panel storyboard) from a scene brief. A text-only brief runs on veo-3.1-fast unless `model` names another allowed video model. With image_url (reference still) or video_url (source clip) and no `model`, it runs on seedance-2-reference, with the same reference routing as pixeldojo_generate. For a multi-shot film with dialogue and a soundtrack, use pixeldojo_film.",
|
|
1068
1094
|
inputZod: InputSchema4,
|
|
1069
1095
|
inputJsonSchema: InputJsonSchema4,
|
|
1070
1096
|
allowedModels: [...ALLOWED2],
|
|
@@ -1161,20 +1187,42 @@ var init_upscale = __esm({
|
|
|
1161
1187
|
InputJsonSchema5 = {
|
|
1162
1188
|
type: "object",
|
|
1163
1189
|
properties: {
|
|
1164
|
-
image_url: {
|
|
1190
|
+
image_url: {
|
|
1191
|
+
type: "string",
|
|
1192
|
+
format: "uri",
|
|
1193
|
+
description: "Source image to upscale (image models). A clip URL here (.mp4/.mov/.webm) is treated as video_url."
|
|
1194
|
+
},
|
|
1165
1195
|
video_url: {
|
|
1166
1196
|
type: "string",
|
|
1167
1197
|
format: "uri",
|
|
1168
|
-
description: "Source video clip
|
|
1198
|
+
description: "Source video clip (MP4, max 500 MB). Routes to video-upscaler when no model is named; needs video_duration."
|
|
1199
|
+
},
|
|
1200
|
+
model: {
|
|
1201
|
+
type: "string",
|
|
1202
|
+
enum: ALLOWED3,
|
|
1203
|
+
description: `Defaults to ${DEFAULT_MODEL5}, or ${VIDEO_MODEL} when the source is a clip. face-enhance is for portraits.`
|
|
1204
|
+
},
|
|
1205
|
+
scale_factor: {
|
|
1206
|
+
type: "number",
|
|
1207
|
+
minimum: 1,
|
|
1208
|
+
maximum: 16,
|
|
1209
|
+
description: "Image models only. magnific-upscaler snaps to the nearest of 2/4/8/16 (default 2); creative-upscale clamps to 1-10 (default 2); face-enhance clamps to 1-8 (default 4)."
|
|
1210
|
+
},
|
|
1211
|
+
creativity: {
|
|
1212
|
+
type: "number",
|
|
1213
|
+
minimum: 0,
|
|
1214
|
+
maximum: 1,
|
|
1215
|
+
description: "magnific-upscaler only: sent unchanged as its creativity setting (default 0 = preserve the source; higher invents more detail). This tool accepts 0-1."
|
|
1169
1216
|
},
|
|
1170
|
-
model: { type: "string", enum: ALLOWED3 },
|
|
1171
|
-
scale_factor: { type: "number", minimum: 1, maximum: 16 },
|
|
1172
|
-
creativity: { type: "number", minimum: 0, maximum: 1 },
|
|
1173
1217
|
video_duration: {
|
|
1174
1218
|
type: "number",
|
|
1175
|
-
description: "video-upscaler only, required there: source clip length in seconds."
|
|
1219
|
+
description: "video-upscaler only, required there: source clip length in seconds. It sets the cost (1 credit per second)."
|
|
1176
1220
|
},
|
|
1177
|
-
target_resolution: {
|
|
1221
|
+
target_resolution: {
|
|
1222
|
+
type: "string",
|
|
1223
|
+
enum: VIDEO_RESOLUTIONS,
|
|
1224
|
+
description: "video-upscaler only: output resolution. Defaults to 1080p."
|
|
1225
|
+
}
|
|
1178
1226
|
}
|
|
1179
1227
|
};
|
|
1180
1228
|
upscaleSkill = {
|
|
@@ -1263,7 +1311,7 @@ var init_status = __esm({
|
|
|
1263
1311
|
properties: {
|
|
1264
1312
|
jobId: {
|
|
1265
1313
|
type: "string",
|
|
1266
|
-
description: "
|
|
1314
|
+
description: "The jobId a generation tool returned instead of an asset (a job_... id)."
|
|
1267
1315
|
}
|
|
1268
1316
|
},
|
|
1269
1317
|
required: ["jobId"]
|
|
@@ -1272,7 +1320,7 @@ var init_status = __esm({
|
|
|
1272
1320
|
ABANDON_HINT_MS = 12 * 60 * 1e3;
|
|
1273
1321
|
statusSkill = {
|
|
1274
1322
|
name: "pixeldojo_status",
|
|
1275
|
-
description:
|
|
1323
|
+
description: 'Check once, without waiting, on a jobId that a generation tool returned instead of an asset after its 30s wait. Free. Returns asset URLs when complete, the failure reason if it failed, or the current state and job age if still running. Campaign ids go to pixeldojo_campaign_status; films report progress through pixeldojo_film with action "status".',
|
|
1276
1324
|
inputZod: InputSchema6,
|
|
1277
1325
|
inputJsonSchema: InputJsonSchema6,
|
|
1278
1326
|
// status is special — it doesn't dispatch to a model
|
|
@@ -1317,7 +1365,7 @@ var init_from_url = __esm({
|
|
|
1317
1365
|
};
|
|
1318
1366
|
fromUrlSkill = {
|
|
1319
1367
|
name: "pixeldojo_from_url",
|
|
1320
|
-
description: "Extract product
|
|
1368
|
+
description: "Extract a product profile from a product page URL: name, description, image URLs (the first three are listed), and the extraction method used. Works on Shopify, BigCommerce, WooCommerce, or any page with JSON-LD / OpenGraph product metadata. Free. pixeldojo_campaign and pixeldojo_ad accept a product URL and run this extraction themselves; call this directly to check the product data first, or to reuse its images in other tools.",
|
|
1321
1369
|
inputZod: InputSchema7,
|
|
1322
1370
|
inputJsonSchema: InputJsonSchema7,
|
|
1323
1371
|
// No model dispatch — this skill calls a server-side scrape, not a generation.
|
|
@@ -1522,20 +1570,31 @@ var init_film = __esm({
|
|
|
1522
1570
|
film_id: zod.z.string().max(40).optional().describe("Existing film id (from a previous call) for produce/status."),
|
|
1523
1571
|
action: zod.z.enum(["plan", "produce", "status"]).default("plan").describe("'plan' creates + storyboards (free). 'produce' starts charged generation. 'status' advances production and reports progress; poll it every ~30s until it returns the finished film."),
|
|
1524
1572
|
soundtrack: zod.z.enum(["scene-synced", "flat", "none"]).default("scene-synced").describe("scene-synced composes one musical section per scene, pinned to the scene lengths (default). flat is a single cohesive bed. none skips music."),
|
|
1525
|
-
music_job_id: zod.z.string().max(80).optional().describe("
|
|
1573
|
+
music_job_id: zod.z.string().max(80).optional().describe("The music_job_id from the previous status reply while the score is composing, so that score is attached. A status call without it, once all clips are ready and no score is attached, starts and charges for a new score.")
|
|
1526
1574
|
});
|
|
1527
1575
|
InputJsonSchema8 = {
|
|
1528
1576
|
type: "object",
|
|
1529
1577
|
properties: {
|
|
1530
|
-
idea: { type: "string", description: "
|
|
1531
|
-
script: { type: "string", description: "
|
|
1532
|
-
look: { type: "string", enum: [...LOOKS], description: "
|
|
1533
|
-
aspect: { type: "string", enum: ["16:9", "9:16"], description: "Default 16:9." },
|
|
1534
|
-
length: { type: "string", enum: ["30s", "60s", "2-3min", "5min"], description: "
|
|
1535
|
-
film_id: { type: "string", description:
|
|
1536
|
-
action: {
|
|
1537
|
-
|
|
1538
|
-
|
|
1578
|
+
idea: { type: "string", description: "Plan step: one-to-three sentence film idea. The studio writes the screenplay (free). Provide idea or script." },
|
|
1579
|
+
script: { type: "string", description: "Plan step: a full screenplay (sluglines, action lines, dialogue) to plan instead of an idea." },
|
|
1580
|
+
look: { type: "string", enum: [...LOOKS], description: "Plan step: visual style carried through frames, clips and soundtrack. Default live-action." },
|
|
1581
|
+
aspect: { type: "string", enum: ["16:9", "9:16"], description: "Plan step: frame aspect ratio. Default 16:9." },
|
|
1582
|
+
length: { type: "string", enum: ["30s", "60s", "2-3min", "5min"], description: "Plan step: target length, which sets the shot count (~6/12/24/60 shots). Default 60s." },
|
|
1583
|
+
film_id: { type: "string", description: 'The film_id returned by the plan step. Required for produce and status; with it, action "plan" is treated as "status".' },
|
|
1584
|
+
action: {
|
|
1585
|
+
type: "string",
|
|
1586
|
+
enum: ["plan", "produce", "status"],
|
|
1587
|
+
description: "plan (default, free): writes the script and plans shots, returns film_id and a cost estimate. produce (charged): starts rendering frames. status: advances production one step and reports progress; call it every ~30s until it returns the finished film URL."
|
|
1588
|
+
},
|
|
1589
|
+
soundtrack: {
|
|
1590
|
+
type: "string",
|
|
1591
|
+
enum: ["scene-synced", "flat", "none"],
|
|
1592
|
+
description: "Read on status calls once all clips are ready. scene-synced (default): one musical section per scene. flat: one cohesive bed. none: export without music."
|
|
1593
|
+
},
|
|
1594
|
+
music_job_id: {
|
|
1595
|
+
type: "string",
|
|
1596
|
+
description: "The music_job_id from the previous status reply while the score is composing. A status call without it, once all clips are ready and no score is attached, starts and charges for a new score."
|
|
1597
|
+
}
|
|
1539
1598
|
}
|
|
1540
1599
|
};
|
|
1541
1600
|
shots = (f) => f.scenes.flatMap((s) => s.shots);
|
|
@@ -1572,11 +1631,11 @@ var init_film = __esm({
|
|
|
1572
1631
|
async function run9(input, ctx) {
|
|
1573
1632
|
const productImages = [
|
|
1574
1633
|
...input.product_image_urls ?? [],
|
|
1575
|
-
...await Promise.all((input.product_image_paths ?? []).map((p) => uploadLocalFile(p, ctx
|
|
1634
|
+
...await Promise.all((input.product_image_paths ?? []).map((p) => uploadLocalFile(p, ctx)))
|
|
1576
1635
|
];
|
|
1577
1636
|
const characterImages = [
|
|
1578
1637
|
...input.character_image_urls ?? [],
|
|
1579
|
-
...await Promise.all((input.character_image_paths ?? []).map((p) => uploadLocalFile(p, ctx
|
|
1638
|
+
...await Promise.all((input.character_image_paths ?? []).map((p) => uploadLocalFile(p, ctx)))
|
|
1580
1639
|
];
|
|
1581
1640
|
const body = {
|
|
1582
1641
|
style: input.style,
|
|
@@ -1654,16 +1713,24 @@ var init_ad = __esm({
|
|
|
1654
1713
|
product_url: {
|
|
1655
1714
|
type: "string",
|
|
1656
1715
|
format: "uri",
|
|
1657
|
-
description: "Product page URL. Name, description, and images are extracted automatically."
|
|
1716
|
+
description: "Product page URL. Name, description, and images are extracted automatically. Pass this, or product_name plus product images; when set, the product_* fields are ignored."
|
|
1717
|
+
},
|
|
1718
|
+
product_name: {
|
|
1719
|
+
type: "string",
|
|
1720
|
+
description: "Product name. Required with product_image_urls / product_image_paths when there is no product_url."
|
|
1721
|
+
},
|
|
1722
|
+
product_description: { type: "string", description: "Optional product description (no product_url case)." },
|
|
1723
|
+
product_image_urls: {
|
|
1724
|
+
type: "array",
|
|
1725
|
+
items: { type: "string", format: "uri" },
|
|
1726
|
+
maxItems: 5,
|
|
1727
|
+
description: "Up to 5 hosted product photos (no product_url case)."
|
|
1658
1728
|
},
|
|
1659
|
-
product_name: { type: "string" },
|
|
1660
|
-
product_description: { type: "string" },
|
|
1661
|
-
product_image_urls: { type: "array", items: { type: "string", format: "uri" }, maxItems: 5 },
|
|
1662
1729
|
product_image_paths: {
|
|
1663
1730
|
type: "array",
|
|
1664
1731
|
items: { type: "string" },
|
|
1665
1732
|
maxItems: 5,
|
|
1666
|
-
description: "
|
|
1733
|
+
description: "Up to 5 absolute local product image paths; uploaded to 24h temp storage automatically."
|
|
1667
1734
|
},
|
|
1668
1735
|
character_image_urls: {
|
|
1669
1736
|
type: "array",
|
|
@@ -1671,12 +1738,21 @@ var init_ad = __esm({
|
|
|
1671
1738
|
maxItems: 4,
|
|
1672
1739
|
description: "Presenter reference images for a consistent on-camera character."
|
|
1673
1740
|
},
|
|
1674
|
-
character_image_paths: {
|
|
1741
|
+
character_image_paths: {
|
|
1742
|
+
type: "array",
|
|
1743
|
+
items: { type: "string" },
|
|
1744
|
+
maxItems: 4,
|
|
1745
|
+
description: "Absolute local presenter image paths; uploaded to 24h temp storage automatically."
|
|
1746
|
+
},
|
|
1675
1747
|
location_description: {
|
|
1676
1748
|
type: "string",
|
|
1677
1749
|
description: 'Where the ad takes place ("a sunlit Parisian cafe"). Text is enough.'
|
|
1678
1750
|
},
|
|
1679
|
-
location_image_url: {
|
|
1751
|
+
location_image_url: {
|
|
1752
|
+
type: "string",
|
|
1753
|
+
format: "uri",
|
|
1754
|
+
description: "Optional reference photo of the location."
|
|
1755
|
+
},
|
|
1680
1756
|
hook: {
|
|
1681
1757
|
type: "string",
|
|
1682
1758
|
description: "The opening visual beat (first 1-2 seconds). Omit to use the style default."
|
|
@@ -1685,21 +1761,34 @@ var init_ad = __esm({
|
|
|
1685
1761
|
type: "string",
|
|
1686
1762
|
description: "The exact spoken line, voiced word for word. Omit and the presenter improvises."
|
|
1687
1763
|
},
|
|
1688
|
-
quality: {
|
|
1764
|
+
quality: {
|
|
1765
|
+
type: "string",
|
|
1766
|
+
enum: ["mini", "fast", "high"],
|
|
1767
|
+
description: "Render tier. Omitted or unsupported by the ad engine, the engine's default tier is used."
|
|
1768
|
+
},
|
|
1689
1769
|
resolution: {
|
|
1690
1770
|
type: "string",
|
|
1691
1771
|
enum: ["480p", "720p", "1080p", "4k"],
|
|
1692
|
-
description: '1080p/4k require quality "high".'
|
|
1772
|
+
description: '1080p/4k require quality "high"; without it, or when the engine lacks the value, the engine default resolution is used.'
|
|
1693
1773
|
},
|
|
1694
|
-
aspect_ratio: {
|
|
1695
|
-
|
|
1774
|
+
aspect_ratio: {
|
|
1775
|
+
type: "string",
|
|
1776
|
+
enum: ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9"],
|
|
1777
|
+
description: "Defaults to the style's own aspect ratio; a value the engine does not support falls back to it."
|
|
1778
|
+
},
|
|
1779
|
+
duration: {
|
|
1780
|
+
type: "integer",
|
|
1781
|
+
minimum: 4,
|
|
1782
|
+
maximum: 15,
|
|
1783
|
+
description: "Ad length in seconds. Defaults to the style's length; clamped to what the engine allows."
|
|
1784
|
+
}
|
|
1696
1785
|
}
|
|
1697
1786
|
// "product_url OR product_name+images" is enforced by the server and the
|
|
1698
1787
|
// Zod refine; no root-level oneOf (Grok rejects non-object root unions).
|
|
1699
1788
|
};
|
|
1700
1789
|
adSkill = {
|
|
1701
1790
|
name: "pixeldojo_ad",
|
|
1702
|
-
description: "Marketing Studio: turn
|
|
1791
|
+
description: "Marketing Studio: turn a product into a rendered video ad with voiceover. Requires `product_url` (name, description and images are extracted), or `product_name` plus product_image_urls / product_image_paths. Pick a `style` slug (default ugc-testimonial; full catalog at GET https://pixeldojo.ai/api/v1/marketing/presets), and optionally add presenter reference images, a location, a hook, and the exact spoken script. Returns the video URL, or a jobId to check with pixeldojo_status.",
|
|
1703
1792
|
inputZod: InputSchema9,
|
|
1704
1793
|
inputJsonSchema: InputJsonSchema9,
|
|
1705
1794
|
// Composition skill — the server routes to the ad engine internally.
|
|
@@ -1761,27 +1850,47 @@ var init_campaign = __esm({
|
|
|
1761
1850
|
productUrl: {
|
|
1762
1851
|
type: "string",
|
|
1763
1852
|
format: "uri",
|
|
1764
|
-
description: "Product page URL
|
|
1853
|
+
description: "Product page URL; name, description and images are extracted automatically. Pass this or `product` (one is required); when both are set, productUrl wins."
|
|
1765
1854
|
},
|
|
1766
1855
|
product: {
|
|
1767
1856
|
type: "object",
|
|
1857
|
+
description: "Manual product profile, used when productUrl is omitted.",
|
|
1768
1858
|
properties: {
|
|
1769
|
-
name: { type: "string" },
|
|
1770
|
-
description: { type: "string" },
|
|
1771
|
-
images: {
|
|
1859
|
+
name: { type: "string", description: "Product name (required)." },
|
|
1860
|
+
description: { type: "string", description: "Optional product description." },
|
|
1861
|
+
images: {
|
|
1862
|
+
type: "array",
|
|
1863
|
+
items: { type: "string", format: "uri" },
|
|
1864
|
+
maxItems: 5,
|
|
1865
|
+
description: "Up to 5 hosted product photo URLs."
|
|
1866
|
+
}
|
|
1772
1867
|
},
|
|
1773
1868
|
required: ["name"]
|
|
1774
1869
|
},
|
|
1775
1870
|
tone: {
|
|
1776
1871
|
type: "string",
|
|
1777
|
-
description:
|
|
1872
|
+
description: 'Optional creative direction ("premium minimalist", "playful Y2K"), threaded through every prompt.'
|
|
1778
1873
|
},
|
|
1779
|
-
variants: {
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1874
|
+
variants: {
|
|
1875
|
+
type: "integer",
|
|
1876
|
+
minimum: 1,
|
|
1877
|
+
maximum: 8,
|
|
1878
|
+
description: "Lifestyle shots in addition to the hero (default 4)."
|
|
1879
|
+
},
|
|
1880
|
+
includeVideo: { type: "boolean", description: "Also render a launch video (default true)." },
|
|
1881
|
+
videoAspectRatio: {
|
|
1882
|
+
type: "string",
|
|
1883
|
+
enum: ["9:16", "16:9", "1:1"],
|
|
1884
|
+
description: "Launch video aspect ratio (default 9:16)."
|
|
1885
|
+
},
|
|
1886
|
+
videoMode: {
|
|
1887
|
+
type: "string",
|
|
1888
|
+
enum: ["lifestyle", "cgi", "ugc", "skip"],
|
|
1889
|
+
description: "Launch video styling: lifestyle (default), cgi, ugc, or skip for no video."
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
// productUrl-or-product is enforced by the Zod refine and the server; no
|
|
1893
|
+
// root-level oneOf (some clients reject root unions — see ad.ts).
|
|
1785
1894
|
};
|
|
1786
1895
|
campaignSkill = {
|
|
1787
1896
|
name: "pixeldojo_campaign",
|
|
@@ -1856,7 +1965,7 @@ var init_campaign_status = __esm({
|
|
|
1856
1965
|
async function run12(input, ctx) {
|
|
1857
1966
|
let url;
|
|
1858
1967
|
try {
|
|
1859
|
-
url = await uploadLocalFile(input.path, ctx
|
|
1968
|
+
url = await uploadLocalFile(input.path, ctx);
|
|
1860
1969
|
} catch (err) {
|
|
1861
1970
|
if (err instanceof SkillUploadError) {
|
|
1862
1971
|
return { kind: "text", text: `pixeldojo_upload: ${err.userMessage}` };
|
|
@@ -1866,7 +1975,7 @@ async function run12(input, ctx) {
|
|
|
1866
1975
|
return {
|
|
1867
1976
|
kind: "text",
|
|
1868
1977
|
text: `Uploaded ${path.basename(input.path)} \u2192 ${url}
|
|
1869
|
-
(temp storage; auto-deletes in ~24h
|
|
1978
|
+
(temp storage; auto-deletes in ~24h. Pass this URL as image_url, or video_url for a clip, to any pixeldojo tool that takes one.)`
|
|
1870
1979
|
};
|
|
1871
1980
|
}
|
|
1872
1981
|
var InputSchema12, InputJsonSchema12, uploadSkill;
|
|
@@ -1890,7 +1999,7 @@ var init_upload = __esm({
|
|
|
1890
1999
|
};
|
|
1891
2000
|
uploadSkill = {
|
|
1892
2001
|
name: "pixeldojo_upload",
|
|
1893
|
-
description: "Upload a local image or video
|
|
2002
|
+
description: "Upload a local image or video (JPEG, PNG, WebP, GIF up to 50MB; MP4, WebM, MOV up to 200MB) and get back a public URL that expires after 24 hours. Free. Audio files are not accepted. Pass the URL as image_url (stills) or video_url (clips) to tools that take hosted URLs only, such as pixeldojo_character, pixeldojo_storyboard and pixeldojo_upscale. pixeldojo_generate, pixeldojo_edit and pixeldojo_ad take local paths directly and need no separate upload.",
|
|
1894
2003
|
inputZod: InputSchema12,
|
|
1895
2004
|
inputJsonSchema: InputJsonSchema12,
|
|
1896
2005
|
allowedModels: [],
|
|
@@ -1908,18 +2017,7 @@ async function run13(input, ctx) {
|
|
|
1908
2017
|
};
|
|
1909
2018
|
}
|
|
1910
2019
|
const apiId = requested;
|
|
1911
|
-
|
|
1912
|
-
if (input.audio_paths?.length) {
|
|
1913
|
-
try {
|
|
1914
|
-
const uploaded = await uploadLocalFiles(input.audio_paths, ctx.client);
|
|
1915
|
-
audioUrls = [...audioUrls, ...uploaded].slice(0, 3);
|
|
1916
|
-
} catch (err) {
|
|
1917
|
-
if (err instanceof SkillUploadError) {
|
|
1918
|
-
return { kind: "text", text: `pixeldojo_audio (upload): ${err.userMessage}` };
|
|
1919
|
-
}
|
|
1920
|
-
throw err;
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
2020
|
+
const audioUrls = input.audio_urls ?? [];
|
|
1923
2021
|
const body = { prompt: input.prompt };
|
|
1924
2022
|
if (apiId === "seed-audio") {
|
|
1925
2023
|
if (input.voice) body.voice = input.voice;
|
|
@@ -1952,37 +2050,57 @@ var ALLOWED4, DEFAULT_MODEL6, InputSchema13, InputJsonSchema13, audioSkill;
|
|
|
1952
2050
|
var init_audio = __esm({
|
|
1953
2051
|
"src/skills/audio.ts"() {
|
|
1954
2052
|
init_poll();
|
|
1955
|
-
init_upload_helpers();
|
|
1956
2053
|
init_types();
|
|
1957
2054
|
ALLOWED4 = ["seed-audio", "text-to-speech"];
|
|
1958
2055
|
DEFAULT_MODEL6 = "seed-audio";
|
|
1959
2056
|
InputSchema13 = zod.z.object({
|
|
1960
2057
|
prompt: zod.z.string().min(1).describe(
|
|
1961
|
-
"
|
|
2058
|
+
"seed-audio: a script to speak, or a scene description (dialogue, sound effects, music), up to 2048 characters; refer to audio_urls clips in order as @Audio1..@Audio3. text-to-speech: the exact text to speak, up to 10,000 characters."
|
|
1962
2059
|
),
|
|
1963
|
-
model: zod.z.string().optional().describe(
|
|
1964
|
-
voice: zod.z.string().optional().describe("
|
|
1965
|
-
audio_urls: zod.z.array(zod.z.string().url()).max(3).optional().describe("seed-audio only: up to 3 reference
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
speed: zod.z.number().min(0.5).max(2).optional().describe("Speech speed multiplier (0.5\u20132).")
|
|
2060
|
+
model: zod.z.string().optional().describe(`${DEFAULT_MODEL6} (default): speech, multi-voice dialogue, effects and music in one clip, and voice cloning from audio_urls. text-to-speech: plain narration with preset voices.`),
|
|
2061
|
+
voice: zod.z.string().optional().describe("text-to-speech only: voice preset (e.g. Wise_Woman, Calm_Woman, Friendly_Person; default Wise_Woman). seed-audio ignores it: describe the voice in the prompt, or clone one with audio_urls."),
|
|
2062
|
+
audio_urls: zod.z.array(zod.z.string().url()).max(3).optional().describe("seed-audio only: up to 3 hosted reference clips (wav, mp3, pcm or ogg_opus, 30s / 10MB max each) for voice cloning, referenced in the prompt as @Audio1..@Audio3. Local audio files cannot be uploaded; pass URLs. Ignored by text-to-speech."),
|
|
2063
|
+
output_format: zod.z.string().optional().describe("Output format. seed-audio: mp3 (default), wav, pcm, ogg_opus. text-to-speech: mp3 (default), wav, flac, pcm."),
|
|
2064
|
+
speed: zod.z.number().min(0.5).max(2).optional().describe("Speech speed multiplier, 0.5-2 (default 1). Both models.")
|
|
1969
2065
|
});
|
|
1970
2066
|
InputJsonSchema13 = {
|
|
1971
2067
|
type: "object",
|
|
1972
2068
|
properties: {
|
|
1973
|
-
prompt: {
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
2069
|
+
prompt: {
|
|
2070
|
+
type: "string",
|
|
2071
|
+
description: "seed-audio: a script to speak, or a scene description (dialogue, sound effects, music), up to 2048 characters; refer to audio_urls clips in order as @Audio1..@Audio3. text-to-speech: the exact text to speak, up to 10,000 characters."
|
|
2072
|
+
},
|
|
2073
|
+
model: {
|
|
2074
|
+
type: "string",
|
|
2075
|
+
enum: ALLOWED4,
|
|
2076
|
+
description: `${DEFAULT_MODEL6} (default): speech, multi-voice dialogue, effects and music in one clip, and voice cloning from audio_urls. text-to-speech: plain narration with preset voices.`
|
|
2077
|
+
},
|
|
2078
|
+
voice: {
|
|
2079
|
+
type: "string",
|
|
2080
|
+
description: "text-to-speech only: voice preset (e.g. Wise_Woman, Calm_Woman, Friendly_Person; default Wise_Woman). seed-audio ignores it: describe the voice in the prompt, or clone one with audio_urls."
|
|
2081
|
+
},
|
|
2082
|
+
audio_urls: {
|
|
2083
|
+
type: "array",
|
|
2084
|
+
items: { type: "string", format: "uri" },
|
|
2085
|
+
maxItems: 3,
|
|
2086
|
+
description: "seed-audio only: up to 3 hosted reference clips (wav, mp3, pcm or ogg_opus, 30s / 10MB max each) for voice cloning, referenced in the prompt as @Audio1..@Audio3. Local audio files cannot be uploaded; pass URLs. Ignored by text-to-speech."
|
|
2087
|
+
},
|
|
2088
|
+
output_format: {
|
|
2089
|
+
type: "string",
|
|
2090
|
+
description: "Output format. seed-audio: mp3 (default), wav, pcm, ogg_opus. text-to-speech: mp3 (default), wav, flac, pcm."
|
|
2091
|
+
},
|
|
2092
|
+
speed: {
|
|
2093
|
+
type: "number",
|
|
2094
|
+
minimum: 0.5,
|
|
2095
|
+
maximum: 2,
|
|
2096
|
+
description: "Speech speed multiplier, 0.5-2 (default 1). Both models."
|
|
2097
|
+
}
|
|
1980
2098
|
},
|
|
1981
2099
|
required: ["prompt"]
|
|
1982
2100
|
};
|
|
1983
2101
|
audioSkill = {
|
|
1984
2102
|
name: "pixeldojo_audio",
|
|
1985
|
-
description: "Generate audio: speech, multi-character dialogue, sound effects, and background music from one prompt (Seed Audio 1.0 by default; plain
|
|
2103
|
+
description: "Generate audio: speech, multi-character dialogue, sound effects, and background music from one prompt (Seed Audio 1.0 by default; plain text-to-speech available). Voice cloning takes hosted reference clip URLs in audio_urls; local audio files are not accepted. Returns an audio URL, or a jobId for pixeldojo_status.",
|
|
1986
2104
|
inputZod: InputSchema13,
|
|
1987
2105
|
inputJsonSchema: InputJsonSchema13,
|
|
1988
2106
|
allowedModels: [...ALLOWED4],
|
|
@@ -2019,7 +2137,7 @@ async function run14(input, ctx) {
|
|
|
2019
2137
|
text: `${res.items.length} library item(s):
|
|
2020
2138
|
${lines.join("\n")}
|
|
2021
2139
|
|
|
2022
|
-
Pass any URL back into
|
|
2140
|
+
Pass any URL back into pixeldojo_generate, pixeldojo_edit, pixeldojo_character, or pixeldojo_upscale as a reference input.`
|
|
2023
2141
|
};
|
|
2024
2142
|
}
|
|
2025
2143
|
var InputSchema14, InputJsonSchema14, librarySkill;
|
|
@@ -2034,16 +2152,23 @@ var init_library = __esm({
|
|
|
2034
2152
|
InputJsonSchema14 = {
|
|
2035
2153
|
type: "object",
|
|
2036
2154
|
properties: {
|
|
2037
|
-
q: {
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2155
|
+
q: {
|
|
2156
|
+
type: "string",
|
|
2157
|
+
description: "Substring match against the prompt that produced the asset. Omit to list the newest items."
|
|
2158
|
+
},
|
|
2159
|
+
model: { type: "string", description: "Only assets from this model apiId." },
|
|
2160
|
+
modality: {
|
|
2161
|
+
type: "string",
|
|
2162
|
+
enum: ["image", "video", "audio"],
|
|
2163
|
+
description: "Only this output type."
|
|
2164
|
+
},
|
|
2165
|
+
limit: { type: "integer", minimum: 1, maximum: 50, description: "Max results (default 10)." }
|
|
2041
2166
|
},
|
|
2042
2167
|
required: []
|
|
2043
2168
|
};
|
|
2044
2169
|
librarySkill = {
|
|
2045
2170
|
name: "pixeldojo_library",
|
|
2046
|
-
description: "Search your media library: saved My Media items (permanent) and recent API/MCP generations (
|
|
2171
|
+
description: "Search your media library: saved My Media items (permanent) and recent API/MCP generations (deleted 1 hour after they finish), newest first. Returns asset URLs to reuse as reference inputs.",
|
|
2047
2172
|
inputZod: InputSchema14,
|
|
2048
2173
|
inputJsonSchema: InputJsonSchema14,
|
|
2049
2174
|
allowedModels: [],
|
|
@@ -2052,52 +2177,6 @@ var init_library = __esm({
|
|
|
2052
2177
|
};
|
|
2053
2178
|
}
|
|
2054
2179
|
});
|
|
2055
|
-
async function run15(input, ctx) {
|
|
2056
|
-
const res = await ctx.client.saveMedia({
|
|
2057
|
-
url: input.url,
|
|
2058
|
-
prompt: input.prompt,
|
|
2059
|
-
tool_name: input.tool_name,
|
|
2060
|
-
modality: input.modality,
|
|
2061
|
-
job_id: input.job_id
|
|
2062
|
-
});
|
|
2063
|
-
return {
|
|
2064
|
-
kind: "text",
|
|
2065
|
-
text: `Saved to My Media (permanent): ${res.url}
|
|
2066
|
-
It will appear at https://pixeldojo.ai/my-images and in pixeldojo_library searches.`
|
|
2067
|
-
};
|
|
2068
|
-
}
|
|
2069
|
-
var InputSchema15, InputJsonSchema15, saveSkill;
|
|
2070
|
-
var init_save = __esm({
|
|
2071
|
-
"src/skills/save.ts"() {
|
|
2072
|
-
InputSchema15 = zod.z.object({
|
|
2073
|
-
url: zod.z.string().url().describe("The asset URL to save (image or video)."),
|
|
2074
|
-
prompt: zod.z.string().optional().describe("The prompt that produced it \u2014 makes it findable in the library later."),
|
|
2075
|
-
tool_name: zod.z.string().optional().describe("Tool/model slug that produced it."),
|
|
2076
|
-
modality: zod.z.enum(["image", "video", "audio"]).optional(),
|
|
2077
|
-
job_id: zod.z.string().optional().describe("The jobId that produced this asset, when known.")
|
|
2078
|
-
});
|
|
2079
|
-
InputJsonSchema15 = {
|
|
2080
|
-
type: "object",
|
|
2081
|
-
properties: {
|
|
2082
|
-
url: { type: "string", format: "uri" },
|
|
2083
|
-
prompt: { type: "string" },
|
|
2084
|
-
tool_name: { type: "string" },
|
|
2085
|
-
modality: { type: "string", enum: ["image", "video", "audio"] },
|
|
2086
|
-
job_id: { type: "string" }
|
|
2087
|
-
},
|
|
2088
|
-
required: ["url"]
|
|
2089
|
-
};
|
|
2090
|
-
saveSkill = {
|
|
2091
|
-
name: "pixeldojo_save",
|
|
2092
|
-
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.",
|
|
2093
|
-
inputZod: InputSchema15,
|
|
2094
|
-
inputJsonSchema: InputJsonSchema15,
|
|
2095
|
-
allowedModels: [],
|
|
2096
|
-
defaultModel: "",
|
|
2097
|
-
run: run15
|
|
2098
|
-
};
|
|
2099
|
-
}
|
|
2100
|
-
});
|
|
2101
2180
|
function substitutePlaceholders(args, inputs, prevUrl) {
|
|
2102
2181
|
const missing = [];
|
|
2103
2182
|
const fill = (value) => {
|
|
@@ -2225,7 +2304,7 @@ async function runWorkflow(input, ctx) {
|
|
|
2225
2304
|
${outputs.join("\n")}`
|
|
2226
2305
|
};
|
|
2227
2306
|
}
|
|
2228
|
-
var WORKFLOW_STEP_EXTRA_BUDGET_MS, StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
|
|
2307
|
+
var WORKFLOW_STEP_EXTRA_BUDGET_MS, StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, STEP_SKILLS, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
|
|
2229
2308
|
var init_workflows = __esm({
|
|
2230
2309
|
"src/skills/workflows.ts"() {
|
|
2231
2310
|
init_poll();
|
|
@@ -2249,11 +2328,28 @@ var init_workflows = __esm({
|
|
|
2249
2328
|
inputs: zod.z.record(zod.z.string(), zod.z.string()).optional().describe("Values for {{input.<key>}} placeholders in the workflow steps.")
|
|
2250
2329
|
});
|
|
2251
2330
|
ListInputSchema = zod.z.object({});
|
|
2331
|
+
STEP_SKILLS = [
|
|
2332
|
+
"pixeldojo_generate",
|
|
2333
|
+
"pixeldojo_edit",
|
|
2334
|
+
"pixeldojo_character",
|
|
2335
|
+
"pixeldojo_storyboard",
|
|
2336
|
+
"pixeldojo_upscale",
|
|
2337
|
+
"pixeldojo_audio",
|
|
2338
|
+
"pixeldojo_upload",
|
|
2339
|
+
"pixeldojo_from_url"
|
|
2340
|
+
];
|
|
2252
2341
|
stepJson = {
|
|
2253
2342
|
type: "object",
|
|
2254
2343
|
properties: {
|
|
2255
|
-
skill: {
|
|
2256
|
-
|
|
2344
|
+
skill: {
|
|
2345
|
+
type: "string",
|
|
2346
|
+
enum: STEP_SKILLS,
|
|
2347
|
+
description: "Tool this step runs. Steps run in order when the workflow runs, and each is charged at that tool's own rate."
|
|
2348
|
+
},
|
|
2349
|
+
args: {
|
|
2350
|
+
type: "object",
|
|
2351
|
+
description: "That tool's own arguments, exactly as you would pass them calling it directly. Any string value, at any depth, may contain {{input.<key>}} (filled from pixeldojo_run_workflow inputs) or {{prev}} (the first asset URL the previous step produced)."
|
|
2352
|
+
}
|
|
2257
2353
|
},
|
|
2258
2354
|
required: ["skill"]
|
|
2259
2355
|
};
|
|
@@ -2264,9 +2360,19 @@ var init_workflows = __esm({
|
|
|
2264
2360
|
inputJsonSchema: {
|
|
2265
2361
|
type: "object",
|
|
2266
2362
|
properties: {
|
|
2267
|
-
name: {
|
|
2268
|
-
|
|
2269
|
-
|
|
2363
|
+
name: {
|
|
2364
|
+
type: "string",
|
|
2365
|
+
pattern: "^[a-z0-9][a-z0-9-]{1,40}$",
|
|
2366
|
+
description: 'Kebab-case handle, 2-41 chars (e.g. "product-launch-pack"). Saving to an existing name overwrites it.'
|
|
2367
|
+
},
|
|
2368
|
+
description: { type: "string", description: "Optional note on what the workflow does (max 500 chars)." },
|
|
2369
|
+
steps: {
|
|
2370
|
+
type: "array",
|
|
2371
|
+
items: stepJson,
|
|
2372
|
+
minItems: 1,
|
|
2373
|
+
maxItems: 8,
|
|
2374
|
+
description: "The chain, 1-8 steps, run in order. Saving charges nothing; running charges each step."
|
|
2375
|
+
}
|
|
2270
2376
|
},
|
|
2271
2377
|
required: ["name", "steps"]
|
|
2272
2378
|
},
|
|
@@ -2281,8 +2387,12 @@ var init_workflows = __esm({
|
|
|
2281
2387
|
inputJsonSchema: {
|
|
2282
2388
|
type: "object",
|
|
2283
2389
|
properties: {
|
|
2284
|
-
name: { type: "string" },
|
|
2285
|
-
inputs: {
|
|
2390
|
+
name: { type: "string", description: "Saved workflow name (see pixeldojo_list_workflows)." },
|
|
2391
|
+
inputs: {
|
|
2392
|
+
type: "object",
|
|
2393
|
+
additionalProperties: { type: "string" },
|
|
2394
|
+
description: `String values for the workflow's {{input.<key>}} placeholders, e.g. {"product": "red sneaker"}. A step whose placeholder has no value stops the run before that step.`
|
|
2395
|
+
}
|
|
2286
2396
|
},
|
|
2287
2397
|
required: ["name"]
|
|
2288
2398
|
},
|
|
@@ -2306,6 +2416,7 @@ var init_workflows = __esm({
|
|
|
2306
2416
|
var skills_exports = {};
|
|
2307
2417
|
__export(skills_exports, {
|
|
2308
2418
|
ALL_SKILLS: () => ALL_SKILLS,
|
|
2419
|
+
HOSTED_SKILLS: () => HOSTED_SKILLS,
|
|
2309
2420
|
adSkill: () => adSkill,
|
|
2310
2421
|
audioSkill: () => audioSkill,
|
|
2311
2422
|
campaignSkill: () => campaignSkill,
|
|
@@ -2313,24 +2424,28 @@ __export(skills_exports, {
|
|
|
2313
2424
|
characterSkill: () => characterSkill,
|
|
2314
2425
|
editSkill: () => editSkill,
|
|
2315
2426
|
filmSkill: () => filmSkill,
|
|
2427
|
+
findHostedSkill: () => findHostedSkill,
|
|
2316
2428
|
findSkill: () => findSkill,
|
|
2317
2429
|
fromUrlSkill: () => fromUrlSkill,
|
|
2318
2430
|
generateSkill: () => generateSkill,
|
|
2319
2431
|
librarySkill: () => librarySkill,
|
|
2320
2432
|
listWorkflowsSkill: () => listWorkflowsSkill,
|
|
2321
2433
|
runWorkflowSkill: () => runWorkflowSkill,
|
|
2322
|
-
saveSkill: () => saveSkill,
|
|
2323
2434
|
saveWorkflowSkill: () => saveWorkflowSkill,
|
|
2324
2435
|
statusSkill: () => statusSkill,
|
|
2325
2436
|
storyboardSkill: () => storyboardSkill,
|
|
2326
2437
|
uploadSkill: () => uploadSkill,
|
|
2327
2438
|
upscaleSkill: () => upscaleSkill
|
|
2328
2439
|
});
|
|
2440
|
+
function findHostedSkill(name) {
|
|
2441
|
+
const wanted = name.replace(/^pixeldojo:/, "pixeldojo_");
|
|
2442
|
+
return HOSTED_SKILLS.find((s) => s.name === wanted);
|
|
2443
|
+
}
|
|
2329
2444
|
function findSkill(name) {
|
|
2330
2445
|
const wanted = name.replace(/^pixeldojo:/, "pixeldojo_");
|
|
2331
2446
|
return ALL_SKILLS.find((s) => s.name === wanted);
|
|
2332
2447
|
}
|
|
2333
|
-
var ALL_SKILLS;
|
|
2448
|
+
var ALL_SKILLS, isLocalPathField, HOSTED_SKILLS;
|
|
2334
2449
|
var init_skills = __esm({
|
|
2335
2450
|
"src/skills/index.ts"() {
|
|
2336
2451
|
init_generate();
|
|
@@ -2347,7 +2462,6 @@ var init_skills = __esm({
|
|
|
2347
2462
|
init_upload();
|
|
2348
2463
|
init_audio();
|
|
2349
2464
|
init_library();
|
|
2350
|
-
init_save();
|
|
2351
2465
|
init_workflows();
|
|
2352
2466
|
ALL_SKILLS = [
|
|
2353
2467
|
generateSkill,
|
|
@@ -2357,7 +2471,6 @@ var init_skills = __esm({
|
|
|
2357
2471
|
upscaleSkill,
|
|
2358
2472
|
audioSkill,
|
|
2359
2473
|
librarySkill,
|
|
2360
|
-
saveSkill,
|
|
2361
2474
|
saveWorkflowSkill,
|
|
2362
2475
|
runWorkflowSkill,
|
|
2363
2476
|
listWorkflowsSkill,
|
|
@@ -2369,6 +2482,20 @@ var init_skills = __esm({
|
|
|
2369
2482
|
campaignStatusSkill,
|
|
2370
2483
|
filmSkill
|
|
2371
2484
|
];
|
|
2485
|
+
isLocalPathField = (key) => /_paths?$/.test(key);
|
|
2486
|
+
HOSTED_SKILLS = ALL_SKILLS.filter(
|
|
2487
|
+
(s) => s.name !== uploadSkill.name
|
|
2488
|
+
).map((s) => {
|
|
2489
|
+
const props = s.inputJsonSchema.properties ?? {};
|
|
2490
|
+
return {
|
|
2491
|
+
...s,
|
|
2492
|
+
description: s.hostedDescription ?? s.description,
|
|
2493
|
+
inputJsonSchema: {
|
|
2494
|
+
...s.inputJsonSchema,
|
|
2495
|
+
properties: Object.fromEntries(Object.entries(props).filter(([k]) => !isLocalPathField(k)))
|
|
2496
|
+
}
|
|
2497
|
+
};
|
|
2498
|
+
});
|
|
2372
2499
|
}
|
|
2373
2500
|
});
|
|
2374
2501
|
function makeAttributedClient(options) {
|
|
@@ -2422,7 +2549,8 @@ function makeRedactedLogger(target = console) {
|
|
|
2422
2549
|
}
|
|
2423
2550
|
|
|
2424
2551
|
// src/server.ts
|
|
2425
|
-
var PACKAGE_VERSION = "0.
|
|
2552
|
+
var PACKAGE_VERSION = "0.13.0" ;
|
|
2553
|
+
var SERVER_INSTRUCTIONS = "PixelDojo generates images, video, audio and short films across 100+ models, billed in credits from the connected PixelDojo account. A job that runs past the 30-second wait returns a jobId to check later; check it rather than submitting again, since every new submission is charged. Generated asset URLs are deleted one hour after they are created, so download anything the user wants to keep. Finished films are the exception and stay in the account library.";
|
|
2426
2554
|
function buildServer(options) {
|
|
2427
2555
|
if (!options.apiKey) {
|
|
2428
2556
|
throw new Error(
|
|
@@ -2440,7 +2568,8 @@ function buildServer(options) {
|
|
|
2440
2568
|
{
|
|
2441
2569
|
capabilities: {
|
|
2442
2570
|
tools: {}
|
|
2443
|
-
}
|
|
2571
|
+
},
|
|
2572
|
+
instructions: SERVER_INSTRUCTIONS
|
|
2444
2573
|
}
|
|
2445
2574
|
);
|
|
2446
2575
|
server.setRequestHandler(types_js.ListToolsRequestSchema, async () => {
|
|
@@ -2492,6 +2621,8 @@ function buildServer(options) {
|
|
|
2492
2621
|
apiKey: options.apiKey,
|
|
2493
2622
|
baseUrl,
|
|
2494
2623
|
mcpVersion: version,
|
|
2624
|
+
localFiles: true,
|
|
2625
|
+
// stdio: the caller's own machine
|
|
2495
2626
|
logger,
|
|
2496
2627
|
buildStatusUrl: (jobId) => `${baseUrl}/api/v1/jobs/${encodeURIComponent(jobId)}`
|
|
2497
2628
|
};
|
|
@@ -2596,7 +2727,6 @@ function printInit() {
|
|
|
2596
2727
|
`# pixeldojo_upscale Enhance any image or video.`,
|
|
2597
2728
|
`# pixeldojo_audio Voices + effects + music in one clip.`,
|
|
2598
2729
|
`# pixeldojo_library Search your saved media + generations.`,
|
|
2599
|
-
`# pixeldojo_save Keep a result in My Media permanently.`,
|
|
2600
2730
|
`# pixeldojo_*_workflow Save / run / list multi-step chains.`,
|
|
2601
2731
|
`# pixeldojo_upload Local file \u2192 temp URL for references.`,
|
|
2602
2732
|
`# pixeldojo_from_url Product URL \u2192 structured product info.`,
|