@pixeldojo/mcp 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +49 -13
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +49 -13
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +50 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +50 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1408,13 +1408,13 @@ function progressLine(f) {
|
|
|
1408
1408
|
const rendering = all.filter((sh) => sh.status === "clip-generating").length;
|
|
1409
1409
|
return `frames ${frames}/${all.length}, clips ${clips}/${all.length}${rendering > 0 ? ` (${rendering} rendering)` : ""}`;
|
|
1410
1410
|
}
|
|
1411
|
-
async function runPlanner(ctx, filmId, path, body) {
|
|
1411
|
+
async function runPlanner(ctx, filmId, path, body, maxPolls = PLANNER_MAX_POLLS) {
|
|
1412
1412
|
const submit = await filmApi(ctx, "POST", path, body);
|
|
1413
1413
|
if (submit.data.film) return { film: submit.data.film };
|
|
1414
1414
|
const jobId = submit.data.jobId;
|
|
1415
1415
|
if (!jobId) return { error: submit.data.error ?? `HTTP ${submit.status}` };
|
|
1416
1416
|
const sleep = ctx.pollOverrides?.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
1417
|
-
for (let i = 0; i <
|
|
1417
|
+
for (let i = 0; i < maxPolls; i += 1) {
|
|
1418
1418
|
await sleep(PLANNER_POLL_MS);
|
|
1419
1419
|
const { data } = await filmApi(ctx, "GET", `/api/films/${filmId}`);
|
|
1420
1420
|
const job = data.film?.llmJob;
|
|
@@ -1483,7 +1483,7 @@ ${input.lyrics.trim()}` : ""].filter(Boolean).join("\n\n");
|
|
|
1483
1483
|
let script = input.script?.trim() ?? "";
|
|
1484
1484
|
if (!script) {
|
|
1485
1485
|
const wrote = await runPlanner(ctx, id, `/api/films/${id}/script`, { idea: input.idea.trim() });
|
|
1486
|
-
if ("pending" in wrote) return { kind: "text", text: stillPlanningText(id) };
|
|
1486
|
+
if ("pending" in wrote) return { kind: "text", text: stillPlanningText(id, "script") };
|
|
1487
1487
|
if ("error" in wrote) return { kind: "text", text: `Script writing failed: ${wrote.error}` };
|
|
1488
1488
|
script = wrote.film.script ?? "";
|
|
1489
1489
|
if (!script) return { kind: "text", text: "Script writing failed: the studio returned an empty script." };
|
|
@@ -1503,12 +1503,14 @@ ${err} Call action "status" to retry the cut.` };
|
|
|
1503
1503
|
}
|
|
1504
1504
|
async function resumePlanning(film, ctx) {
|
|
1505
1505
|
if (film.scenes.length > 0 && film.llmJob?.status !== "running") return null;
|
|
1506
|
-
if (film.llmJob?.status === "running")
|
|
1506
|
+
if (film.llmJob?.status === "running") {
|
|
1507
|
+
return { kind: "text", text: stillPlanningText(film.id, film.llmJob.kind === "script" ? "script" : "plan") };
|
|
1508
|
+
}
|
|
1507
1509
|
const prior = film.llmJob?.status === "error" ? `The last planning run failed (${film.llmJob.error ?? "unknown"}). ` : "";
|
|
1508
1510
|
if (!film.script?.trim()) {
|
|
1509
1511
|
return { kind: "text", text: `${prior}This film has nothing to plan from. Start a new one with action "plan".` };
|
|
1510
1512
|
}
|
|
1511
|
-
const planned = await runPlanner(ctx, film.id, `/api/films/${film.id}/plan`, { script: film.script });
|
|
1513
|
+
const planned = await runPlanner(ctx, film.id, `/api/films/${film.id}/plan`, { script: film.script }, 0);
|
|
1512
1514
|
if ("pending" in planned) return { kind: "text", text: `${prior}${stillPlanningText(film.id)}` };
|
|
1513
1515
|
if ("error" in planned) return { kind: "text", text: `Shot planning failed: ${planned.error} Call action "status" to retry.` };
|
|
1514
1516
|
if (needsSlice(planned.film)) {
|
|
@@ -1594,6 +1596,9 @@ It is saved in the Library folder "Film: ${film.title}".`
|
|
|
1594
1596
|
if (err) return { kind: "text", text: `${err} Poll again with action "status" to retry.` };
|
|
1595
1597
|
return { kind: "text", text: `Song cut into one slice per shot. Poll again with {"film_id": "${filmId}", "action": "status"} to keep production moving.` };
|
|
1596
1598
|
}
|
|
1599
|
+
if (shots(film).length > 0 && shots(film).every((sh) => sh.status === "idle")) {
|
|
1600
|
+
return { kind: "text", text: plannedText(film, ctx) };
|
|
1601
|
+
}
|
|
1597
1602
|
const idleFrames = all.filter((sh) => sh.status === "idle");
|
|
1598
1603
|
for (const sh of idleFrames.slice(0, 6)) {
|
|
1599
1604
|
await filmApi(ctx, "POST", `/api/films/${filmId}/shots/${sh.id}/generate`, { kind: "frame" });
|
|
@@ -1719,7 +1724,7 @@ var init_film = __esm({
|
|
|
1719
1724
|
PLANNER_MAX_POLLS = 8;
|
|
1720
1725
|
isMusicVideo = (f) => f.musicVideoMode === true;
|
|
1721
1726
|
needsSlice = (f) => isMusicVideo(f) && shots(f).length > 0 && !shots(f).some((sh) => sh.musicChunkUrl);
|
|
1722
|
-
stillPlanningText = (filmId) =>
|
|
1727
|
+
stillPlanningText = (filmId, stage = "plan") => `${stage === "script" ? "Still writing the script" : "Still planning the shots"} for film_id ${filmId}. Nothing has been charged. Call pixeldojo_film with {"film_id": "${filmId}", "action": "status"} in ~30s; it returns the plan once it is ready.`;
|
|
1723
1728
|
LOOK_MUSIC = {
|
|
1724
1729
|
"live-action": "modern cinematic underscore, warm strings and soft felt piano, subtle rhythmic pulse, slow emotional build",
|
|
1725
1730
|
anime: "sweeping anime film score, lush strings and piano, taiko drum accents, soaring heartfelt theme",
|
|
@@ -3045,6 +3050,7 @@ var skills_exports = {};
|
|
|
3045
3050
|
__export(skills_exports, {
|
|
3046
3051
|
ALL_SKILLS: () => ALL_SKILLS,
|
|
3047
3052
|
HOSTED_SKILLS: () => HOSTED_SKILLS,
|
|
3053
|
+
TOOL_ANNOTATIONS: () => TOOL_ANNOTATIONS,
|
|
3048
3054
|
adSkill: () => adSkill,
|
|
3049
3055
|
audioSkill: () => audioSkill,
|
|
3050
3056
|
campaignSkill: () => campaignSkill,
|
|
@@ -3063,10 +3069,21 @@ __export(skills_exports, {
|
|
|
3063
3069
|
saveWorkflowSkill: () => saveWorkflowSkill,
|
|
3064
3070
|
statusSkill: () => statusSkill,
|
|
3065
3071
|
storyboardSkill: () => storyboardSkill,
|
|
3072
|
+
toolListing: () => toolListing,
|
|
3066
3073
|
uploadSkill: () => uploadSkill,
|
|
3067
3074
|
upscaleSkill: () => upscaleSkill,
|
|
3068
3075
|
videoSkill: () => videoSkill
|
|
3069
3076
|
});
|
|
3077
|
+
function toolListing(skill) {
|
|
3078
|
+
const { title, ...hints } = TOOL_ANNOTATIONS[skill.name];
|
|
3079
|
+
return {
|
|
3080
|
+
name: skill.name,
|
|
3081
|
+
title,
|
|
3082
|
+
description: skill.description,
|
|
3083
|
+
inputSchema: skill.inputJsonSchema,
|
|
3084
|
+
annotations: { title, ...hints }
|
|
3085
|
+
};
|
|
3086
|
+
}
|
|
3070
3087
|
function findHostedSkill(name) {
|
|
3071
3088
|
const wanted = name.replace(/^pixeldojo:/, "pixeldojo_");
|
|
3072
3089
|
return HOSTED_SKILLS.find((s) => s.name === wanted);
|
|
@@ -3075,7 +3092,7 @@ function findSkill(name) {
|
|
|
3075
3092
|
const wanted = name.replace(/^pixeldojo:/, "pixeldojo_");
|
|
3076
3093
|
return ALL_SKILLS.find((s) => s.name === wanted);
|
|
3077
3094
|
}
|
|
3078
|
-
var ALL_SKILLS, isLocalPathField, HOSTED_SKILLS;
|
|
3095
|
+
var ALL_SKILLS, isLocalPathField, HOSTED_SKILLS, render, read, TOOL_ANNOTATIONS;
|
|
3079
3096
|
var init_skills = __esm({
|
|
3080
3097
|
"src/skills/index.ts"() {
|
|
3081
3098
|
init_generate();
|
|
@@ -3130,6 +3147,29 @@ var init_skills = __esm({
|
|
|
3130
3147
|
}
|
|
3131
3148
|
};
|
|
3132
3149
|
});
|
|
3150
|
+
render = (title) => ({ title, readOnlyHint: false, destructiveHint: false, openWorldHint: false });
|
|
3151
|
+
read = (title) => ({ title, readOnlyHint: true, destructiveHint: false, openWorldHint: false });
|
|
3152
|
+
TOOL_ANNOTATIONS = {
|
|
3153
|
+
pixeldojo_generate: render("Generate image or video"),
|
|
3154
|
+
pixeldojo_edit: render("Edit image"),
|
|
3155
|
+
pixeldojo_character: render("Consistent character image"),
|
|
3156
|
+
pixeldojo_storyboard: render("Storyboard preview video"),
|
|
3157
|
+
pixeldojo_upscale: render("Upscale image or video"),
|
|
3158
|
+
pixeldojo_audio: render("Generate music, speech or sound"),
|
|
3159
|
+
pixeldojo_video: render("Change, animate or extend video"),
|
|
3160
|
+
pixeldojo_ad: render("Make video ad"),
|
|
3161
|
+
pixeldojo_campaign: render("Make product launch campaign"),
|
|
3162
|
+
pixeldojo_film: render("Make short film"),
|
|
3163
|
+
pixeldojo_episode: render("Make faceless video"),
|
|
3164
|
+
pixeldojo_run_workflow: render("Run saved workflow"),
|
|
3165
|
+
pixeldojo_upload: render("Upload local file"),
|
|
3166
|
+
pixeldojo_save_workflow: { ...render("Save workflow"), destructiveHint: true },
|
|
3167
|
+
pixeldojo_status: read("Check job status"),
|
|
3168
|
+
pixeldojo_campaign_status: read("Check campaign status"),
|
|
3169
|
+
pixeldojo_library: read("Search media library"),
|
|
3170
|
+
pixeldojo_list_workflows: read("List saved workflows"),
|
|
3171
|
+
pixeldojo_from_url: { ...read("Read product page"), openWorldHint: true }
|
|
3172
|
+
};
|
|
3133
3173
|
}
|
|
3134
3174
|
});
|
|
3135
3175
|
function makeAttributedClient(options) {
|
|
@@ -3183,7 +3223,7 @@ function makeRedactedLogger(target = console) {
|
|
|
3183
3223
|
}
|
|
3184
3224
|
|
|
3185
3225
|
// src/server.ts
|
|
3186
|
-
var PACKAGE_VERSION = "0.
|
|
3226
|
+
var PACKAGE_VERSION = "0.16.0" ;
|
|
3187
3227
|
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.";
|
|
3188
3228
|
function buildServer(options) {
|
|
3189
3229
|
if (!options.apiKey) {
|
|
@@ -3208,11 +3248,7 @@ function buildServer(options) {
|
|
|
3208
3248
|
);
|
|
3209
3249
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
3210
3250
|
return {
|
|
3211
|
-
tools: ALL_SKILLS.map(
|
|
3212
|
-
name: skill.name,
|
|
3213
|
-
description: skill.description,
|
|
3214
|
-
inputSchema: skill.inputJsonSchema
|
|
3215
|
-
}))
|
|
3251
|
+
tools: ALL_SKILLS.map(toolListing)
|
|
3216
3252
|
};
|
|
3217
3253
|
});
|
|
3218
3254
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|