@pixeldojo/mcp 0.16.1 → 0.16.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -458,6 +458,14 @@ function buildPayload(apiId, input, src, slot, audioSlot) {
458
458
  async function run(input, ctx) {
459
459
  const paramsGate = paramsWithoutModel(input.params, input.model);
460
460
  if (paramsGate) return { kind: "text", text: paramsGate };
461
+ if (input.upgrade_draft) return upgradeDraft(input, ctx);
462
+ if (input.draft && input.model && input.model !== DRAFT_MODEL) {
463
+ return {
464
+ kind: "text",
465
+ text: `Draft mode runs on ${DRAFT_MODEL} only. Drop model (or set it to ${DRAFT_MODEL}) to render a 480p draft.`
466
+ };
467
+ }
468
+ if (input.draft) input = { ...input, model: DRAFT_MODEL, resolution: DRAFT_RESOLUTION };
461
469
  let resolved = input;
462
470
  let referenceUrls = [];
463
471
  try {
@@ -519,6 +527,8 @@ async function run(input, ctx) {
519
527
  }
520
528
  const body = buildPayload(apiId, resolved, src, refField, audioSlot);
521
529
  const paramsNote = applyParams(body, input.params, input.model, apiId);
530
+ const draftDuration = input.draft ? Number(body.duration ?? DRAFT_DEFAULT_DURATION) : void 0;
531
+ if (input.draft) Object.assign(body, { draft: true, resolution: DRAFT_RESOLUTION, duration: draftDuration });
522
532
  const note = [routeNote, paramsNote].filter(Boolean).join(" ");
523
533
  const submitted = await ctx.client.run(apiId, body);
524
534
  const result = await pollJobUntilDoneOrHandoff(
@@ -530,15 +540,45 @@ async function run(input, ctx) {
530
540
  sleep: ctx.pollOverrides?.sleep
531
541
  }
532
542
  );
533
- return prefixNote(
543
+ const out = prefixNote(
534
544
  pollResultToSkillResult(
535
545
  result,
536
546
  (urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : urls.length === 1 ? `Generated. Asset: ${urls[0]}` : `Generated ${urls.length} assets. URLs: ${urls.join(", ")}`
537
547
  ),
538
548
  note
539
549
  );
550
+ return draftDuration === void 0 ? out : { ...out, text: `${out.text}
551
+
552
+ ${draftLine(submitted.jobId, draftDuration)}` };
553
+ }
554
+ function draftLine(jobId, duration) {
555
+ return `This is a 480p draft (draft_job_id: ${jobId}, duration: ${duration}). When the user likes it, call pixeldojo_generate with {"upgrade_draft": "${jobId}", "duration": ${duration}} to render the same take at ${DRAFT_FINAL_RESOLUTION} (billed as a ${DRAFT_FINAL_RESOLUTION} run; upgrade it within a day).`;
556
+ }
557
+ async function upgradeDraft(input, ctx) {
558
+ if (input.duration === void 0) {
559
+ return {
560
+ kind: "text",
561
+ text: `upgrade_draft also needs duration: the draft's own length (its reply says "duration: N"; ${DRAFT_DEFAULT_DURATION} when it was made without one).`
562
+ };
563
+ }
564
+ const submitted = await ctx.client.run(DRAFT_MODEL, {
565
+ draft_job_id: input.upgrade_draft,
566
+ resolution: DRAFT_FINAL_RESOLUTION,
567
+ duration: input.duration
568
+ });
569
+ const result = await pollJobUntilDoneOrHandoff(submitted.jobId, (id) => ctx.client.getJob(id), ctx.buildStatusUrl, {
570
+ now: ctx.pollOverrides?.now,
571
+ sleep: ctx.pollOverrides?.sleep
572
+ });
573
+ return prefixNote(
574
+ pollResultToSkillResult(
575
+ result,
576
+ (urls) => urls.length === 0 ? `Job ${submitted.jobId} completed but returned no assets.` : `Upgraded to ${DRAFT_FINAL_RESOLUTION}. Asset: ${urls[0]}`
577
+ ),
578
+ `Rendering draft ${input.upgrade_draft} at ${DRAFT_FINAL_RESOLUTION}.`
579
+ );
540
580
  }
541
- var InputSchema, DEFAULT_MODEL, VIDEO_REFERENCE_MODEL, VIDEO_REFERENCE_SLOTS, VIDEO_INPUT_MODELS, InputJsonSchema, generateSkill;
581
+ var DRAFT_MODEL, DRAFT_RESOLUTION, DRAFT_FINAL_RESOLUTION, DRAFT_DEFAULT_DURATION, DRAFT_DESCRIPTION, UPGRADE_DESCRIPTION, InputSchema, DEFAULT_MODEL, VIDEO_REFERENCE_MODEL, VIDEO_REFERENCE_SLOTS, VIDEO_INPUT_MODELS, InputJsonSchema, generateSkill;
542
582
  var init_generate = __esm({
543
583
  "src/skills/generate.ts"() {
544
584
  init_poll();
@@ -546,6 +586,12 @@ var init_generate = __esm({
546
586
  init_upload_helpers();
547
587
  init_schema_snap();
548
588
  init_params();
589
+ DRAFT_MODEL = "seedance-2-5";
590
+ DRAFT_RESOLUTION = "480p";
591
+ DRAFT_FINAL_RESOLUTION = "1080p";
592
+ DRAFT_DEFAULT_DURATION = 5;
593
+ DRAFT_DESCRIPTION = "Seedance 2.5 draft mode: render a cheap 480p draft (runs on seedance-2-5) so the user can try takes before paying for full resolution. The reply gives the draft's job id and duration; pass them to upgrade_draft to render that exact take at 1080p.";
594
+ UPGRADE_DESCRIPTION = "Job id of a finished Seedance 2.5 draft to render at 1080p, the same take with full detail. Also pass `duration` equal to the draft's (the draft reply states it). The draft's prompt and media are reused, so prompt and references are ignored. Billed as a 1080p run.";
549
595
  InputSchema = z.object({
550
596
  prompt: z.string().min(1).max(8e3).describe("Prompt describing what to generate."),
551
597
  model: z.string().optional().describe(
@@ -564,6 +610,8 @@ var init_generate = __esm({
564
610
  "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."
565
611
  ),
566
612
  params: ParamsInput,
613
+ draft: z.boolean().optional().describe(DRAFT_DESCRIPTION),
614
+ upgrade_draft: z.string().regex(/^[A-Za-z0-9_-]{1,128}$/).optional().describe(UPGRADE_DESCRIPTION),
567
615
  image_path: z.string().min(1).optional().describe(
568
616
  "Absolute local file path to a reference image/video. The skill uploads it to PixelDojo first (24h temp storage) and then dispatches. Prefer this over image_url when the user has the file on disk."
569
617
  ),
@@ -617,6 +665,8 @@ var init_generate = __esm({
617
665
  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."
618
666
  },
619
667
  params: PARAMS_JSON_SCHEMA,
668
+ draft: { type: "boolean", description: DRAFT_DESCRIPTION },
669
+ upgrade_draft: { type: "string", description: UPGRADE_DESCRIPTION },
620
670
  image_urls: {
621
671
  type: "array",
622
672
  items: { type: "string", format: "uri" },
@@ -636,8 +686,8 @@ var init_generate = __esm({
636
686
  };
637
687
  generateSkill = {
638
688
  name: "pixeldojo_generate",
639
- description: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a prompt runs on seedream-5, which makes still images only. For a video, name seedance-2-5, which works from a prompt alone or a starting image. If a provider refuses the content, retry once on wan-3-0-video (video) or seedream-5 (images), the least-restricted models. For a multi-shot film or a music video synced to a song use pixeldojo_film; to change, move or extend an existing clip use pixeldojo_video. These are the models the PixelDojo studios use; name another only when the user asks for it. 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.",
640
- hostedDescription: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a prompt runs on seedream-5, which makes still images only. For a video, name seedance-2-5, which works from a prompt alone or a starting image. If a provider refuses the content, retry once on wan-3-0-video (video) or seedream-5 (images), the least-restricted models. For a multi-shot film or a music video synced to a song use pixeldojo_film; to change, move or extend an existing clip use pixeldojo_video. These are the models the PixelDojo studios use; name another only when the user asks for it. 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.",
689
+ description: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a prompt runs on seedream-5, which makes still images only. For a video, name seedance-2-5, which works from a prompt alone or a starting image. To try video takes cheaply, set draft: true (a 480p Seedance 2.5 draft), then upgrade_draft the one the user picks to 1080p. If a provider refuses the content, retry once on wan-3-0-video (video) or seedream-5 (images), the least-restricted models. For a multi-shot film or a music video synced to a song use pixeldojo_film; to change, move or extend an existing clip use pixeldojo_video. These are the models the PixelDojo studios use; name another only when the user asks for it. 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.",
690
+ hostedDescription: "Generate an image or video from a prompt with any model in the PixelDojo catalog. With no `model`, a prompt runs on seedream-5, which makes still images only. For a video, name seedance-2-5, which works from a prompt alone or a starting image. To try video takes cheaply, set draft: true (a 480p Seedance 2.5 draft), then upgrade_draft the one the user picks to 1080p. If a provider refuses the content, retry once on wan-3-0-video (video) or seedream-5 (images), the least-restricted models. For a multi-shot film or a music video synced to a song use pixeldojo_film; to change, move or extend an existing clip use pixeldojo_video. These are the models the PixelDojo studios use; name another only when the user asks for it. 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.",
641
691
  inputZod: InputSchema,
642
692
  inputJsonSchema: InputJsonSchema,
643
693
  allowedModels: null,
@@ -3225,7 +3275,7 @@ function makeRedactedLogger(target = console) {
3225
3275
  }
3226
3276
 
3227
3277
  // src/server.ts
3228
- var PACKAGE_VERSION = "0.16.1" ;
3278
+ var PACKAGE_VERSION = "0.16.3" ;
3229
3279
  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.";
3230
3280
  function buildServer(options) {
3231
3281
  if (!options.apiKey) {