@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/index.js
CHANGED
|
@@ -111,7 +111,8 @@ var init_types = __esm({
|
|
|
111
111
|
"src/skills/types.ts"() {
|
|
112
112
|
}
|
|
113
113
|
});
|
|
114
|
-
async function uploadLocalFile(path,
|
|
114
|
+
async function uploadLocalFile(path, ctx) {
|
|
115
|
+
if (ctx.localFiles !== true) throw new SkillUploadError(HOSTED_LOCAL_PATH_MESSAGE);
|
|
115
116
|
const ext = extname(path).toLowerCase();
|
|
116
117
|
const mime = EXT_TO_MIME[ext];
|
|
117
118
|
if (!mime) {
|
|
@@ -150,13 +151,13 @@ async function uploadLocalFile(path, client) {
|
|
|
150
151
|
const buffer = await readFile(path);
|
|
151
152
|
const blob = new Blob([new Uint8Array(buffer)], { type: mime });
|
|
152
153
|
const filename = basename(path);
|
|
153
|
-
const response = await client.uploadImage(blob, filename);
|
|
154
|
+
const response = await ctx.client.uploadImage(blob, filename);
|
|
154
155
|
return response.url;
|
|
155
156
|
}
|
|
156
|
-
async function uploadLocalFiles(paths,
|
|
157
|
-
return Promise.all(paths.map((p) => uploadLocalFile(p,
|
|
157
|
+
async function uploadLocalFiles(paths, ctx) {
|
|
158
|
+
return Promise.all(paths.map((p) => uploadLocalFile(p, ctx)));
|
|
158
159
|
}
|
|
159
|
-
var MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, EXT_TO_MIME, SkillUploadError;
|
|
160
|
+
var MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, EXT_TO_MIME, SkillUploadError, HOSTED_LOCAL_PATH_MESSAGE;
|
|
160
161
|
var init_upload_helpers = __esm({
|
|
161
162
|
"src/skills/upload-helpers.ts"() {
|
|
162
163
|
MAX_IMAGE_BYTES = 50 * 1024 * 1024;
|
|
@@ -179,6 +180,7 @@ var init_upload_helpers = __esm({
|
|
|
179
180
|
}
|
|
180
181
|
userMessage;
|
|
181
182
|
};
|
|
183
|
+
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.";
|
|
182
184
|
}
|
|
183
185
|
});
|
|
184
186
|
|
|
@@ -450,10 +452,10 @@ async function run(input, ctx) {
|
|
|
450
452
|
let resolved = input;
|
|
451
453
|
let referenceUrls = [];
|
|
452
454
|
try {
|
|
453
|
-
const singleUrl = input.image_url ?? (input.image_path ? await uploadLocalFile(input.image_path, ctx
|
|
455
|
+
const singleUrl = input.image_url ?? (input.image_path ? await uploadLocalFile(input.image_path, ctx) : void 0);
|
|
454
456
|
const manyUrls = [...input.image_urls ?? []];
|
|
455
457
|
for (const p of input.image_paths ?? []) {
|
|
456
|
-
manyUrls.push(await uploadLocalFile(p, ctx
|
|
458
|
+
manyUrls.push(await uploadLocalFile(p, ctx));
|
|
457
459
|
}
|
|
458
460
|
referenceUrls = [...singleUrl ? [singleUrl] : [], ...manyUrls].filter(
|
|
459
461
|
(u, i, all) => all.indexOf(u) === i
|
|
@@ -538,19 +540,19 @@ var init_generate = __esm({
|
|
|
538
540
|
InputSchema = z.object({
|
|
539
541
|
prompt: z.string().min(1).max(8e3).describe("Prompt describing what to generate."),
|
|
540
542
|
model: z.string().optional().describe(
|
|
541
|
-
|
|
543
|
+
`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.`
|
|
542
544
|
),
|
|
543
545
|
preset: z.string().optional().describe(
|
|
544
|
-
|
|
546
|
+
"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."
|
|
545
547
|
),
|
|
546
|
-
aspect_ratio: z.string().optional().describe('
|
|
547
|
-
duration: z.number().int().positive().optional().describe("Video
|
|
548
|
+
aspect_ratio: 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.'),
|
|
549
|
+
duration: 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)."),
|
|
548
550
|
resolution: z.string().optional().describe(
|
|
549
551
|
'Output resolution when the model supports it (e.g. "480p", "720p", "1080p", "4k"). Lower tiers cost fewer credits. Omit to use the model default.'
|
|
550
552
|
),
|
|
551
|
-
image_url: z.string().url().optional().describe("Reference
|
|
553
|
+
image_url: 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."),
|
|
552
554
|
video_url: z.string().url().optional().describe(
|
|
553
|
-
"Source video clip to animate / restyle / extend. Use this for videos; image_url is for still frames.
|
|
555
|
+
"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."
|
|
554
556
|
),
|
|
555
557
|
params: ParamsInput,
|
|
556
558
|
image_path: z.string().min(1).optional().describe(
|
|
@@ -577,45 +579,56 @@ var init_generate = __esm({
|
|
|
577
579
|
prompt: { type: "string", description: "Prompt describing what to generate." },
|
|
578
580
|
model: {
|
|
579
581
|
type: "string",
|
|
580
|
-
description:
|
|
582
|
+
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.`
|
|
581
583
|
},
|
|
582
584
|
preset: {
|
|
583
585
|
type: "string",
|
|
584
|
-
description:
|
|
586
|
+
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."
|
|
587
|
+
},
|
|
588
|
+
aspect_ratio: {
|
|
589
|
+
type: "string",
|
|
590
|
+
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.'
|
|
591
|
+
},
|
|
592
|
+
duration: {
|
|
593
|
+
type: "integer",
|
|
594
|
+
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)."
|
|
585
595
|
},
|
|
586
|
-
aspect_ratio: { type: "string" },
|
|
587
|
-
duration: { type: "integer" },
|
|
588
596
|
resolution: {
|
|
589
597
|
type: "string",
|
|
590
|
-
description: 'Output resolution when
|
|
598
|
+
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.'
|
|
599
|
+
},
|
|
600
|
+
image_url: {
|
|
601
|
+
type: "string",
|
|
602
|
+
format: "uri",
|
|
603
|
+
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."
|
|
591
604
|
},
|
|
592
|
-
image_url: { type: "string", format: "uri" },
|
|
593
605
|
video_url: {
|
|
594
606
|
type: "string",
|
|
595
607
|
format: "uri",
|
|
596
|
-
description: "Source video clip to animate / restyle / extend. Use this for videos; image_url is for still frames."
|
|
608
|
+
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."
|
|
597
609
|
},
|
|
598
610
|
params: PARAMS_JSON_SCHEMA,
|
|
599
611
|
image_urls: {
|
|
600
612
|
type: "array",
|
|
601
613
|
items: { type: "string", format: "uri" },
|
|
602
|
-
description: "Multiple reference image URLs for models that accept a reference set. Single-reference models use the first."
|
|
614
|
+
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."
|
|
603
615
|
},
|
|
604
616
|
image_paths: {
|
|
605
617
|
type: "array",
|
|
606
618
|
items: { type: "string" },
|
|
607
|
-
description: "Multiple absolute local file paths, each uploaded to 24h temp storage and used as a reference."
|
|
619
|
+
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."
|
|
608
620
|
},
|
|
609
621
|
image_path: {
|
|
610
622
|
type: "string",
|
|
611
|
-
description: "Absolute local file path. The skill uploads it to
|
|
623
|
+
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."
|
|
612
624
|
}
|
|
613
625
|
},
|
|
614
626
|
required: ["prompt"]
|
|
615
627
|
};
|
|
616
628
|
generateSkill = {
|
|
617
629
|
name: "pixeldojo_generate",
|
|
618
|
-
description: "Generate
|
|
630
|
+
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.",
|
|
631
|
+
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.",
|
|
619
632
|
inputZod: InputSchema,
|
|
620
633
|
inputJsonSchema: InputJsonSchema,
|
|
621
634
|
allowedModels: null,
|
|
@@ -691,13 +704,13 @@ async function run2(input, ctx) {
|
|
|
691
704
|
let resolved = input;
|
|
692
705
|
try {
|
|
693
706
|
if (input.image_paths && input.image_paths.length > 0) {
|
|
694
|
-
const urls = await uploadLocalFiles(input.image_paths, ctx
|
|
707
|
+
const urls = await uploadLocalFiles(input.image_paths, ctx);
|
|
695
708
|
resolved = {
|
|
696
709
|
...input,
|
|
697
710
|
image_urls: [...input.image_urls ?? [], ...urls]
|
|
698
711
|
};
|
|
699
712
|
} else if (input.image_path && !input.image_url) {
|
|
700
|
-
const url = await uploadLocalFile(input.image_path, ctx
|
|
713
|
+
const url = await uploadLocalFile(input.image_path, ctx);
|
|
701
714
|
resolved = { ...input, image_url: url };
|
|
702
715
|
}
|
|
703
716
|
} catch (err) {
|
|
@@ -779,32 +792,35 @@ var init_edit = __esm({
|
|
|
779
792
|
image_url: {
|
|
780
793
|
type: "string",
|
|
781
794
|
format: "uri",
|
|
782
|
-
description: "Single
|
|
795
|
+
description: "Single image to edit. Ignored when image_urls is set; pass image_urls for multi-image edits."
|
|
783
796
|
},
|
|
784
797
|
image_urls: {
|
|
785
798
|
type: "array",
|
|
786
799
|
items: { type: "string", format: "uri" },
|
|
787
800
|
minItems: 1,
|
|
788
801
|
maxItems: 9,
|
|
789
|
-
description: "Multiple reference images (1-9)."
|
|
802
|
+
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."
|
|
790
803
|
},
|
|
791
804
|
image_path: {
|
|
792
805
|
type: "string",
|
|
793
|
-
description: "Absolute local
|
|
806
|
+
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."
|
|
794
807
|
},
|
|
795
808
|
image_paths: {
|
|
796
809
|
type: "array",
|
|
797
810
|
items: { type: "string" },
|
|
798
811
|
minItems: 1,
|
|
799
812
|
maxItems: 9,
|
|
800
|
-
description: "Multiple absolute local
|
|
813
|
+
description: "Multiple absolute local image paths (1-9). Each is uploaded to 24h temp storage and appended after any image_urls."
|
|
801
814
|
},
|
|
802
815
|
model: {
|
|
803
816
|
type: "string",
|
|
804
817
|
enum: [...ALLOWED_MODELS],
|
|
805
818
|
description: "Override edit model. Default: wan-2.7-image-edit."
|
|
806
819
|
},
|
|
807
|
-
aspect_ratio: {
|
|
820
|
+
aspect_ratio: {
|
|
821
|
+
type: "string",
|
|
822
|
+
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.'
|
|
823
|
+
},
|
|
808
824
|
params: PARAMS_JSON_SCHEMA
|
|
809
825
|
},
|
|
810
826
|
required: ["prompt"]
|
|
@@ -812,6 +828,7 @@ var init_edit = __esm({
|
|
|
812
828
|
editSkill = {
|
|
813
829
|
name: "pixeldojo_edit",
|
|
814
830
|
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).",
|
|
831
|
+
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.",
|
|
815
832
|
inputZod: InputSchema2,
|
|
816
833
|
inputJsonSchema: InputJsonSchema2,
|
|
817
834
|
allowedModels: [...ALLOWED_MODELS],
|
|
@@ -922,7 +939,7 @@ var init_character = __esm({
|
|
|
922
939
|
InputJsonSchema3 = {
|
|
923
940
|
type: "object",
|
|
924
941
|
properties: {
|
|
925
|
-
prompt: { type: "string" },
|
|
942
|
+
prompt: { type: "string", description: "The shot to render: scene, pose, wardrobe, framing. The references supply the identity." },
|
|
926
943
|
model: {
|
|
927
944
|
type: "string",
|
|
928
945
|
enum: ALLOWED,
|
|
@@ -931,16 +948,19 @@ var init_character = __esm({
|
|
|
931
948
|
reference_image_url: {
|
|
932
949
|
type: "string",
|
|
933
950
|
format: "uri",
|
|
934
|
-
description: "Single
|
|
951
|
+
description: "Single still of the character. Ignored when reference_image_urls is set; prefer that, since more angles lock the face better."
|
|
935
952
|
},
|
|
936
953
|
reference_image_urls: {
|
|
937
954
|
type: "array",
|
|
938
955
|
items: { type: "string", format: "uri" },
|
|
939
956
|
minItems: 1,
|
|
940
957
|
maxItems: MAX_REFERENCES,
|
|
941
|
-
description: "All
|
|
958
|
+
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."
|
|
959
|
+
},
|
|
960
|
+
aspect_ratio: {
|
|
961
|
+
type: "string",
|
|
962
|
+
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).'
|
|
942
963
|
},
|
|
943
|
-
aspect_ratio: { type: "string" },
|
|
944
964
|
params: PARAMS_JSON_SCHEMA
|
|
945
965
|
},
|
|
946
966
|
required: ["prompt"]
|
|
@@ -1037,24 +1057,30 @@ var init_storyboard = __esm({
|
|
|
1037
1057
|
properties: {
|
|
1038
1058
|
brief: {
|
|
1039
1059
|
type: "string",
|
|
1040
|
-
description: "
|
|
1060
|
+
description: "Scene brief: setting, action, camera, mood. Sent to the video model as its prompt."
|
|
1041
1061
|
},
|
|
1042
1062
|
model: {
|
|
1043
1063
|
type: "string",
|
|
1044
1064
|
enum: ALLOWED2,
|
|
1045
|
-
description: `One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}.`
|
|
1065
|
+
description: `One of: ${ALLOWED2.join(", ")}. Defaults to ${DEFAULT_MODEL4}, or ${VIDEO_REFERENCE_MODEL} when image_url or video_url is given.`
|
|
1066
|
+
},
|
|
1067
|
+
aspect_ratio: {
|
|
1068
|
+
type: "string",
|
|
1069
|
+
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.'
|
|
1070
|
+
},
|
|
1071
|
+
duration: {
|
|
1072
|
+
type: "integer",
|
|
1073
|
+
description: "Clip length in seconds. Snapped or clamped to what the model allows."
|
|
1046
1074
|
},
|
|
1047
|
-
aspect_ratio: { type: "string" },
|
|
1048
|
-
duration: { type: "integer" },
|
|
1049
1075
|
image_url: {
|
|
1050
1076
|
type: "string",
|
|
1051
1077
|
format: "uri",
|
|
1052
|
-
description: "Reference still to build the shot from."
|
|
1078
|
+
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."
|
|
1053
1079
|
},
|
|
1054
1080
|
video_url: {
|
|
1055
1081
|
type: "string",
|
|
1056
1082
|
format: "uri",
|
|
1057
|
-
description: "Source clip to work from. Use this for videos; image_url is for stills."
|
|
1083
|
+
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."
|
|
1058
1084
|
},
|
|
1059
1085
|
params: PARAMS_JSON_SCHEMA
|
|
1060
1086
|
},
|
|
@@ -1062,7 +1088,7 @@ var init_storyboard = __esm({
|
|
|
1062
1088
|
};
|
|
1063
1089
|
storyboardSkill = {
|
|
1064
1090
|
name: "pixeldojo_storyboard",
|
|
1065
|
-
description: "Generate
|
|
1091
|
+
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.",
|
|
1066
1092
|
inputZod: InputSchema4,
|
|
1067
1093
|
inputJsonSchema: InputJsonSchema4,
|
|
1068
1094
|
allowedModels: [...ALLOWED2],
|
|
@@ -1159,20 +1185,42 @@ var init_upscale = __esm({
|
|
|
1159
1185
|
InputJsonSchema5 = {
|
|
1160
1186
|
type: "object",
|
|
1161
1187
|
properties: {
|
|
1162
|
-
image_url: {
|
|
1188
|
+
image_url: {
|
|
1189
|
+
type: "string",
|
|
1190
|
+
format: "uri",
|
|
1191
|
+
description: "Source image to upscale (image models). A clip URL here (.mp4/.mov/.webm) is treated as video_url."
|
|
1192
|
+
},
|
|
1163
1193
|
video_url: {
|
|
1164
1194
|
type: "string",
|
|
1165
1195
|
format: "uri",
|
|
1166
|
-
description: "Source video clip
|
|
1196
|
+
description: "Source video clip (MP4, max 500 MB). Routes to video-upscaler when no model is named; needs video_duration."
|
|
1197
|
+
},
|
|
1198
|
+
model: {
|
|
1199
|
+
type: "string",
|
|
1200
|
+
enum: ALLOWED3,
|
|
1201
|
+
description: `Defaults to ${DEFAULT_MODEL5}, or ${VIDEO_MODEL} when the source is a clip. face-enhance is for portraits.`
|
|
1202
|
+
},
|
|
1203
|
+
scale_factor: {
|
|
1204
|
+
type: "number",
|
|
1205
|
+
minimum: 1,
|
|
1206
|
+
maximum: 16,
|
|
1207
|
+
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)."
|
|
1208
|
+
},
|
|
1209
|
+
creativity: {
|
|
1210
|
+
type: "number",
|
|
1211
|
+
minimum: 0,
|
|
1212
|
+
maximum: 1,
|
|
1213
|
+
description: "magnific-upscaler only: sent unchanged as its creativity setting (default 0 = preserve the source; higher invents more detail). This tool accepts 0-1."
|
|
1167
1214
|
},
|
|
1168
|
-
model: { type: "string", enum: ALLOWED3 },
|
|
1169
|
-
scale_factor: { type: "number", minimum: 1, maximum: 16 },
|
|
1170
|
-
creativity: { type: "number", minimum: 0, maximum: 1 },
|
|
1171
1215
|
video_duration: {
|
|
1172
1216
|
type: "number",
|
|
1173
|
-
description: "video-upscaler only, required there: source clip length in seconds."
|
|
1217
|
+
description: "video-upscaler only, required there: source clip length in seconds. It sets the cost (1 credit per second)."
|
|
1174
1218
|
},
|
|
1175
|
-
target_resolution: {
|
|
1219
|
+
target_resolution: {
|
|
1220
|
+
type: "string",
|
|
1221
|
+
enum: VIDEO_RESOLUTIONS,
|
|
1222
|
+
description: "video-upscaler only: output resolution. Defaults to 1080p."
|
|
1223
|
+
}
|
|
1176
1224
|
}
|
|
1177
1225
|
};
|
|
1178
1226
|
upscaleSkill = {
|
|
@@ -1261,7 +1309,7 @@ var init_status = __esm({
|
|
|
1261
1309
|
properties: {
|
|
1262
1310
|
jobId: {
|
|
1263
1311
|
type: "string",
|
|
1264
|
-
description: "
|
|
1312
|
+
description: "The jobId a generation tool returned instead of an asset (a job_... id)."
|
|
1265
1313
|
}
|
|
1266
1314
|
},
|
|
1267
1315
|
required: ["jobId"]
|
|
@@ -1270,7 +1318,7 @@ var init_status = __esm({
|
|
|
1270
1318
|
ABANDON_HINT_MS = 12 * 60 * 1e3;
|
|
1271
1319
|
statusSkill = {
|
|
1272
1320
|
name: "pixeldojo_status",
|
|
1273
|
-
description:
|
|
1321
|
+
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".',
|
|
1274
1322
|
inputZod: InputSchema6,
|
|
1275
1323
|
inputJsonSchema: InputJsonSchema6,
|
|
1276
1324
|
// status is special — it doesn't dispatch to a model
|
|
@@ -1315,7 +1363,7 @@ var init_from_url = __esm({
|
|
|
1315
1363
|
};
|
|
1316
1364
|
fromUrlSkill = {
|
|
1317
1365
|
name: "pixeldojo_from_url",
|
|
1318
|
-
description: "Extract product
|
|
1366
|
+
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.",
|
|
1319
1367
|
inputZod: InputSchema7,
|
|
1320
1368
|
inputJsonSchema: InputJsonSchema7,
|
|
1321
1369
|
// No model dispatch — this skill calls a server-side scrape, not a generation.
|
|
@@ -1520,20 +1568,31 @@ var init_film = __esm({
|
|
|
1520
1568
|
film_id: z.string().max(40).optional().describe("Existing film id (from a previous call) for produce/status."),
|
|
1521
1569
|
action: 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."),
|
|
1522
1570
|
soundtrack: 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."),
|
|
1523
|
-
music_job_id: z.string().max(80).optional().describe("
|
|
1571
|
+
music_job_id: 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.")
|
|
1524
1572
|
});
|
|
1525
1573
|
InputJsonSchema8 = {
|
|
1526
1574
|
type: "object",
|
|
1527
1575
|
properties: {
|
|
1528
|
-
idea: { type: "string", description: "
|
|
1529
|
-
script: { type: "string", description: "
|
|
1530
|
-
look: { type: "string", enum: [...LOOKS], description: "
|
|
1531
|
-
aspect: { type: "string", enum: ["16:9", "9:16"], description: "Default 16:9." },
|
|
1532
|
-
length: { type: "string", enum: ["30s", "60s", "2-3min", "5min"], description: "
|
|
1533
|
-
film_id: { type: "string", description:
|
|
1534
|
-
action: {
|
|
1535
|
-
|
|
1536
|
-
|
|
1576
|
+
idea: { type: "string", description: "Plan step: one-to-three sentence film idea. The studio writes the screenplay (free). Provide idea or script." },
|
|
1577
|
+
script: { type: "string", description: "Plan step: a full screenplay (sluglines, action lines, dialogue) to plan instead of an idea." },
|
|
1578
|
+
look: { type: "string", enum: [...LOOKS], description: "Plan step: visual style carried through frames, clips and soundtrack. Default live-action." },
|
|
1579
|
+
aspect: { type: "string", enum: ["16:9", "9:16"], description: "Plan step: frame aspect ratio. Default 16:9." },
|
|
1580
|
+
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." },
|
|
1581
|
+
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".' },
|
|
1582
|
+
action: {
|
|
1583
|
+
type: "string",
|
|
1584
|
+
enum: ["plan", "produce", "status"],
|
|
1585
|
+
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."
|
|
1586
|
+
},
|
|
1587
|
+
soundtrack: {
|
|
1588
|
+
type: "string",
|
|
1589
|
+
enum: ["scene-synced", "flat", "none"],
|
|
1590
|
+
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."
|
|
1591
|
+
},
|
|
1592
|
+
music_job_id: {
|
|
1593
|
+
type: "string",
|
|
1594
|
+
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."
|
|
1595
|
+
}
|
|
1537
1596
|
}
|
|
1538
1597
|
};
|
|
1539
1598
|
shots = (f) => f.scenes.flatMap((s) => s.shots);
|
|
@@ -1570,11 +1629,11 @@ var init_film = __esm({
|
|
|
1570
1629
|
async function run9(input, ctx) {
|
|
1571
1630
|
const productImages = [
|
|
1572
1631
|
...input.product_image_urls ?? [],
|
|
1573
|
-
...await Promise.all((input.product_image_paths ?? []).map((p) => uploadLocalFile(p, ctx
|
|
1632
|
+
...await Promise.all((input.product_image_paths ?? []).map((p) => uploadLocalFile(p, ctx)))
|
|
1574
1633
|
];
|
|
1575
1634
|
const characterImages = [
|
|
1576
1635
|
...input.character_image_urls ?? [],
|
|
1577
|
-
...await Promise.all((input.character_image_paths ?? []).map((p) => uploadLocalFile(p, ctx
|
|
1636
|
+
...await Promise.all((input.character_image_paths ?? []).map((p) => uploadLocalFile(p, ctx)))
|
|
1578
1637
|
];
|
|
1579
1638
|
const body = {
|
|
1580
1639
|
style: input.style,
|
|
@@ -1652,16 +1711,24 @@ var init_ad = __esm({
|
|
|
1652
1711
|
product_url: {
|
|
1653
1712
|
type: "string",
|
|
1654
1713
|
format: "uri",
|
|
1655
|
-
description: "Product page URL. Name, description, and images are extracted automatically."
|
|
1714
|
+
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."
|
|
1715
|
+
},
|
|
1716
|
+
product_name: {
|
|
1717
|
+
type: "string",
|
|
1718
|
+
description: "Product name. Required with product_image_urls / product_image_paths when there is no product_url."
|
|
1719
|
+
},
|
|
1720
|
+
product_description: { type: "string", description: "Optional product description (no product_url case)." },
|
|
1721
|
+
product_image_urls: {
|
|
1722
|
+
type: "array",
|
|
1723
|
+
items: { type: "string", format: "uri" },
|
|
1724
|
+
maxItems: 5,
|
|
1725
|
+
description: "Up to 5 hosted product photos (no product_url case)."
|
|
1656
1726
|
},
|
|
1657
|
-
product_name: { type: "string" },
|
|
1658
|
-
product_description: { type: "string" },
|
|
1659
|
-
product_image_urls: { type: "array", items: { type: "string", format: "uri" }, maxItems: 5 },
|
|
1660
1727
|
product_image_paths: {
|
|
1661
1728
|
type: "array",
|
|
1662
1729
|
items: { type: "string" },
|
|
1663
1730
|
maxItems: 5,
|
|
1664
|
-
description: "
|
|
1731
|
+
description: "Up to 5 absolute local product image paths; uploaded to 24h temp storage automatically."
|
|
1665
1732
|
},
|
|
1666
1733
|
character_image_urls: {
|
|
1667
1734
|
type: "array",
|
|
@@ -1669,12 +1736,21 @@ var init_ad = __esm({
|
|
|
1669
1736
|
maxItems: 4,
|
|
1670
1737
|
description: "Presenter reference images for a consistent on-camera character."
|
|
1671
1738
|
},
|
|
1672
|
-
character_image_paths: {
|
|
1739
|
+
character_image_paths: {
|
|
1740
|
+
type: "array",
|
|
1741
|
+
items: { type: "string" },
|
|
1742
|
+
maxItems: 4,
|
|
1743
|
+
description: "Absolute local presenter image paths; uploaded to 24h temp storage automatically."
|
|
1744
|
+
},
|
|
1673
1745
|
location_description: {
|
|
1674
1746
|
type: "string",
|
|
1675
1747
|
description: 'Where the ad takes place ("a sunlit Parisian cafe"). Text is enough.'
|
|
1676
1748
|
},
|
|
1677
|
-
location_image_url: {
|
|
1749
|
+
location_image_url: {
|
|
1750
|
+
type: "string",
|
|
1751
|
+
format: "uri",
|
|
1752
|
+
description: "Optional reference photo of the location."
|
|
1753
|
+
},
|
|
1678
1754
|
hook: {
|
|
1679
1755
|
type: "string",
|
|
1680
1756
|
description: "The opening visual beat (first 1-2 seconds). Omit to use the style default."
|
|
@@ -1683,21 +1759,34 @@ var init_ad = __esm({
|
|
|
1683
1759
|
type: "string",
|
|
1684
1760
|
description: "The exact spoken line, voiced word for word. Omit and the presenter improvises."
|
|
1685
1761
|
},
|
|
1686
|
-
quality: {
|
|
1762
|
+
quality: {
|
|
1763
|
+
type: "string",
|
|
1764
|
+
enum: ["mini", "fast", "high"],
|
|
1765
|
+
description: "Render tier. Omitted or unsupported by the ad engine, the engine's default tier is used."
|
|
1766
|
+
},
|
|
1687
1767
|
resolution: {
|
|
1688
1768
|
type: "string",
|
|
1689
1769
|
enum: ["480p", "720p", "1080p", "4k"],
|
|
1690
|
-
description: '1080p/4k require quality "high".'
|
|
1770
|
+
description: '1080p/4k require quality "high"; without it, or when the engine lacks the value, the engine default resolution is used.'
|
|
1691
1771
|
},
|
|
1692
|
-
aspect_ratio: {
|
|
1693
|
-
|
|
1772
|
+
aspect_ratio: {
|
|
1773
|
+
type: "string",
|
|
1774
|
+
enum: ["16:9", "4:3", "1:1", "3:4", "9:16", "21:9"],
|
|
1775
|
+
description: "Defaults to the style's own aspect ratio; a value the engine does not support falls back to it."
|
|
1776
|
+
},
|
|
1777
|
+
duration: {
|
|
1778
|
+
type: "integer",
|
|
1779
|
+
minimum: 4,
|
|
1780
|
+
maximum: 15,
|
|
1781
|
+
description: "Ad length in seconds. Defaults to the style's length; clamped to what the engine allows."
|
|
1782
|
+
}
|
|
1694
1783
|
}
|
|
1695
1784
|
// "product_url OR product_name+images" is enforced by the server and the
|
|
1696
1785
|
// Zod refine; no root-level oneOf (Grok rejects non-object root unions).
|
|
1697
1786
|
};
|
|
1698
1787
|
adSkill = {
|
|
1699
1788
|
name: "pixeldojo_ad",
|
|
1700
|
-
description: "Marketing Studio: turn
|
|
1789
|
+
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.",
|
|
1701
1790
|
inputZod: InputSchema9,
|
|
1702
1791
|
inputJsonSchema: InputJsonSchema9,
|
|
1703
1792
|
// Composition skill — the server routes to the ad engine internally.
|
|
@@ -1759,27 +1848,47 @@ var init_campaign = __esm({
|
|
|
1759
1848
|
productUrl: {
|
|
1760
1849
|
type: "string",
|
|
1761
1850
|
format: "uri",
|
|
1762
|
-
description: "Product page URL
|
|
1851
|
+
description: "Product page URL; name, description and images are extracted automatically. Pass this or `product` (one is required); when both are set, productUrl wins."
|
|
1763
1852
|
},
|
|
1764
1853
|
product: {
|
|
1765
1854
|
type: "object",
|
|
1855
|
+
description: "Manual product profile, used when productUrl is omitted.",
|
|
1766
1856
|
properties: {
|
|
1767
|
-
name: { type: "string" },
|
|
1768
|
-
description: { type: "string" },
|
|
1769
|
-
images: {
|
|
1857
|
+
name: { type: "string", description: "Product name (required)." },
|
|
1858
|
+
description: { type: "string", description: "Optional product description." },
|
|
1859
|
+
images: {
|
|
1860
|
+
type: "array",
|
|
1861
|
+
items: { type: "string", format: "uri" },
|
|
1862
|
+
maxItems: 5,
|
|
1863
|
+
description: "Up to 5 hosted product photo URLs."
|
|
1864
|
+
}
|
|
1770
1865
|
},
|
|
1771
1866
|
required: ["name"]
|
|
1772
1867
|
},
|
|
1773
1868
|
tone: {
|
|
1774
1869
|
type: "string",
|
|
1775
|
-
description:
|
|
1870
|
+
description: 'Optional creative direction ("premium minimalist", "playful Y2K"), threaded through every prompt.'
|
|
1776
1871
|
},
|
|
1777
|
-
variants: {
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1872
|
+
variants: {
|
|
1873
|
+
type: "integer",
|
|
1874
|
+
minimum: 1,
|
|
1875
|
+
maximum: 8,
|
|
1876
|
+
description: "Lifestyle shots in addition to the hero (default 4)."
|
|
1877
|
+
},
|
|
1878
|
+
includeVideo: { type: "boolean", description: "Also render a launch video (default true)." },
|
|
1879
|
+
videoAspectRatio: {
|
|
1880
|
+
type: "string",
|
|
1881
|
+
enum: ["9:16", "16:9", "1:1"],
|
|
1882
|
+
description: "Launch video aspect ratio (default 9:16)."
|
|
1883
|
+
},
|
|
1884
|
+
videoMode: {
|
|
1885
|
+
type: "string",
|
|
1886
|
+
enum: ["lifestyle", "cgi", "ugc", "skip"],
|
|
1887
|
+
description: "Launch video styling: lifestyle (default), cgi, ugc, or skip for no video."
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
// productUrl-or-product is enforced by the Zod refine and the server; no
|
|
1891
|
+
// root-level oneOf (some clients reject root unions — see ad.ts).
|
|
1783
1892
|
};
|
|
1784
1893
|
campaignSkill = {
|
|
1785
1894
|
name: "pixeldojo_campaign",
|
|
@@ -1854,7 +1963,7 @@ var init_campaign_status = __esm({
|
|
|
1854
1963
|
async function run12(input, ctx) {
|
|
1855
1964
|
let url;
|
|
1856
1965
|
try {
|
|
1857
|
-
url = await uploadLocalFile(input.path, ctx
|
|
1966
|
+
url = await uploadLocalFile(input.path, ctx);
|
|
1858
1967
|
} catch (err) {
|
|
1859
1968
|
if (err instanceof SkillUploadError) {
|
|
1860
1969
|
return { kind: "text", text: `pixeldojo_upload: ${err.userMessage}` };
|
|
@@ -1864,7 +1973,7 @@ async function run12(input, ctx) {
|
|
|
1864
1973
|
return {
|
|
1865
1974
|
kind: "text",
|
|
1866
1975
|
text: `Uploaded ${basename(input.path)} \u2192 ${url}
|
|
1867
|
-
(temp storage; auto-deletes in ~24h
|
|
1976
|
+
(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.)`
|
|
1868
1977
|
};
|
|
1869
1978
|
}
|
|
1870
1979
|
var InputSchema12, InputJsonSchema12, uploadSkill;
|
|
@@ -1888,7 +1997,7 @@ var init_upload = __esm({
|
|
|
1888
1997
|
};
|
|
1889
1998
|
uploadSkill = {
|
|
1890
1999
|
name: "pixeldojo_upload",
|
|
1891
|
-
description: "Upload a local image or video
|
|
2000
|
+
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.",
|
|
1892
2001
|
inputZod: InputSchema12,
|
|
1893
2002
|
inputJsonSchema: InputJsonSchema12,
|
|
1894
2003
|
allowedModels: [],
|
|
@@ -1906,18 +2015,7 @@ async function run13(input, ctx) {
|
|
|
1906
2015
|
};
|
|
1907
2016
|
}
|
|
1908
2017
|
const apiId = requested;
|
|
1909
|
-
|
|
1910
|
-
if (input.audio_paths?.length) {
|
|
1911
|
-
try {
|
|
1912
|
-
const uploaded = await uploadLocalFiles(input.audio_paths, ctx.client);
|
|
1913
|
-
audioUrls = [...audioUrls, ...uploaded].slice(0, 3);
|
|
1914
|
-
} catch (err) {
|
|
1915
|
-
if (err instanceof SkillUploadError) {
|
|
1916
|
-
return { kind: "text", text: `pixeldojo_audio (upload): ${err.userMessage}` };
|
|
1917
|
-
}
|
|
1918
|
-
throw err;
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
2018
|
+
const audioUrls = input.audio_urls ?? [];
|
|
1921
2019
|
const body = { prompt: input.prompt };
|
|
1922
2020
|
if (apiId === "seed-audio") {
|
|
1923
2021
|
if (input.voice) body.voice = input.voice;
|
|
@@ -1950,37 +2048,57 @@ var ALLOWED4, DEFAULT_MODEL6, InputSchema13, InputJsonSchema13, audioSkill;
|
|
|
1950
2048
|
var init_audio = __esm({
|
|
1951
2049
|
"src/skills/audio.ts"() {
|
|
1952
2050
|
init_poll();
|
|
1953
|
-
init_upload_helpers();
|
|
1954
2051
|
init_types();
|
|
1955
2052
|
ALLOWED4 = ["seed-audio", "text-to-speech"];
|
|
1956
2053
|
DEFAULT_MODEL6 = "seed-audio";
|
|
1957
2054
|
InputSchema13 = z.object({
|
|
1958
2055
|
prompt: z.string().min(1).describe(
|
|
1959
|
-
"
|
|
2056
|
+
"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."
|
|
1960
2057
|
),
|
|
1961
|
-
model: z.string().optional().describe(
|
|
1962
|
-
voice: z.string().optional().describe("
|
|
1963
|
-
audio_urls: z.array(z.string().url()).max(3).optional().describe("seed-audio only: up to 3 reference
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
speed: z.number().min(0.5).max(2).optional().describe("Speech speed multiplier (0.5\u20132).")
|
|
2058
|
+
model: 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.`),
|
|
2059
|
+
voice: 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."),
|
|
2060
|
+
audio_urls: z.array(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."),
|
|
2061
|
+
output_format: z.string().optional().describe("Output format. seed-audio: mp3 (default), wav, pcm, ogg_opus. text-to-speech: mp3 (default), wav, flac, pcm."),
|
|
2062
|
+
speed: z.number().min(0.5).max(2).optional().describe("Speech speed multiplier, 0.5-2 (default 1). Both models.")
|
|
1967
2063
|
});
|
|
1968
2064
|
InputJsonSchema13 = {
|
|
1969
2065
|
type: "object",
|
|
1970
2066
|
properties: {
|
|
1971
|
-
prompt: {
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
2067
|
+
prompt: {
|
|
2068
|
+
type: "string",
|
|
2069
|
+
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."
|
|
2070
|
+
},
|
|
2071
|
+
model: {
|
|
2072
|
+
type: "string",
|
|
2073
|
+
enum: ALLOWED4,
|
|
2074
|
+
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.`
|
|
2075
|
+
},
|
|
2076
|
+
voice: {
|
|
2077
|
+
type: "string",
|
|
2078
|
+
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."
|
|
2079
|
+
},
|
|
2080
|
+
audio_urls: {
|
|
2081
|
+
type: "array",
|
|
2082
|
+
items: { type: "string", format: "uri" },
|
|
2083
|
+
maxItems: 3,
|
|
2084
|
+
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."
|
|
2085
|
+
},
|
|
2086
|
+
output_format: {
|
|
2087
|
+
type: "string",
|
|
2088
|
+
description: "Output format. seed-audio: mp3 (default), wav, pcm, ogg_opus. text-to-speech: mp3 (default), wav, flac, pcm."
|
|
2089
|
+
},
|
|
2090
|
+
speed: {
|
|
2091
|
+
type: "number",
|
|
2092
|
+
minimum: 0.5,
|
|
2093
|
+
maximum: 2,
|
|
2094
|
+
description: "Speech speed multiplier, 0.5-2 (default 1). Both models."
|
|
2095
|
+
}
|
|
1978
2096
|
},
|
|
1979
2097
|
required: ["prompt"]
|
|
1980
2098
|
};
|
|
1981
2099
|
audioSkill = {
|
|
1982
2100
|
name: "pixeldojo_audio",
|
|
1983
|
-
description: "Generate audio: speech, multi-character dialogue, sound effects, and background music from one prompt (Seed Audio 1.0 by default; plain
|
|
2101
|
+
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.",
|
|
1984
2102
|
inputZod: InputSchema13,
|
|
1985
2103
|
inputJsonSchema: InputJsonSchema13,
|
|
1986
2104
|
allowedModels: [...ALLOWED4],
|
|
@@ -2017,7 +2135,7 @@ async function run14(input, ctx) {
|
|
|
2017
2135
|
text: `${res.items.length} library item(s):
|
|
2018
2136
|
${lines.join("\n")}
|
|
2019
2137
|
|
|
2020
|
-
Pass any URL back into
|
|
2138
|
+
Pass any URL back into pixeldojo_generate, pixeldojo_edit, pixeldojo_character, or pixeldojo_upscale as a reference input.`
|
|
2021
2139
|
};
|
|
2022
2140
|
}
|
|
2023
2141
|
var InputSchema14, InputJsonSchema14, librarySkill;
|
|
@@ -2032,16 +2150,23 @@ var init_library = __esm({
|
|
|
2032
2150
|
InputJsonSchema14 = {
|
|
2033
2151
|
type: "object",
|
|
2034
2152
|
properties: {
|
|
2035
|
-
q: {
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2153
|
+
q: {
|
|
2154
|
+
type: "string",
|
|
2155
|
+
description: "Substring match against the prompt that produced the asset. Omit to list the newest items."
|
|
2156
|
+
},
|
|
2157
|
+
model: { type: "string", description: "Only assets from this model apiId." },
|
|
2158
|
+
modality: {
|
|
2159
|
+
type: "string",
|
|
2160
|
+
enum: ["image", "video", "audio"],
|
|
2161
|
+
description: "Only this output type."
|
|
2162
|
+
},
|
|
2163
|
+
limit: { type: "integer", minimum: 1, maximum: 50, description: "Max results (default 10)." }
|
|
2039
2164
|
},
|
|
2040
2165
|
required: []
|
|
2041
2166
|
};
|
|
2042
2167
|
librarySkill = {
|
|
2043
2168
|
name: "pixeldojo_library",
|
|
2044
|
-
description: "Search your media library: saved My Media items (permanent) and recent API/MCP generations (
|
|
2169
|
+
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.",
|
|
2045
2170
|
inputZod: InputSchema14,
|
|
2046
2171
|
inputJsonSchema: InputJsonSchema14,
|
|
2047
2172
|
allowedModels: [],
|
|
@@ -2050,52 +2175,6 @@ var init_library = __esm({
|
|
|
2050
2175
|
};
|
|
2051
2176
|
}
|
|
2052
2177
|
});
|
|
2053
|
-
async function run15(input, ctx) {
|
|
2054
|
-
const res = await ctx.client.saveMedia({
|
|
2055
|
-
url: input.url,
|
|
2056
|
-
prompt: input.prompt,
|
|
2057
|
-
tool_name: input.tool_name,
|
|
2058
|
-
modality: input.modality,
|
|
2059
|
-
job_id: input.job_id
|
|
2060
|
-
});
|
|
2061
|
-
return {
|
|
2062
|
-
kind: "text",
|
|
2063
|
-
text: `Saved to My Media (permanent): ${res.url}
|
|
2064
|
-
It will appear at https://pixeldojo.ai/my-images and in pixeldojo_library searches.`
|
|
2065
|
-
};
|
|
2066
|
-
}
|
|
2067
|
-
var InputSchema15, InputJsonSchema15, saveSkill;
|
|
2068
|
-
var init_save = __esm({
|
|
2069
|
-
"src/skills/save.ts"() {
|
|
2070
|
-
InputSchema15 = z.object({
|
|
2071
|
-
url: z.string().url().describe("The asset URL to save (image or video)."),
|
|
2072
|
-
prompt: z.string().optional().describe("The prompt that produced it \u2014 makes it findable in the library later."),
|
|
2073
|
-
tool_name: z.string().optional().describe("Tool/model slug that produced it."),
|
|
2074
|
-
modality: z.enum(["image", "video", "audio"]).optional(),
|
|
2075
|
-
job_id: z.string().optional().describe("The jobId that produced this asset, when known.")
|
|
2076
|
-
});
|
|
2077
|
-
InputJsonSchema15 = {
|
|
2078
|
-
type: "object",
|
|
2079
|
-
properties: {
|
|
2080
|
-
url: { type: "string", format: "uri" },
|
|
2081
|
-
prompt: { type: "string" },
|
|
2082
|
-
tool_name: { type: "string" },
|
|
2083
|
-
modality: { type: "string", enum: ["image", "video", "audio"] },
|
|
2084
|
-
job_id: { type: "string" }
|
|
2085
|
-
},
|
|
2086
|
-
required: ["url"]
|
|
2087
|
-
};
|
|
2088
|
-
saveSkill = {
|
|
2089
|
-
name: "pixeldojo_save",
|
|
2090
|
-
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.",
|
|
2091
|
-
inputZod: InputSchema15,
|
|
2092
|
-
inputJsonSchema: InputJsonSchema15,
|
|
2093
|
-
allowedModels: [],
|
|
2094
|
-
defaultModel: "",
|
|
2095
|
-
run: run15
|
|
2096
|
-
};
|
|
2097
|
-
}
|
|
2098
|
-
});
|
|
2099
2178
|
function substitutePlaceholders(args, inputs, prevUrl) {
|
|
2100
2179
|
const missing = [];
|
|
2101
2180
|
const fill = (value) => {
|
|
@@ -2223,7 +2302,7 @@ async function runWorkflow(input, ctx) {
|
|
|
2223
2302
|
${outputs.join("\n")}`
|
|
2224
2303
|
};
|
|
2225
2304
|
}
|
|
2226
|
-
var WORKFLOW_STEP_EXTRA_BUDGET_MS, StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
|
|
2305
|
+
var WORKFLOW_STEP_EXTRA_BUDGET_MS, StepSchema, SaveInputSchema, RunInputSchema, ListInputSchema, STEP_SKILLS, stepJson, saveWorkflowSkill, runWorkflowSkill, listWorkflowsSkill;
|
|
2227
2306
|
var init_workflows = __esm({
|
|
2228
2307
|
"src/skills/workflows.ts"() {
|
|
2229
2308
|
init_poll();
|
|
@@ -2247,11 +2326,28 @@ var init_workflows = __esm({
|
|
|
2247
2326
|
inputs: z.record(z.string(), z.string()).optional().describe("Values for {{input.<key>}} placeholders in the workflow steps.")
|
|
2248
2327
|
});
|
|
2249
2328
|
ListInputSchema = z.object({});
|
|
2329
|
+
STEP_SKILLS = [
|
|
2330
|
+
"pixeldojo_generate",
|
|
2331
|
+
"pixeldojo_edit",
|
|
2332
|
+
"pixeldojo_character",
|
|
2333
|
+
"pixeldojo_storyboard",
|
|
2334
|
+
"pixeldojo_upscale",
|
|
2335
|
+
"pixeldojo_audio",
|
|
2336
|
+
"pixeldojo_upload",
|
|
2337
|
+
"pixeldojo_from_url"
|
|
2338
|
+
];
|
|
2250
2339
|
stepJson = {
|
|
2251
2340
|
type: "object",
|
|
2252
2341
|
properties: {
|
|
2253
|
-
skill: {
|
|
2254
|
-
|
|
2342
|
+
skill: {
|
|
2343
|
+
type: "string",
|
|
2344
|
+
enum: STEP_SKILLS,
|
|
2345
|
+
description: "Tool this step runs. Steps run in order when the workflow runs, and each is charged at that tool's own rate."
|
|
2346
|
+
},
|
|
2347
|
+
args: {
|
|
2348
|
+
type: "object",
|
|
2349
|
+
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)."
|
|
2350
|
+
}
|
|
2255
2351
|
},
|
|
2256
2352
|
required: ["skill"]
|
|
2257
2353
|
};
|
|
@@ -2262,9 +2358,19 @@ var init_workflows = __esm({
|
|
|
2262
2358
|
inputJsonSchema: {
|
|
2263
2359
|
type: "object",
|
|
2264
2360
|
properties: {
|
|
2265
|
-
name: {
|
|
2266
|
-
|
|
2267
|
-
|
|
2361
|
+
name: {
|
|
2362
|
+
type: "string",
|
|
2363
|
+
pattern: "^[a-z0-9][a-z0-9-]{1,40}$",
|
|
2364
|
+
description: 'Kebab-case handle, 2-41 chars (e.g. "product-launch-pack"). Saving to an existing name overwrites it.'
|
|
2365
|
+
},
|
|
2366
|
+
description: { type: "string", description: "Optional note on what the workflow does (max 500 chars)." },
|
|
2367
|
+
steps: {
|
|
2368
|
+
type: "array",
|
|
2369
|
+
items: stepJson,
|
|
2370
|
+
minItems: 1,
|
|
2371
|
+
maxItems: 8,
|
|
2372
|
+
description: "The chain, 1-8 steps, run in order. Saving charges nothing; running charges each step."
|
|
2373
|
+
}
|
|
2268
2374
|
},
|
|
2269
2375
|
required: ["name", "steps"]
|
|
2270
2376
|
},
|
|
@@ -2279,8 +2385,12 @@ var init_workflows = __esm({
|
|
|
2279
2385
|
inputJsonSchema: {
|
|
2280
2386
|
type: "object",
|
|
2281
2387
|
properties: {
|
|
2282
|
-
name: { type: "string" },
|
|
2283
|
-
inputs: {
|
|
2388
|
+
name: { type: "string", description: "Saved workflow name (see pixeldojo_list_workflows)." },
|
|
2389
|
+
inputs: {
|
|
2390
|
+
type: "object",
|
|
2391
|
+
additionalProperties: { type: "string" },
|
|
2392
|
+
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.`
|
|
2393
|
+
}
|
|
2284
2394
|
},
|
|
2285
2395
|
required: ["name"]
|
|
2286
2396
|
},
|
|
@@ -2304,6 +2414,7 @@ var init_workflows = __esm({
|
|
|
2304
2414
|
var skills_exports = {};
|
|
2305
2415
|
__export(skills_exports, {
|
|
2306
2416
|
ALL_SKILLS: () => ALL_SKILLS,
|
|
2417
|
+
HOSTED_SKILLS: () => HOSTED_SKILLS,
|
|
2307
2418
|
adSkill: () => adSkill,
|
|
2308
2419
|
audioSkill: () => audioSkill,
|
|
2309
2420
|
campaignSkill: () => campaignSkill,
|
|
@@ -2311,24 +2422,28 @@ __export(skills_exports, {
|
|
|
2311
2422
|
characterSkill: () => characterSkill,
|
|
2312
2423
|
editSkill: () => editSkill,
|
|
2313
2424
|
filmSkill: () => filmSkill,
|
|
2425
|
+
findHostedSkill: () => findHostedSkill,
|
|
2314
2426
|
findSkill: () => findSkill,
|
|
2315
2427
|
fromUrlSkill: () => fromUrlSkill,
|
|
2316
2428
|
generateSkill: () => generateSkill,
|
|
2317
2429
|
librarySkill: () => librarySkill,
|
|
2318
2430
|
listWorkflowsSkill: () => listWorkflowsSkill,
|
|
2319
2431
|
runWorkflowSkill: () => runWorkflowSkill,
|
|
2320
|
-
saveSkill: () => saveSkill,
|
|
2321
2432
|
saveWorkflowSkill: () => saveWorkflowSkill,
|
|
2322
2433
|
statusSkill: () => statusSkill,
|
|
2323
2434
|
storyboardSkill: () => storyboardSkill,
|
|
2324
2435
|
uploadSkill: () => uploadSkill,
|
|
2325
2436
|
upscaleSkill: () => upscaleSkill
|
|
2326
2437
|
});
|
|
2438
|
+
function findHostedSkill(name) {
|
|
2439
|
+
const wanted = name.replace(/^pixeldojo:/, "pixeldojo_");
|
|
2440
|
+
return HOSTED_SKILLS.find((s) => s.name === wanted);
|
|
2441
|
+
}
|
|
2327
2442
|
function findSkill(name) {
|
|
2328
2443
|
const wanted = name.replace(/^pixeldojo:/, "pixeldojo_");
|
|
2329
2444
|
return ALL_SKILLS.find((s) => s.name === wanted);
|
|
2330
2445
|
}
|
|
2331
|
-
var ALL_SKILLS;
|
|
2446
|
+
var ALL_SKILLS, isLocalPathField, HOSTED_SKILLS;
|
|
2332
2447
|
var init_skills = __esm({
|
|
2333
2448
|
"src/skills/index.ts"() {
|
|
2334
2449
|
init_generate();
|
|
@@ -2345,7 +2460,6 @@ var init_skills = __esm({
|
|
|
2345
2460
|
init_upload();
|
|
2346
2461
|
init_audio();
|
|
2347
2462
|
init_library();
|
|
2348
|
-
init_save();
|
|
2349
2463
|
init_workflows();
|
|
2350
2464
|
ALL_SKILLS = [
|
|
2351
2465
|
generateSkill,
|
|
@@ -2355,7 +2469,6 @@ var init_skills = __esm({
|
|
|
2355
2469
|
upscaleSkill,
|
|
2356
2470
|
audioSkill,
|
|
2357
2471
|
librarySkill,
|
|
2358
|
-
saveSkill,
|
|
2359
2472
|
saveWorkflowSkill,
|
|
2360
2473
|
runWorkflowSkill,
|
|
2361
2474
|
listWorkflowsSkill,
|
|
@@ -2367,6 +2480,20 @@ var init_skills = __esm({
|
|
|
2367
2480
|
campaignStatusSkill,
|
|
2368
2481
|
filmSkill
|
|
2369
2482
|
];
|
|
2483
|
+
isLocalPathField = (key) => /_paths?$/.test(key);
|
|
2484
|
+
HOSTED_SKILLS = ALL_SKILLS.filter(
|
|
2485
|
+
(s) => s.name !== uploadSkill.name
|
|
2486
|
+
).map((s) => {
|
|
2487
|
+
const props = s.inputJsonSchema.properties ?? {};
|
|
2488
|
+
return {
|
|
2489
|
+
...s,
|
|
2490
|
+
description: s.hostedDescription ?? s.description,
|
|
2491
|
+
inputJsonSchema: {
|
|
2492
|
+
...s.inputJsonSchema,
|
|
2493
|
+
properties: Object.fromEntries(Object.entries(props).filter(([k]) => !isLocalPathField(k)))
|
|
2494
|
+
}
|
|
2495
|
+
};
|
|
2496
|
+
});
|
|
2370
2497
|
}
|
|
2371
2498
|
});
|
|
2372
2499
|
function makeAttributedClient(options) {
|
|
@@ -2420,7 +2547,8 @@ function makeRedactedLogger(target = console) {
|
|
|
2420
2547
|
}
|
|
2421
2548
|
|
|
2422
2549
|
// src/server.ts
|
|
2423
|
-
var PACKAGE_VERSION = "0.
|
|
2550
|
+
var PACKAGE_VERSION = "0.13.0" ;
|
|
2551
|
+
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.";
|
|
2424
2552
|
function buildServer(options) {
|
|
2425
2553
|
if (!options.apiKey) {
|
|
2426
2554
|
throw new Error(
|
|
@@ -2438,7 +2566,8 @@ function buildServer(options) {
|
|
|
2438
2566
|
{
|
|
2439
2567
|
capabilities: {
|
|
2440
2568
|
tools: {}
|
|
2441
|
-
}
|
|
2569
|
+
},
|
|
2570
|
+
instructions: SERVER_INSTRUCTIONS
|
|
2442
2571
|
}
|
|
2443
2572
|
);
|
|
2444
2573
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
@@ -2490,6 +2619,8 @@ function buildServer(options) {
|
|
|
2490
2619
|
apiKey: options.apiKey,
|
|
2491
2620
|
baseUrl,
|
|
2492
2621
|
mcpVersion: version,
|
|
2622
|
+
localFiles: true,
|
|
2623
|
+
// stdio: the caller's own machine
|
|
2493
2624
|
logger,
|
|
2494
2625
|
buildStatusUrl: (jobId) => `${baseUrl}/api/v1/jobs/${encodeURIComponent(jobId)}`
|
|
2495
2626
|
};
|
|
@@ -2561,6 +2692,6 @@ async function runStdio(options) {
|
|
|
2561
2692
|
init_skills();
|
|
2562
2693
|
init_poll();
|
|
2563
2694
|
|
|
2564
|
-
export { ALL_SKILLS, PACKAGE_VERSION, buildServer, errorToActionableMessage, findSkill, makeAttributedClient, makeRedactedLogger, pollJobUntilDoneOrHandoff, redactKeys, redactValue, runStdio, skillResultToMcpResponse };
|
|
2695
|
+
export { ALL_SKILLS, HOSTED_SKILLS, PACKAGE_VERSION, SERVER_INSTRUCTIONS, buildServer, errorToActionableMessage, findHostedSkill, findSkill, makeAttributedClient, makeRedactedLogger, pollJobUntilDoneOrHandoff, redactKeys, redactValue, runStdio, skillResultToMcpResponse };
|
|
2565
2696
|
//# sourceMappingURL=index.js.map
|
|
2566
2697
|
//# sourceMappingURL=index.js.map
|