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