makaron-cli 0.13.8 → 0.13.9
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +11 -1
- package/bin/makaron.mjs +129 -9
- package/package.json +1 -1
- package/skills/makaron/SKILL.md +3 -2
package/README.md
CHANGED
|
@@ -377,7 +377,7 @@ For project/timeline video editing, use:
|
|
|
377
377
|
npx makaron-cli chat --project <id|auto> --video input.mp4 -b "make it funny"
|
|
378
378
|
```
|
|
379
379
|
|
|
380
|
-
Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to the selected model limit), `--video <file|url>` and `--audio <file|url>` (repeatable where supported), `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3`, `--video-resolution auto|480p|720p|768p|1080p|2k|4k`. Default model is `seedance-fast`. SeeDance accepts native text-to-video with no image and integer output duration 4-15s (default 5s); `seedance-mini` supports 480p/720p and is best for cheaper drafts/multi-size tests; MiniMax H3 accepts native text-to-video, 4-15s output, public 768p/2k resolution, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. H3 defaults to 768p; request 2k explicitly for maximum/final quality. Kling supports 5-15s; Grok 1.5 supports 1-15s single-image-to-video only; Gemini Omni supports 3-10s fast 720p image/video generation and editing with native generated audio, including up to 6 image references when no video reference is provided. For `--video-model grok`, forced `--aspect` is ignored to avoid xAI stretching the source image; pad/create the image at the target shape first or use another model.
|
|
380
|
+
Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to the selected model limit), `--video <file|url>` and `--audio <file|url>` (repeatable where supported), `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3|sync-lipsync-v3`, `--video-resolution auto|480p|720p|768p|1080p|2k|4k`. Default model is `seedance-fast`. SeeDance accepts native text-to-video with no image and integer output duration 4-15s (default 5s); `seedance-mini` supports 480p/720p and is best for cheaper drafts/multi-size tests; MiniMax H3 accepts native text-to-video, 4-15s output, public 768p/2k resolution, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. `sync-lipsync-v3` requires exactly one video plus one MP3/WAV and preserves that replacement audio while aligning the mouth. H3 defaults to 768p; request 2k explicitly for maximum/final quality. Kling supports 5-15s; Grok 1.5 supports 1-15s single-image-to-video only; Gemini Omni supports 3-10s fast 720p image/video generation and editing with native generated audio, including up to 6 image references when no video reference is provided. For `--video-model grok`, forced `--aspect` is ignored to avoid xAI stretching the source image; pad/create the image at the target shape first or use another model.
|
|
381
381
|
|
|
382
382
|
Seedance 2.5: use `--video-model seedance-2.5` for 4-30 second output at 480p/720p. `--image` accepts local files or URLs (up to 30), while repeatable `--video` and `--audio` accept up to 10 each. Use `--video-operation generate|edit|extend`, `--extend-direction forward|backward`, `--output-format mp4|mov`, `--web-search`, `--generated-audio` / `--no-generated-audio`, and `--relaxed-content-filter`. Edit/extend require a video reference. The Evolink route does not currently expose 4K output.
|
|
383
383
|
|
|
@@ -428,6 +428,7 @@ type CompletionAction = {
|
|
|
428
428
|
3. Stop when `status` is `"completed"`, `"failed"`, or `"aborted"`
|
|
429
429
|
4. Top-level `status: "completed"` means ALL artifacts are ready (including rendered videos)
|
|
430
430
|
5. If an async video fails, top-level `status` is `"failed"` and the failed video may include `completion_actions` for a safe retry or diagnosis. Agents can surface these as the next user-confirmed step.
|
|
431
|
+
6. `responses get --wait` reconciles pending video output against completed Project Media with the same `snapshot_id` or `task_id`. A lagging Run row therefore does not block delivery after the durable project video is ready.
|
|
431
432
|
|
|
432
433
|
## Exit Codes
|
|
433
434
|
|
|
@@ -508,6 +509,15 @@ send_message "All done!"
|
|
|
508
509
|
|
|
509
510
|
Admin commands require an API key with admin privileges. Ask your admin to run `makaron admin set-admin <your-email>` to grant access.
|
|
510
511
|
|
|
512
|
+
### Add credits to a user
|
|
513
|
+
|
|
514
|
+
Use either the account email address or the Supabase user UUID. Credits must be a positive integer.
|
|
515
|
+
|
|
516
|
+
```bash
|
|
517
|
+
npx makaron-cli admin add-credits user@example.com 1000
|
|
518
|
+
npx makaron-cli admin add-credits <user-id> 1000 --json
|
|
519
|
+
```
|
|
520
|
+
|
|
511
521
|
### List all marketplace skills
|
|
512
522
|
|
|
513
523
|
```bash
|
package/bin/makaron.mjs
CHANGED
|
@@ -328,6 +328,86 @@ function normalizeRunResponse(data) {
|
|
|
328
328
|
return data;
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
+
function projectMediaIdentity(item) {
|
|
332
|
+
const snapshotId = item?.snapshot_id || item?.snapshotId;
|
|
333
|
+
const taskId = item?.task_id || item?.taskId;
|
|
334
|
+
return {
|
|
335
|
+
snapshotId: typeof snapshotId === 'string' && snapshotId ? snapshotId : null,
|
|
336
|
+
taskId: typeof taskId === 'string' && taskId ? taskId : null,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function findMatchingCompletedProjectVideo(item, media) {
|
|
341
|
+
const identity = projectMediaIdentity(item);
|
|
342
|
+
if (!identity.snapshotId && !identity.taskId) return null;
|
|
343
|
+
return (media || []).find(candidate => {
|
|
344
|
+
if (candidate?.type !== 'video' || candidate?.status !== 'completed' || !candidate?.url) return false;
|
|
345
|
+
const candidateIdentity = projectMediaIdentity(candidate);
|
|
346
|
+
return (identity.snapshotId && candidateIdentity.snapshotId === identity.snapshotId)
|
|
347
|
+
|| (identity.taskId && candidateIdentity.taskId === identity.taskId);
|
|
348
|
+
}) || null;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async function reconcileRunWithProjectMedia(baseUrl, headers, data) {
|
|
352
|
+
normalizeRunResponse(data);
|
|
353
|
+
const output = Array.isArray(data.output) ? data.output : [];
|
|
354
|
+
const pendingVideos = output.filter(item =>
|
|
355
|
+
item?.type === 'video' && (item.status === 'queued' || item.status === 'rendering')
|
|
356
|
+
);
|
|
357
|
+
const agentDone = data.agent_status === 'completed'
|
|
358
|
+
|| (data.status === 'in_progress' && data.incomplete === true);
|
|
359
|
+
if (!agentDone || pendingVideos.length === 0 || !data.projectId) return data;
|
|
360
|
+
|
|
361
|
+
let projectMedia;
|
|
362
|
+
try {
|
|
363
|
+
const res = await fetch(`${baseUrl}/api/projects/${data.projectId}/media`, { headers });
|
|
364
|
+
if (!res.ok) return data;
|
|
365
|
+
projectMedia = await res.json();
|
|
366
|
+
} catch {
|
|
367
|
+
return data;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
let reconciled = false;
|
|
371
|
+
for (const item of pendingVideos) {
|
|
372
|
+
const completed = findMatchingCompletedProjectVideo(item, projectMedia.media);
|
|
373
|
+
if (!completed) continue;
|
|
374
|
+
const identity = projectMediaIdentity(completed);
|
|
375
|
+
item.status = 'completed';
|
|
376
|
+
item.url = completed.url;
|
|
377
|
+
if (identity.snapshotId) item.snapshot_id = identity.snapshotId;
|
|
378
|
+
if (identity.taskId) item.task_id = identity.taskId;
|
|
379
|
+
if (completed.posterUrl) item.poster_url = completed.posterUrl;
|
|
380
|
+
for (const field of ['duration', 'width', 'height']) {
|
|
381
|
+
if (typeof completed[field] === 'number') item[field] = completed[field];
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const legacyVideos = Array.isArray(data.result?.videos) ? data.result.videos : [];
|
|
385
|
+
const legacy = legacyVideos.find(video => {
|
|
386
|
+
const legacyIdentity = projectMediaIdentity(video);
|
|
387
|
+
return (identity.snapshotId && legacyIdentity.snapshotId === identity.snapshotId)
|
|
388
|
+
|| (identity.taskId && legacyIdentity.taskId === identity.taskId);
|
|
389
|
+
});
|
|
390
|
+
if (legacy) {
|
|
391
|
+
legacy.status = 'completed';
|
|
392
|
+
legacy.videoUrl = completed.url;
|
|
393
|
+
if (identity.snapshotId && !legacy.snapshotId) legacy.snapshotId = identity.snapshotId;
|
|
394
|
+
}
|
|
395
|
+
reconciled = true;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (!reconciled) return data;
|
|
399
|
+
const pendingArtifacts = output.some(item =>
|
|
400
|
+
(item?.type === 'video' || item?.type === 'music')
|
|
401
|
+
&& (item.status === 'queued' || item.status === 'rendering')
|
|
402
|
+
);
|
|
403
|
+
if (!pendingArtifacts) {
|
|
404
|
+
data.status = 'completed';
|
|
405
|
+
data.incomplete = false;
|
|
406
|
+
delete data.next_poll_after_ms;
|
|
407
|
+
}
|
|
408
|
+
return data;
|
|
409
|
+
}
|
|
410
|
+
|
|
331
411
|
function collectCompletionActions(data) {
|
|
332
412
|
const items = [];
|
|
333
413
|
const add = (action, source) => {
|
|
@@ -612,6 +692,7 @@ async function pollRun(baseUrl, headers, runId, opts = {}) {
|
|
|
612
692
|
continue;
|
|
613
693
|
}
|
|
614
694
|
data = await res.json();
|
|
695
|
+
data = await reconcileRunWithProjectMedia(baseUrl, headers, data);
|
|
615
696
|
} catch {
|
|
616
697
|
continue;
|
|
617
698
|
}
|
|
@@ -764,6 +845,7 @@ async function watchRun(baseUrl, headers, runId, opts = {}) {
|
|
|
764
845
|
continue;
|
|
765
846
|
}
|
|
766
847
|
data = await res.json();
|
|
848
|
+
data = await reconcileRunWithProjectMedia(baseUrl, headers, data);
|
|
767
849
|
} catch {
|
|
768
850
|
await new Promise(r => setTimeout(r, interval));
|
|
769
851
|
continue;
|
|
@@ -1791,7 +1873,7 @@ Commands:
|
|
|
1791
1873
|
video script|create|status Video generation
|
|
1792
1874
|
music create|status Music generation
|
|
1793
1875
|
|
|
1794
|
-
admin Admin commands (skills, upload, set-admin)
|
|
1876
|
+
admin Admin commands (skills, credits, upload, set-admin)
|
|
1795
1877
|
|
|
1796
1878
|
Examples:
|
|
1797
1879
|
makaron chat --project auto "plan a launch poster"
|
|
@@ -1928,7 +2010,7 @@ Not sure which built-in skill to use? Start with:
|
|
|
1928
2010
|
console.log('Usage: makaron analyze --video <file|url> ["question"]');
|
|
1929
2011
|
} else if (topic === 'video') {
|
|
1930
2012
|
if (subtopic === 'script') console.log('Usage: makaron video script --image <file> [--image <file>] [--lang en|zh] "direction"');
|
|
1931
|
-
else if (subtopic === 'create') console.log('Usage: makaron video create --script "..." [--image <url> ...] [--video <url> ...] [--audio <url> ...] [--duration 10] [--aspect 9:16] [--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3] [--operation generate|edit|extend] [--video-resolution auto|480p|720p|768p|1080p|2k|4k] [--keep-original-sound]');
|
|
2013
|
+
else if (subtopic === 'create') console.log('Usage: makaron video create --script "..." [--image <url> ...] [--video <url> ...] [--audio <url> ...] [--duration 10] [--aspect 9:16] [--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3|sync-lipsync-v3] [--operation generate|edit|extend] [--video-resolution auto|480p|720p|768p|1080p|2k|4k] [--keep-original-sound]');
|
|
1932
2014
|
else if (subtopic === 'status') console.log('Usage: makaron video status <taskId> | --snapshot <snapshotId> [--wait]');
|
|
1933
2015
|
else console.log(`Video commands:
|
|
1934
2016
|
video script --image <file> [--image <file>] "direction" Write video script
|
|
@@ -1936,6 +2018,7 @@ Not sure which built-in skill to use? Start with:
|
|
|
1936
2018
|
video create --script "..." --video-model minimax-h3 MiniMax H3 text-to-video (default 768P)
|
|
1937
2019
|
video create --script "..." --image <url> [--duration 10] Submit video task
|
|
1938
2020
|
video create --script "..." --video <public-url> [--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|google-omni|minimax-h3] Edit/reference a video (Grok does not support video refs)
|
|
2021
|
+
video create --script "Use the supplied audio" --video <url> --audio <url> --video-model sync-lipsync-v3 Lip-sync exact replacement audio
|
|
1939
2022
|
video status <taskId> Check video status
|
|
1940
2023
|
video status --snapshot <snapshotId> [--wait] Check v2 video snapshot
|
|
1941
2024
|
`);
|
|
@@ -1951,6 +2034,7 @@ Not sure which built-in skill to use? Start with:
|
|
|
1951
2034
|
else if (subtopic === 'skill-categories') console.log('Usage: makaron admin skill-categories [--json|add|update|delete] ...');
|
|
1952
2035
|
else if (subtopic === 'upload') console.log('Usage: makaron admin upload <local-file> <storage-path>');
|
|
1953
2036
|
else if (subtopic === 'fetch-skill') console.log('Usage: makaron admin fetch-skill <share-code|url>');
|
|
2037
|
+
else if (subtopic === 'add-credits') console.log('Usage: makaron admin add-credits <email-or-user-id> <credits> [--json]');
|
|
1954
2038
|
else if (subtopic === 'set-admin') console.log('Usage: makaron admin set-admin <email>');
|
|
1955
2039
|
else console.log(`Admin commands:
|
|
1956
2040
|
admin skills List all marketplace skills
|
|
@@ -1963,6 +2047,7 @@ Not sure which built-in skill to use? Start with:
|
|
|
1963
2047
|
admin skill-categories delete <id> Delete a category
|
|
1964
2048
|
admin upload <file> <storage-path> Upload file to Storage
|
|
1965
2049
|
admin fetch-skill <code|url> Download skill from share link
|
|
2050
|
+
admin add-credits <user> <credits> Add credits by email or user ID
|
|
1966
2051
|
admin set-admin <email> Grant admin access to a user
|
|
1967
2052
|
`);
|
|
1968
2053
|
} else if (topic === 'register') {
|
|
@@ -2398,7 +2483,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2398
2483
|
const res = await fetch(`${baseUrl}/api/agent/run/${runId}`, { headers });
|
|
2399
2484
|
if (!res.ok) { process.stderr.write(`Error ${res.status}: ${await res.text()}\n`); process.exit(1); }
|
|
2400
2485
|
let data = await res.json();
|
|
2401
|
-
|
|
2486
|
+
data = await reconcileRunWithProjectMedia(baseUrl, headers, data);
|
|
2402
2487
|
if (exportCompositions && data.status === 'completed') {
|
|
2403
2488
|
data = await exportAnimatedCompositionsFromRun(baseUrl, headers, data, { publish: publishExports, quiet: jsonOutput || !!pick });
|
|
2404
2489
|
}
|
|
@@ -2768,6 +2853,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2768
2853
|
const isSeedance25 = selectedVideoModel === 'seedance-2.5';
|
|
2769
2854
|
const isSeedanceModel = selectedVideoModel === 'seedance-fast' || selectedVideoModel === 'seedance-mini' || selectedVideoModel === 'seedance' || isSeedance25;
|
|
2770
2855
|
const isMinimaxH3 = selectedVideoModel === 'minimax-h3';
|
|
2856
|
+
const isSyncLipsync = selectedVideoModel === 'sync-lipsync-v3';
|
|
2771
2857
|
const supportsNativeTextToVideo = isSeedanceModel || isMinimaxH3;
|
|
2772
2858
|
if (!script || (!images.length && !videos.length && !audios.length && !supportsNativeTextToVideo)) {
|
|
2773
2859
|
console.error('Usage: makaron video create --script "..." [--image <url>] [--video <file|url>] [--audio <file|url>] [--duration 30] [--video-model seedance-2.5|minimax-h3]');
|
|
@@ -2779,6 +2865,10 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2779
2865
|
if (isMinimaxH3 && images.length > 9) { console.error('MiniMax H3 supports at most 9 image references.'); process.exit(1); }
|
|
2780
2866
|
if (isMinimaxH3 && videos.length > 3) { console.error('MiniMax H3 supports at most 3 video references.'); process.exit(1); }
|
|
2781
2867
|
if (isMinimaxH3 && audios.length > 3) { console.error('MiniMax H3 supports at most 3 audio references.'); process.exit(1); }
|
|
2868
|
+
if (isSyncLipsync && (images.length !== 0 || videos.length !== 1 || audios.length !== 1)) { console.error('Sync Lipsync v3 requires exactly one --video and one --audio, with no --image.'); process.exit(1); }
|
|
2869
|
+
if (isSyncLipsync && !/<<<audio_1>>>/i.test(script)) {
|
|
2870
|
+
script += '\nUse <<<audio_1>>> as the exact replacement soundtrack.';
|
|
2871
|
+
}
|
|
2782
2872
|
if (videoOperation && !['generate', 'edit', 'extend'].includes(videoOperation)) { console.error('--video-operation must be generate, edit, or extend.'); process.exit(1); }
|
|
2783
2873
|
if (extendDirection && !['forward', 'backward'].includes(extendDirection)) { console.error('--extend-direction must be forward or backward.'); process.exit(1); }
|
|
2784
2874
|
if (outputFormat && !['mp4', 'mov'].includes(outputFormat)) { console.error('--output-format must be mp4 or mov.'); process.exit(1); }
|
|
@@ -2788,8 +2878,9 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2788
2878
|
process.exit(1);
|
|
2789
2879
|
}
|
|
2790
2880
|
|
|
2791
|
-
|
|
2792
|
-
|
|
2881
|
+
let providerMaxDuration = isSeedance25 ? SEEDANCE25_MAX_VIDEO_REFERENCE_DURATION : MAX_VIDEO_PROVIDER_REFERENCE_DURATION;
|
|
2882
|
+
if (isSyncLipsync) providerMaxDuration = 60;
|
|
2883
|
+
const providerMaxPixels = isSyncLipsync || isMinimaxH3 ? Infinity : isSeedance25 ? SEEDANCE25_MAX_VIDEO_FRAME_PIXELS : MAX_VIDEO_FRAME_PIXELS;
|
|
2793
2884
|
const localImages = images.filter(image => !isHttpUrl(image));
|
|
2794
2885
|
if (localImages.length) {
|
|
2795
2886
|
const uploadedImages = await uploadImageFilesViaSignedUrl(baseUrl, headers, undefined, localImages);
|
|
@@ -2804,7 +2895,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2804
2895
|
maxDuration: providerMaxDuration,
|
|
2805
2896
|
durationTolerance: MAX_VIDEO_PROVIDER_REFERENCE_DURATION_TOLERANCE,
|
|
2806
2897
|
maxFramePixels: providerMaxPixels,
|
|
2807
|
-
maxFileSize: isSeedance25 ? 200 * 1024 * 1024 : MAX_VIDEO_UPLOAD_FILE_SIZE,
|
|
2898
|
+
maxFileSize: isSeedance25 || isSyncLipsync ? 200 * 1024 * 1024 : MAX_VIDEO_UPLOAD_FILE_SIZE,
|
|
2808
2899
|
...(selectedVideoModel === 'minimax-h3' ? {
|
|
2809
2900
|
allowedExtensions: ['mp4', 'mov'],
|
|
2810
2901
|
minSide: MINIMAX_H3_MIN_VIDEO_SIDE,
|
|
@@ -2830,7 +2921,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2830
2921
|
const audioUrls = [];
|
|
2831
2922
|
for (const audio of audios) {
|
|
2832
2923
|
if (isHttpUrl(audio)) { audioUrls.push(audio); continue; }
|
|
2833
|
-
const valid = validateAudioReferenceFile(audio, { maxDuration: isSeedance25 ? 30 : MAX_AUDIO_REFERENCE_DURATION });
|
|
2924
|
+
const valid = validateAudioReferenceFile(audio, { maxDuration: isSyncLipsync ? 60 : isSeedance25 ? 30 : MAX_AUDIO_REFERENCE_DURATION });
|
|
2834
2925
|
if (!valid.ok) { console.error(`❌ ${valid.error}`); process.exit(1); }
|
|
2835
2926
|
process.stderr.write(`🎵 Uploading ${path.basename(audio)}...\n`);
|
|
2836
2927
|
const uploaded = await uploadFileViaSignedUrl(baseUrl, headers, undefined, audio, valid.mime, { uploadKind: 'audio' });
|
|
@@ -2840,7 +2931,9 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2840
2931
|
// Standalone MCP tool (no project timeline write)
|
|
2841
2932
|
process.stderr.write('🎬 Submitting video...\n');
|
|
2842
2933
|
const resolvedOperation = videoOperation || (isSeedance25 && videoUrls.length ? 'edit' : 'generate');
|
|
2843
|
-
const vArgs =
|
|
2934
|
+
const vArgs = isSyncLipsync
|
|
2935
|
+
? { script, images, videoUrls, audioUrls, videoModel: selectedVideoModel, videoResolution }
|
|
2936
|
+
: isSeedance25
|
|
2844
2937
|
? { script, images, videoUrls, audioUrls, videoModel: selectedVideoModel, videoResolution, operation: resolvedOperation, extendDirection, outputFormat, generateAudio, contentFilter, webSearch }
|
|
2845
2938
|
: isMinimaxH3
|
|
2846
2939
|
? { script, images, videoUrls, audioUrls, videoModel: selectedVideoModel, videoResolution }
|
|
@@ -2851,7 +2944,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2851
2944
|
if (effectiveDuration) vArgs.duration = effectiveDuration;
|
|
2852
2945
|
if (aspectRatio) vArgs.aspectRatio = aspectRatio;
|
|
2853
2946
|
if (keepOriginalSound && videoUrls.length && !isSeedance25) vArgs.keepOriginalSound = true;
|
|
2854
|
-
const result = await callMcpTool(baseUrl, headers, videoUrls.length && !isSeedance25 && !isMinimaxH3 ? 'makaron_edit_video' : 'makaron_create_video', vArgs);
|
|
2947
|
+
const result = await callMcpTool(baseUrl, headers, videoUrls.length && !isSeedance25 && !isMinimaxH3 && !isSyncLipsync ? 'makaron_edit_video' : 'makaron_create_video', vArgs);
|
|
2855
2948
|
const text = result?.content?.find(c => c.type === 'text')?.text;
|
|
2856
2949
|
if (text) {
|
|
2857
2950
|
console.log(text);
|
|
@@ -2898,6 +2991,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
2898
2991
|
video create --script "..." --video-model minimax-h3 MiniMax H3 text-to-video (default 768P)
|
|
2899
2992
|
video create --script "..." --image <url> [--duration 10] Submit video task
|
|
2900
2993
|
video create --script "..." --video <public-url> [--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|google-omni|minimax-h3] Edit/reference a video (Grok does not support video refs)
|
|
2994
|
+
video create --script "Use the supplied audio" --video <url> --audio <url> --video-model sync-lipsync-v3 Lip-sync exact replacement audio
|
|
2901
2995
|
video status <taskId> Check video status
|
|
2902
2996
|
video status --snapshot <snapshotId> [--wait] Check v2 video snapshot
|
|
2903
2997
|
`);
|
|
@@ -3103,6 +3197,31 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
3103
3197
|
if (!res.ok) { console.error(`Error ${res.status}:`, await res.text()); process.exit(1); }
|
|
3104
3198
|
console.log(`✅ ${email} is now admin`);
|
|
3105
3199
|
|
|
3200
|
+
} else if (sub === 'add-credits') {
|
|
3201
|
+
const user = args[2]?.trim();
|
|
3202
|
+
const credits = Number(args[3]);
|
|
3203
|
+
if (!user || !Number.isSafeInteger(credits) || credits <= 0) {
|
|
3204
|
+
console.error('Usage: makaron admin add-credits <email-or-user-id> <credits> [--json]');
|
|
3205
|
+
console.error('Credits must be a positive integer.');
|
|
3206
|
+
process.exit(1);
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
const res = await fetch(`${baseUrl}/api/admin/add-credits`, {
|
|
3210
|
+
method: 'POST',
|
|
3211
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
3212
|
+
body: JSON.stringify({ email: user, credits }),
|
|
3213
|
+
});
|
|
3214
|
+
const data = await res.json().catch(() => null);
|
|
3215
|
+
if (!res.ok) {
|
|
3216
|
+
console.error(`Error ${res.status}:`, data?.error || 'Failed to add credits');
|
|
3217
|
+
process.exit(1);
|
|
3218
|
+
}
|
|
3219
|
+
if (args.includes('--json')) {
|
|
3220
|
+
console.log(JSON.stringify(data));
|
|
3221
|
+
} else {
|
|
3222
|
+
console.log(`✅ Added ${credits} credits to ${user}. New balance: ${data.newBalance}`);
|
|
3223
|
+
}
|
|
3224
|
+
|
|
3106
3225
|
} else {
|
|
3107
3226
|
console.log(`Admin commands:
|
|
3108
3227
|
admin skills List all marketplace skills
|
|
@@ -3115,6 +3234,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
|
|
|
3115
3234
|
admin skill-categories delete <id> Delete a category
|
|
3116
3235
|
admin upload <file> <storage-path> Upload file to Storage
|
|
3117
3236
|
admin fetch-skill <code|url> Download skill from share link
|
|
3237
|
+
admin add-credits <user> <credits> Add credits by email or user ID
|
|
3118
3238
|
admin set-admin <email> Grant admin access to a user
|
|
3119
3239
|
`);
|
|
3120
3240
|
}
|
package/package.json
CHANGED
package/skills/makaron/SKILL.md
CHANGED
|
@@ -162,7 +162,7 @@ npx makaron-cli chat --project auto \
|
|
|
162
162
|
|
|
163
163
|
`--skill` accepts an installed skill name, a marketplace UUID, or a unique marketplace label. Marketplace search matches every localized title, every localized default prompt, and category ids. If a marketplace skill is matched, the CLI installs or reuses it and sends `[Active skill: <installed-skill-name>]` to Makaron Agent. Do not call admin skill commands for ordinary users. There is intentionally no user-facing CLI delete command for marketplace skills.
|
|
164
164
|
|
|
165
|
-
For an explicitly authorized
|
|
165
|
+
For an explicitly authorized administrator, `admin add-credits <email-or-user-id> <positive-integer> [--json]` adds credits to a user. Marketplace administrators can use `admin skills` to see category assignment and 4-locale title/prompt completeness, while `admin skill-categories` supports list/add/update/delete. New skills must include `en`, `zh`, `zh-Hant`, and `ja` in both `labels` and `prompts`, plus at least one existing `categories` id. Partial localized updates are safely merged server-side.
|
|
166
166
|
|
|
167
167
|
### With additional images (existing project)
|
|
168
168
|
|
|
@@ -327,7 +327,7 @@ npx makaron-cli video status <taskId>
|
|
|
327
327
|
npx makaron-cli chat --project <id|auto> --video input.mp4 -b "make it funny"
|
|
328
328
|
```
|
|
329
329
|
|
|
330
|
-
Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to the selected model limit), `--video <file|url>` and `--audio <file|url>` (repeatable where supported), `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3`, `--video-resolution auto|480p|720p|768p|1080p|2k|4k`. Default model is `seedance-fast`. SeeDance accepts native text-to-video with no image and integer output duration 4-15s (default 5s); `seedance-mini` supports 480p/720p and is best for cheaper drafts/multi-size tests; MiniMax H3 accepts native text-to-video, 4-15s output, public 768p/2k resolution, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. H3 defaults to 768p; request 2k explicitly for maximum/final quality. Kling supports 5-15s; Grok 1.5 supports 1-15s single-image-to-video only; Gemini Omni supports 3-10s fast 720p image/video generation and editing with native generated audio, including up to 6 image references when no video reference is provided. For `--video-model grok`, forced `--aspect` is ignored to avoid xAI stretching the source image; pad/create the image at the target shape first or use another model.
|
|
330
|
+
Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to the selected model limit), `--video <file|url>` and `--audio <file|url>` (repeatable where supported), `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|seedance-2.5|kling|grok|google-omni|minimax-h3|sync-lipsync-v3`, `--video-resolution auto|480p|720p|768p|1080p|2k|4k`. Default model is `seedance-fast`. SeeDance accepts native text-to-video with no image and integer output duration 4-15s (default 5s); `seedance-mini` supports 480p/720p and is best for cheaper drafts/multi-size tests; MiniMax H3 accepts native text-to-video, 4-15s output, public 768p/2k resolution, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. `sync-lipsync-v3` requires exactly one video plus one MP3/WAV and preserves that replacement audio while aligning the mouth. H3 defaults to 768p; request 2k explicitly for maximum/final quality. Kling supports 5-15s; Grok 1.5 supports 1-15s single-image-to-video only; Gemini Omni supports 3-10s fast 720p image/video generation and editing with native generated audio, including up to 6 image references when no video reference is provided. For `--video-model grok`, forced `--aspect` is ignored to avoid xAI stretching the source image; pad/create the image at the target shape first or use another model.
|
|
331
331
|
|
|
332
332
|
Seedance 2.5 uses `--video-model seedance-2.5` and supports 4-30s at 480p/720p, up to 30 images + 10 videos + 10 audios, repeatable local/URL references, `--video-operation generate|edit|extend`, `--extend-direction`, `--output-format mp4|mov`, and `--web-search`. The Evolink route does not currently expose 4K output.
|
|
333
333
|
|
|
@@ -378,6 +378,7 @@ type CompletionAction = {
|
|
|
378
378
|
3. Stop when `status` is `"completed"`, `"failed"`, or `"aborted"`
|
|
379
379
|
4. Top-level `status: "completed"` means ALL artifacts are ready (including rendered videos)
|
|
380
380
|
5. If an async video fails, top-level `status` is `"failed"` and the failed video may include `completion_actions` for a safe retry or diagnosis. Agents can surface these as the next user-confirmed step.
|
|
381
|
+
6. `responses get --wait` reconciles pending video output against completed Project Media with the same `snapshot_id` or `task_id`. A lagging Run row therefore does not block delivery after the durable project video is ready.
|
|
381
382
|
|
|
382
383
|
## Exit Codes
|
|
383
384
|
|