makaron-cli 0.13.2 → 0.13.4

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makaron-cli",
3
- "version": "0.13.2",
3
+ "version": "0.13.3",
4
4
  "description": "AI image editing, video generation, music creation, and marketplace skill workflows via CLI. Agents can self-register, install skills, create projects, and produce creative media.",
5
5
  "author": {
6
6
  "name": "Makaron AI",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makaron-cli",
3
- "version": "0.13.2",
3
+ "version": "0.13.3",
4
4
  "description": "AI image editing, video generation, music creation, and marketplace skill workflows via CLI. Agents can self-register, install skills, create projects, and produce creative media.",
5
5
  "displayName": "Makaron",
6
6
  "shortDescription": "AI image/video/music creation from the terminal",
package/README.md CHANGED
@@ -96,12 +96,9 @@ npx makaron-cli chat --project <id> --json -b "<prompt>"
96
96
  # Auto-create project (with or without images)
97
97
  npx makaron-cli chat --project auto --image photo.jpg --json -b "make it cinematic"
98
98
  npx makaron-cli chat --project auto --image img1.jpg --image img2.jpg --json -b "combine these"
99
-
100
- # Choose each model role explicitly
101
- npx makaron-cli chat --project auto --agent-model deepseek-v4-pro --image-model qwen "design a product poster"
102
99
  ```
103
100
 
104
- Model flags are role-specific: `--agent-model` controls reasoning and tool use, `--image-model` controls image generation/editing, and `--video-model` controls video generation. `--agent-model` accepts `auto|gpt-5.6-terra|gpt-5.6-sol|gpt-5.6-luna|grok-4.5|deepseek-v4-pro`. `auto` currently uses GPT-5.6 Terra. `MAKARON_AGENT_MODEL` can set the default for automation; the command flag takes precedence. The legacy `--model` flag remains temporarily supported with a deprecation warning.
101
+ `chat` always routes agent, image, and video models automatically. Never pass `--agent-model`, `--image-model`, `--video-model`, or the legacy `--model` flag to `chat`; the CLI rejects them before starting a run. Model flags remain available only on explicit low-level commands such as `edit` and `video create`.
105
102
 
106
103
  Returns immediately:
107
104
  ```json
@@ -118,7 +115,7 @@ Returns immediately:
118
115
  | Fix one moment in a video from a screenshot | `npx makaron-cli chat --project <id> --image screenshot.png "@4 this frame should be Paris; only fix this moment"` |
119
116
  | Cut or assemble video | `npx makaron-cli chat --project <id> --video clip.mp4 "cut out the dead air and keep the best 20 seconds"` |
120
117
  | Add music | `npx makaron-cli chat --project <id> "add calm piano background music"` |
121
- | Beat-sync video from audio | `npx makaron-cli chat --project auto --audio beat.mp3 --video-model seedance-fast --video-resolution 480p "make a beat-synced video"` |
118
+ | Beat-sync video from audio | `npx makaron-cli chat --project auto --audio beat.mp3 "use Seedance Mini at 480p to make a beat-synced video"` |
122
119
  | Create motion design | `npx makaron-cli chat --project <id> "make an animated Instagram story with this image"` |
123
120
 
124
121
  ### Marketplace skills
@@ -219,13 +216,13 @@ Attach a short song, beat, or voice recording when the video should follow audio
219
216
  ```bash
220
217
  npx makaron-cli chat --project auto \
221
218
  --audio beat.mp3 \
222
- --video-model seedance-fast \
223
- --video-resolution 480p \
224
- -b "make a 15s beat-synced video"
219
+ -b "use Seedance Mini at 480p to make a 15s beat-synced video"
225
220
  ```
226
221
 
227
222
  `--audio` accepts repeatable local files or public URLs. Local MP3/WAV files must be 2-15s and <=15MB; reference audio currently works with Seedance video generation.
228
223
 
224
+ `chat` intentionally has no video model or resolution flags. State both in the chat message so the Agent selects a compatible provider and resolution together. Use `video create` only when you explicitly need direct provider controls.
225
+
229
226
  ### Fix one video moment from a screenshot
230
227
 
231
228
  When a video is mostly good but one moment needs a local fix, attach a screenshot of the problem frame and describe the correction in normal language:
@@ -307,8 +304,9 @@ npx makaron-cli video create --script "Shot 1 (5s): <<<image_1>>> ..." --image h
307
304
  npx makaron-cli video create --script "Shot 1 (5s): <<<image_1>>> slow cinematic push-in with native ambience" --image https://...jpg --duration 5 --video-model grok
308
305
  npx makaron-cli video create --script "Shot 1 (15s): <<<image_1>>> and <<<image_2>>> build a neon one-person studio" --image https://...jpg --image https://...webp --duration 15 --video-model seedance-mini --video-resolution 480p --aspect 9:16
309
306
 
310
- # 3b. Native SeeDance text-to-video (no image required)
307
+ # 3b. Native SeeDance or MiniMax H3 text-to-video (no image required)
311
308
  npx makaron-cli video create --script "Shot 1 (5s): A neon one-person studio wakes at dawn" --duration 5 --video-model seedance-fast --aspect 16:9
309
+ npx makaron-cli video create --script "Shot 1 (15s): A premium creative editor comes alive" --duration 15 --video-model minimax-h3 --video-resolution 2k --aspect 16:9
312
310
 
313
311
  # 3c. Edit a video from a local file or public URL
314
312
  npx makaron-cli video create --script "make it funny" --video input.mp4 --duration 5 --video-model seedance-fast
@@ -324,9 +322,11 @@ For project/timeline video editing, use:
324
322
  npx makaron-cli chat --project <id|auto> --video input.mp4 -b "make it funny"
325
323
  ```
326
324
 
327
- Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to 7), `--video <file|url>`, `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|kling|grok|google-omni`, `--video-resolution auto|480p|720p|1080p|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; 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.
325
+ 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, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. H3 defaults to public 2k output; 768p requires provider preview access plus `MINIMAX_H3_ENABLE_768P=true` on the Makaron server. 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.
326
+
327
+ 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.
328
328
 
329
- Video edit model behavior: `--video-model kling --video` uses Kling base/direct edit internally; `--video-model seedance-fast --video`, `--video-model seedance-mini --video`, or `--video-model seedance --video` uses the SeeDance video-reference path and requires target <=15s, <=50MB, width/height 300-6000px, aspect ratio 0.4-2.5, and frame pixels 409,600-2,086,876. `--video-model google-omni --video` uses Gemini Omni direct video editing and accepts one reference video in Makaron. Output duration is clamped to 3-10s. Grok does not support video references.
329
+ Video edit model behavior: `--video-model kling --video` uses Kling base/direct edit internally; `--video-model seedance-fast --video`, `--video-model seedance-mini --video`, or `--video-model seedance --video` uses the SeeDance video-reference path and requires target <=15s, <=50MB, width/height 300-6000px, aspect ratio 0.4-2.5, and frame pixels 409,600-2,086,876. `--video-model minimax-h3 --video` uses H3 feature/reference mode: up to 3 video references totaling <=15s, each <=50MB with width/height 256-5760px and aspect ratio 0.4-2.5. `--video-model google-omni --video` uses Gemini Omni direct video editing and accepts one reference video in Makaron. Output duration is clamped to 3-10s. Grok does not support video references.
330
330
 
331
331
  ### `music` — Music generation
332
332
 
@@ -439,7 +439,7 @@ send_message "All done!"
439
439
  ## Important Notes
440
440
 
441
441
  - One project = one conversation thread. All history is preserved.
442
- - One run at a time per project. New message interrupts previous run.
442
+ - One active Agent Run at a time per project. A new message received while it is active is appended to that same Agent Run and processed at a durable work-unit boundary; it does not interrupt the execution or create a second owner for an in-progress Studio workflow.
443
443
  - Multi-image: `create --image a.jpg --image b.jpg` or `chat --image ref.jpg`.
444
444
  - Provider-generated videos can take 3-5 minutes; Grok is usually around 30-40 seconds; Gemini Omni is usually around 30-70 seconds plus Storage handoff. Remotion compositions should be converted with `materialize` / `responses get --materialize`, and timing should be read from `duration_seconds`, `render_seconds`, and `realtime_ratio`.
445
445
  - Music takes ~60 seconds. Appears in output when done.
package/bin/makaron.mjs CHANGED
@@ -27,7 +27,6 @@ const APP_URL = process.env.MAKARON_APP_URL || DEFAULT_URL;
27
27
  const NPM_PACKAGE_NAME = 'makaron-cli';
28
28
  const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
29
29
  const UPDATE_CHECK_TIMEOUT_MS = 400;
30
- const AGENT_MODELS = ['auto', 'gpt-5.6-terra', 'gpt-5.6-sol', 'gpt-5.6-luna', 'grok-4.5', 'deepseek-v4-pro'];
31
30
  const AGENT_WAIT_TIMEOUT_SECONDS = Math.max(900, Number(process.env.MAKARON_AGENT_WAIT_TIMEOUT_SECONDS || 10_800));
32
31
 
33
32
  // Public anon key (safe to embed — only enables auth, not data access)
@@ -46,24 +45,20 @@ const MAX_AUDIO_REFERENCE_DURATION_TOLERANCE = 0.5;
46
45
  const MAX_AUDIO_REFERENCE_FILE_SIZE_MB = 15;
47
46
  const MAX_AUDIO_REFERENCE_FILE_SIZE = MAX_AUDIO_REFERENCE_FILE_SIZE_MB * 1024 * 1024;
48
47
  const MAX_VIDEO_FRAME_PIXELS = 2_086_876;
48
+ const SEEDANCE25_MAX_VIDEO_REFERENCE_DURATION = 30;
49
+ const SEEDANCE25_MAX_VIDEO_FRAME_PIXELS = 8_295_044;
49
50
  const SEEDANCE_MIN_VIDEO_FRAME_PIXELS = 409_600;
50
51
  const SEEDANCE_MIN_VIDEO_SIDE = 300;
51
52
  const SEEDANCE_MAX_VIDEO_SIDE = 6000;
52
53
  const SEEDANCE_MIN_VIDEO_ASPECT = 0.4;
53
54
  const SEEDANCE_MAX_VIDEO_ASPECT = 2.5;
55
+ const MINIMAX_H3_MIN_VIDEO_SIDE = 256;
56
+ const MINIMAX_H3_MAX_VIDEO_SIDE = 5760;
54
57
 
55
58
  function warnLegacyModelFlag(replacement) {
56
59
  process.stderr.write(`⚠️ --model is deprecated here; use ${replacement}.\n`);
57
60
  }
58
61
 
59
- function validateAgentModel(value) {
60
- if (!AGENT_MODELS.includes(value)) {
61
- process.stderr.write(`❌ Unknown agent model: ${value}\nChoose one of: ${AGENT_MODELS.join(', ')}\n`);
62
- process.exit(1);
63
- }
64
- return value;
65
- }
66
-
67
62
  function getCliVersion() {
68
63
  try {
69
64
  const pkg = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
@@ -291,15 +286,14 @@ Options:
291
286
  --video <file|url> Attach a video to the project timeline. Repeatable.
292
287
  --audio <file|url> Attach a song, beat, or voice reference. MP3/WAV, repeatable.
293
288
  --skill <id|label|name> Use an installed skill or auto-install a matched marketplace skill.
294
- --image-model <name> Image model: gemini, gemini-lite, qwen, openai, pony, or wai.
295
- --video-model <name> Preferred video model: seedance-fast, seedance-mini, seedance, kling, grok, or google-omni.
296
- --agent-model <name> Agent model: auto, gpt-5.6-terra, gpt-5.6-sol, gpt-5.6-luna, grok-4.5, or deepseek-v4-pro.
297
- --video-resolution <res> Video resolution: auto, 480p, 720p, 1080p, or 4k.
298
289
  --background, -b Submit and print a runId.
299
290
  --json Output structured JSON.
300
291
  --stream Legacy live SSE stream.
301
292
  --help, -h Show this help.
302
293
 
294
+ Model routing is automatic in chat. Do not pass --agent-model, --image-model,
295
+ --video-model, or the legacy --model flag.
296
+
303
297
  What you can ask:
304
298
  Image edit
305
299
  makaron chat --project <id> --image photo.jpg "remove the person in the background"
@@ -323,7 +317,7 @@ What you can ask:
323
317
  makaron chat --project <id> "add calm piano background music"
324
318
 
325
319
  Reference audio / beat sync
326
- makaron chat --project auto --audio beat.mp3 --video-model seedance-fast --video-resolution 480p "用这个音乐做卡点视频"
320
+ makaron chat --project auto --audio beat.mp3 "用 Seedance Mini 480p 做卡点视频"
327
321
  makaron chat --project <id> --audio https://example.com/beat.mp3 "add this as the soundtrack"
328
322
 
329
323
  Motion design
@@ -360,10 +354,6 @@ async function streamAgent(baseUrl, headers, projectId, prompt, opts = {}) {
360
354
  projectId,
361
355
  prompt,
362
356
  headless: true,
363
- ...(opts.preferredModel ? { preferredModel: opts.preferredModel } : {}),
364
- ...(opts.videoModel ? { videoModel: opts.videoModel } : {}),
365
- ...(opts.videoResolution ? { videoResolution: opts.videoResolution } : {}),
366
- ...(opts.agentModel && opts.agentModel !== 'auto' ? { agentModel: opts.agentModel } : {}),
367
357
  ...(opts.uploadedVideoCount ? { uploadedVideoCount: opts.uploadedVideoCount } : {}),
368
358
  ...(opts.turnMediaCount ? { turnMediaCount: opts.turnMediaCount } : {}),
369
359
  }),
@@ -472,10 +462,6 @@ async function streamAgent(baseUrl, headers, projectId, prompt, opts = {}) {
472
462
 
473
463
  async function submitRun(baseUrl, headers, projectId, prompt, opts = {}) {
474
464
  const body = { projectId, prompt };
475
- if (opts.preferredModel) body.preferredModel = opts.preferredModel;
476
- if (opts.agentModel && opts.agentModel !== 'auto') body.agentModel = opts.agentModel;
477
- if (opts.videoModel) body.videoModel = opts.videoModel;
478
- if (opts.videoResolution) body.videoResolution = opts.videoResolution;
479
465
  if (opts.currentSnapshotIndex != null) body.currentSnapshotIndex = opts.currentSnapshotIndex;
480
466
  if (opts.isNsfw) body.isNsfw = opts.isNsfw;
481
467
  if (opts.audioAttachments?.length) body.audioAttachments = opts.audioAttachments;
@@ -1383,7 +1369,8 @@ function getAudioMimeFromExt(ext) {
1383
1369
  return null;
1384
1370
  }
1385
1371
 
1386
- function validateAudioReferenceFile(audioPath) {
1372
+ function validateAudioReferenceFile(audioPath, options = {}) {
1373
+ const maxDuration = options.maxDuration ?? MAX_AUDIO_REFERENCE_DURATION;
1387
1374
  if (!fs.existsSync(audioPath)) {
1388
1375
  return { ok: false, error: `Audio file not found: ${audioPath}` };
1389
1376
  }
@@ -1406,8 +1393,8 @@ function validateAudioReferenceFile(audioPath) {
1406
1393
  if (duration < MIN_AUDIO_REFERENCE_DURATION) {
1407
1394
  return { ok: false, error: `Audio too short: ${formatSeconds(duration)}s (min ${MIN_AUDIO_REFERENCE_DURATION}s).` };
1408
1395
  }
1409
- if (duration > MAX_AUDIO_REFERENCE_DURATION + MAX_AUDIO_REFERENCE_DURATION_TOLERANCE) {
1410
- return { ok: false, error: `Audio too long: ${formatSeconds(duration)}s (max ${MAX_AUDIO_REFERENCE_DURATION}s, with ${MAX_AUDIO_REFERENCE_DURATION_TOLERANCE}s metadata tolerance).` };
1396
+ if (duration > maxDuration + MAX_AUDIO_REFERENCE_DURATION_TOLERANCE) {
1397
+ return { ok: false, error: `Audio too long: ${formatSeconds(duration)}s (max ${maxDuration}s, with ${MAX_AUDIO_REFERENCE_DURATION_TOLERANCE}s metadata tolerance).` };
1411
1398
  }
1412
1399
  return { ok: true, mime, meta: { duration, fileSizeBytes: stat.size } };
1413
1400
  }
@@ -1489,16 +1476,19 @@ function validateVideoFile(videoPath, options = {}) {
1489
1476
  const maxSide = options.maxSide ?? Infinity;
1490
1477
  const minAspect = options.minAspect ?? 0;
1491
1478
  const maxAspect = options.maxAspect ?? Infinity;
1479
+ const allowedExtensions = options.allowedExtensions ?? ['mp4', 'mov', 'webm'];
1480
+ const maxFramePixels = options.maxFramePixels ?? MAX_VIDEO_FRAME_PIXELS;
1481
+ const maxFileSize = options.maxFileSize ?? MAX_VIDEO_UPLOAD_FILE_SIZE;
1492
1482
  if (!fs.existsSync(videoPath)) {
1493
1483
  return { ok: false, error: `Video file not found: ${videoPath}` };
1494
1484
  }
1495
1485
  const stat = fs.statSync(videoPath);
1496
- if (stat.size > MAX_VIDEO_UPLOAD_FILE_SIZE) {
1497
- return { ok: false, error: `Video too large: ${(stat.size / 1024 / 1024).toFixed(1)}MB (max ${MAX_VIDEO_UPLOAD_FILE_SIZE_MB}MB). The CLI uploads directly to Storage; use the frontend to transcode larger videos first.` };
1486
+ if (stat.size > maxFileSize) {
1487
+ return { ok: false, error: `Video too large: ${(stat.size / 1024 / 1024).toFixed(1)}MB (max ${(maxFileSize / 1024 / 1024).toFixed(0)}MB).` };
1498
1488
  }
1499
1489
  const ext = path.extname(videoPath).slice(1).toLowerCase();
1500
- if (!['mp4', 'mov', 'webm'].includes(ext)) {
1501
- return { ok: false, error: `Unsupported video format: .${ext}. Use MP4, MOV, or WebM.` };
1490
+ if (!allowedExtensions.includes(ext)) {
1491
+ return { ok: false, error: `Unsupported video format: .${ext}. Use ${allowedExtensions.map(value => value.toUpperCase()).join(' or ')}.` };
1502
1492
  }
1503
1493
  const meta = probeLocalVideo(videoPath);
1504
1494
  if (!meta) {
@@ -1507,8 +1497,8 @@ function validateVideoFile(videoPath, options = {}) {
1507
1497
  if (meta.duration > maxDuration + durationTolerance) {
1508
1498
  return { ok: false, error: `Video too long: ${formatSeconds(meta.duration)}s (max ${maxDuration}s, with ${durationTolerance}s metadata tolerance)` };
1509
1499
  }
1510
- if (meta.width * meta.height > MAX_VIDEO_FRAME_PIXELS) {
1511
- return { ok: false, error: `Video resolution too high: ${meta.width}x${meta.height} (${meta.width * meta.height} px). Max is <=1080p (${MAX_VIDEO_FRAME_PIXELS} px). Re-upload through the frontend to transcode, or export a smaller video.` };
1500
+ if (meta.width * meta.height > maxFramePixels) {
1501
+ return { ok: false, error: `Video resolution too high: ${meta.width}x${meta.height} (${meta.width * meta.height} px). Max is ${maxFramePixels} pixels.` };
1512
1502
  }
1513
1503
  const framePixels = meta.width * meta.height;
1514
1504
  const aspect = meta.width / meta.height;
@@ -1634,26 +1624,17 @@ Commands:
1634
1624
 
1635
1625
  admin Admin commands (skills, upload, set-admin)
1636
1626
 
1637
- Model selection:
1638
- --agent-model <name> Reasoning/tool model: auto, gpt-5.6-terra, gpt-5.6-sol,
1639
- gpt-5.6-luna, grok-4.5, or deepseek-v4-pro
1640
- --image-model <name> Image model: gemini, gemini-lite, qwen, openai,
1641
- pony, or wai
1642
- --video-model <name> Video model: seedance-fast, seedance-mini, seedance,
1643
- kling, grok, or google-omni
1644
-
1645
1627
  Examples:
1646
- makaron chat --project auto --agent-model deepseek-v4-pro "plan a launch poster"
1647
- makaron chat --project <id> --agent-model gpt-5.6-terra --image-model qwen "make it cinematic"
1648
- makaron chat --project <id> --video-model seedance-fast "turn this into a short video"
1628
+ makaron chat --project auto "plan a launch poster"
1629
+ makaron chat --project <id> "make it cinematic"
1630
+ makaron chat --project <id> "turn this into a short video"
1649
1631
 
1650
1632
  Run makaron <command> --help for command-specific options.
1651
- The legacy --model flag is deprecated; use the role-specific flags above.
1633
+ Chat chooses agent, image, and video models automatically.
1652
1634
 
1653
1635
  Environment:
1654
1636
  MAKARON_API_KEY API key (mk_live_xxx) — recommended for agents
1655
1637
  MAKARON_URL API base (default: ${DEFAULT_URL})
1656
- MAKARON_AGENT_MODEL Default Agent model; --agent-model takes precedence
1657
1638
  `);
1658
1639
  }
1659
1640
 
@@ -1744,8 +1725,6 @@ function printHelp(topic, subtopic) {
1744
1725
  else if (subtopic === 'install') console.log('Usage: makaron skills install <marketplace-id|label> [--json]');
1745
1726
  else console.log(`Skill commands:
1746
1727
  skills list --built-in List all built-in Makaron skills and Studio Run recipes
1747
- skills list --built-in --openmontage
1748
- List OpenMontage-native adapters only
1749
1728
  skills list List marketplace skills
1750
1729
  skills search <query> Search marketplace skills
1751
1730
  skills show <id|label> --built-in Show a built-in skill
@@ -1771,13 +1750,14 @@ Use with chat:
1771
1750
  console.log('Usage: makaron analyze --video <file|url> ["question"]');
1772
1751
  } else if (topic === 'video') {
1773
1752
  if (subtopic === 'script') console.log('Usage: makaron video script --image <file> [--image <file>] [--lang en|zh] "direction"');
1774
- else if (subtopic === 'create') console.log('Usage: makaron video create --script "..." [--image <url> | --video <public-url>] [--duration 10] [--aspect 9:16] [--video-model seedance-fast|seedance-mini|seedance|kling|grok|google-omni] [--video-resolution auto|480p|720p|1080p|4k] [--keep-original-sound]');
1753
+ 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]');
1775
1754
  else if (subtopic === 'status') console.log('Usage: makaron video status <taskId> | --snapshot <snapshotId> [--wait]');
1776
1755
  else console.log(`Video commands:
1777
1756
  video script --image <file> [--image <file>] "direction" Write video script
1778
1757
  video create --script "..." --video-model seedance-fast Native text-to-video (no image required)
1758
+ video create --script "..." --video-model minimax-h3 --video-resolution 2k MiniMax H3 native 2K text-to-video
1779
1759
  video create --script "..." --image <url> [--duration 10] Submit video task
1780
- video create --script "..." --video <public-url> [--video-model seedance-fast|seedance-mini|seedance|kling|google-omni] Edit a video (standalone; Grok does not support video refs)
1760
+ 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)
1781
1761
  video status <taskId> Check video status
1782
1762
  video status --snapshot <snapshotId> [--wait] Check v2 video snapshot
1783
1763
  `);
@@ -1888,10 +1868,6 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
1888
1868
  let background = false;
1889
1869
  let jsonOutput = false;
1890
1870
  let activeSkill = undefined;
1891
- let videoModel = undefined;
1892
- let videoResolution = undefined;
1893
- let preferredModel = undefined;
1894
- let agentModel = process.env.MAKARON_AGENT_MODEL || 'auto';
1895
1871
  for (let i = 1; i < args.length; i++) {
1896
1872
  if (args[i] === '--project' && args[i + 1]) projectId = args[++i];
1897
1873
  else if (args[i] === '--image' && args[i + 1]) chatImages.push(args[++i]);
@@ -1902,13 +1878,17 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
1902
1878
  else if (args[i] === '--stream') useStream = true;
1903
1879
  else if (args[i] === '--background' || args[i] === '-b') background = true;
1904
1880
  else if (args[i] === '--json') jsonOutput = true;
1905
- else if (args[i] === '--video-model' && args[i + 1]) videoModel = args[++i];
1906
- else if (args[i] === '--video-resolution' && args[i + 1]) videoResolution = args[++i];
1907
- else if (args[i] === '--image-model' && args[i + 1]) preferredModel = args[++i];
1908
- else if (args[i] === '--agent-model' && args[i + 1]) agentModel = args[++i];
1909
- else if (args[i] === '--model' && args[i + 1]) {
1910
- warnLegacyModelFlag('--image-model');
1911
- preferredModel = args[++i];
1881
+ else if (args[i] === '--video-resolution' || args[i].startsWith('--video-resolution=')) {
1882
+ process.stderr.write('❌ makaron chat chooses video model and resolution together. Put the requested resolution in your chat message, for example: "use MiniMax H3 at 2K".\n');
1883
+ process.exit(1);
1884
+ }
1885
+ else if (
1886
+ ['--agent-model', '--image-model', '--video-model', '--model'].includes(args[i])
1887
+ || ['--agent-model=', '--image-model=', '--video-model=', '--model='].some(prefix => args[i].startsWith(prefix))
1888
+ ) {
1889
+ const flag = args[i].split('=')[0];
1890
+ process.stderr.write(`❌ makaron chat chooses agent, image, and video models automatically. Remove ${flag} and retry.\n`);
1891
+ process.exit(1);
1912
1892
  }
1913
1893
  else promptParts.push(args[i]);
1914
1894
  }
@@ -1918,7 +1898,6 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
1918
1898
  console.error('Run: makaron chat --help');
1919
1899
  process.exit(1);
1920
1900
  }
1921
- agentModel = validateAgentModel(agentModel);
1922
1901
  const { headers, baseUrl } = getAuth();
1923
1902
  // Split images into URLs vs local files
1924
1903
  const imageUrlList = chatImages.filter(p => p.startsWith('http://') || p.startsWith('https://'));
@@ -2017,7 +1996,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2017
1996
  const resolvedSkill = await resolveChatSkill(baseUrl, headers, activeSkill);
2018
1997
 
2019
1998
  // Upload videos to project timeline (via /api/projects/create with videoUrls)
2020
- let finalPrompt = resolvedSkill ? `[Active skill: ${resolvedSkill}]\n${prompt}` : prompt;
1999
+ const finalPrompt = resolvedSkill ? `[Active skill: ${resolvedSkill}]\n${prompt}` : prompt;
2021
2000
  let audioAttachments = [];
2022
2001
  if (chatAudios.length > 0) {
2023
2002
  const audioImports = [];
@@ -2108,10 +2087,6 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2108
2087
  if (useStream) {
2109
2088
  // Legacy SSE mode
2110
2089
  const { results } = await streamAgent(baseUrl, headers, projectId, finalPrompt, {
2111
- videoModel,
2112
- videoResolution,
2113
- preferredModel,
2114
- agentModel,
2115
2090
  uploadedVideoCount: uploadedTurnVideoCount,
2116
2091
  turnMediaCount: uploadedTurnMediaCount,
2117
2092
  });
@@ -2124,10 +2099,6 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2124
2099
  } else {
2125
2100
  // Default: fire-and-forget + poll
2126
2101
  const { runId } = await submitRun(baseUrl, headers, projectId, finalPrompt, {
2127
- videoModel,
2128
- videoResolution,
2129
- preferredModel,
2130
- agentModel,
2131
2102
  audioAttachments,
2132
2103
  uploadedVideoCount: uploadedTurnVideoCount,
2133
2104
  turnMediaCount: uploadedTurnMediaCount,
@@ -2320,10 +2291,7 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2320
2291
 
2321
2292
  if (sub === 'list') {
2322
2293
  const builtIn = args.includes('--built-in');
2323
- let skills = builtIn ? await fetchBuiltInSkills(baseUrl) : await fetchMarketplaceSkills(baseUrl);
2324
- if (builtIn && args.includes('--openmontage')) {
2325
- skills = skills.filter(skill => skill.sourceProject === 'openmontage');
2326
- }
2294
+ const skills = builtIn ? await fetchBuiltInSkills(baseUrl) : await fetchMarketplaceSkills(baseUrl);
2327
2295
  if (jsonOutput) console.log(JSON.stringify({ skills }, null, 2));
2328
2296
  else if (builtIn) printBuiltInSkills(skills);
2329
2297
  else printMarketplaceSkills(skills);
@@ -2365,8 +2333,6 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2365
2333
  } else {
2366
2334
  console.log(`Skill commands:
2367
2335
  skills list --built-in List all built-in Makaron skills and Studio Run recipes
2368
- skills list --built-in --openmontage
2369
- List OpenMontage-native adapters only
2370
2336
  skills list List marketplace skills
2371
2337
  skills search <query> Search marketplace skills
2372
2338
  skills show <id|label> --built-in Show a built-in skill
@@ -2462,11 +2428,15 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2462
2428
 
2463
2429
  } else if (sub === 'create') {
2464
2430
  const images = [];
2431
+ const videos = [];
2432
+ const audios = [];
2465
2433
  let script = '', duration = undefined, aspectRatio = undefined, videoModel = undefined, videoResolution = undefined, wait = false;
2466
- let video = null, keepOriginalSound = false;
2434
+ let keepOriginalSound = false, videoOperation = undefined, extendDirection = undefined, outputFormat = undefined;
2435
+ let generateAudio = undefined, contentFilter = undefined, webSearch = false;
2467
2436
  for (let i = 2; i < args.length; i++) {
2468
2437
  if (args[i] === '--image' && args[i + 1]) images.push(args[++i]);
2469
- else if (args[i] === '--video' && args[i + 1]) video = args[++i];
2438
+ else if (args[i] === '--video' && args[i + 1]) videos.push(args[++i]);
2439
+ else if (args[i] === '--audio' && args[i + 1]) audios.push(args[++i]);
2470
2440
  else if (args[i] === '--script' && args[i + 1]) script = args[++i];
2471
2441
  else if (args[i] === '--script-file' && args[i + 1]) script = fs.readFileSync(args[++i], 'utf-8');
2472
2442
  else if (args[i] === '--duration' && args[i + 1]) duration = Number(args[++i]);
@@ -2479,6 +2449,13 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2479
2449
  else if (args[i] === '--video-resolution' && args[i + 1]) videoResolution = args[++i];
2480
2450
  else if (args[i] === '--resolution' && args[i + 1]) videoResolution = args[++i];
2481
2451
  else if (args[i] === '--keep-original-sound') keepOriginalSound = true;
2452
+ else if (args[i] === '--video-operation' && args[i + 1]) videoOperation = args[++i];
2453
+ else if (args[i] === '--extend-direction' && args[i + 1]) extendDirection = args[++i];
2454
+ else if (args[i] === '--output-format' && args[i + 1]) outputFormat = args[++i];
2455
+ else if (args[i] === '--no-generated-audio') generateAudio = false;
2456
+ else if (args[i] === '--generated-audio') generateAudio = true;
2457
+ else if (args[i] === '--relaxed-content-filter') contentFilter = false;
2458
+ else if (args[i] === '--web-search') webSearch = true;
2482
2459
  else if (args[i] === '--project') {
2483
2460
  console.error('Usage: video create no longer supports --project. Use: makaron chat --project <id> --video <file|url> "your request"');
2484
2461
  process.exit(1);
@@ -2486,27 +2463,53 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2486
2463
  else if (args[i] === '--wait') wait = true;
2487
2464
  }
2488
2465
  const selectedVideoModel = videoModel || 'seedance-fast';
2489
- const isSeedanceModel = selectedVideoModel === 'seedance-fast' || selectedVideoModel === 'seedance-mini' || selectedVideoModel === 'seedance';
2490
- if (!script || (!images.length && !video && !isSeedanceModel)) {
2491
- console.error('Usage: makaron video create --script "..." [--image <url> | --video <public-url>] [--duration 10] [--aspect 9:16] [--video-model seedance-fast|seedance-mini|seedance|kling|grok|google-omni] [--video-resolution auto|480p|720p|1080p|4k] [--keep-original-sound]');
2466
+ const isSeedance25 = selectedVideoModel === 'seedance-2.5';
2467
+ const isSeedanceModel = selectedVideoModel === 'seedance-fast' || selectedVideoModel === 'seedance-mini' || selectedVideoModel === 'seedance' || isSeedance25;
2468
+ const isMinimaxH3 = selectedVideoModel === 'minimax-h3';
2469
+ const supportsNativeTextToVideo = isSeedanceModel || isMinimaxH3;
2470
+ if (!script || (!images.length && !videos.length && !audios.length && !supportsNativeTextToVideo)) {
2471
+ console.error('Usage: makaron video create --script "..." [--image <url>] [--video <file|url>] [--audio <file|url>] [--duration 30] [--video-model seedance-2.5|minimax-h3]');
2492
2472
  process.exit(1);
2493
2473
  }
2474
+ if (isSeedance25 && images.length > 30) { console.error('Seedance 2.5 supports at most 30 image references.'); process.exit(1); }
2475
+ if (isSeedance25 && videos.length > 10) { console.error('Seedance 2.5 supports at most 10 video references.'); process.exit(1); }
2476
+ if (isSeedance25 && audios.length > 10) { console.error('Seedance 2.5 supports at most 10 audio references.'); process.exit(1); }
2477
+ if (isMinimaxH3 && images.length > 9) { console.error('MiniMax H3 supports at most 9 image references.'); process.exit(1); }
2478
+ if (isMinimaxH3 && videos.length > 3) { console.error('MiniMax H3 supports at most 3 video references.'); process.exit(1); }
2479
+ if (isMinimaxH3 && audios.length > 3) { console.error('MiniMax H3 supports at most 3 audio references.'); process.exit(1); }
2480
+ if (videoOperation && !['generate', 'edit', 'extend'].includes(videoOperation)) { console.error('--video-operation must be generate, edit, or extend.'); process.exit(1); }
2481
+ if (extendDirection && !['forward', 'backward'].includes(extendDirection)) { console.error('--extend-direction must be forward or backward.'); process.exit(1); }
2482
+ if (outputFormat && !['mp4', 'mov'].includes(outputFormat)) { console.error('--output-format must be mp4 or mov.'); process.exit(1); }
2494
2483
 
2495
2484
  if (wait) {
2496
2485
  console.error('Usage: --wait is only supported for project timeline tasks. Use chat --project for project video generation, or poll the returned taskId with video status.');
2497
2486
  process.exit(1);
2498
2487
  }
2499
2488
 
2500
- let videoUrl = isHttpUrl(video) ? video : null;
2501
- let inputVideoMeta = null;
2502
- if (videoUrl) {
2503
- process.stderr.write(`📹 Assuming public video URL already matches provider reference limits. Seedance requires ≤${MAX_VIDEO_PROVIDER_REFERENCE_DURATION}s, ≤50MB, sides 300-6000px, frame pixels 409,600-${MAX_VIDEO_FRAME_PIXELS}; Kling requires ≤200MB and ≤2K; Google Omni accepts one reference video in Makaron; Grok does not support video references.\n`);
2489
+ const providerMaxDuration = isSeedance25 ? SEEDANCE25_MAX_VIDEO_REFERENCE_DURATION : MAX_VIDEO_PROVIDER_REFERENCE_DURATION;
2490
+ const providerMaxPixels = isMinimaxH3 ? Infinity : isSeedance25 ? SEEDANCE25_MAX_VIDEO_FRAME_PIXELS : MAX_VIDEO_FRAME_PIXELS;
2491
+ const localImages = images.filter(image => !isHttpUrl(image));
2492
+ if (localImages.length) {
2493
+ const uploadedImages = await uploadImageFilesViaSignedUrl(baseUrl, headers, undefined, localImages);
2494
+ const uploadedByPath = new Map(localImages.map((image, index) => [image, uploadedImages[index]]));
2495
+ images = images.map(image => isHttpUrl(image) ? image : uploadedByPath.get(image)).filter(Boolean);
2504
2496
  }
2505
- if (video && !videoUrl) {
2497
+ const videoUrls = [];
2498
+ let inputVideoMeta = null;
2499
+ for (const video of videos) {
2500
+ if (isHttpUrl(video)) { videoUrls.push(video); continue; }
2506
2501
  const valid = validateVideoFile(video, {
2507
- maxDuration: MAX_VIDEO_PROVIDER_REFERENCE_DURATION,
2502
+ maxDuration: providerMaxDuration,
2508
2503
  durationTolerance: MAX_VIDEO_PROVIDER_REFERENCE_DURATION_TOLERANCE,
2509
- ...(selectedVideoModel === 'seedance' || selectedVideoModel === 'seedance-fast' || selectedVideoModel === 'seedance-mini' ? {
2504
+ maxFramePixels: providerMaxPixels,
2505
+ maxFileSize: isSeedance25 ? 200 * 1024 * 1024 : MAX_VIDEO_UPLOAD_FILE_SIZE,
2506
+ ...(selectedVideoModel === 'minimax-h3' ? {
2507
+ allowedExtensions: ['mp4', 'mov'],
2508
+ minSide: MINIMAX_H3_MIN_VIDEO_SIDE,
2509
+ maxSide: MINIMAX_H3_MAX_VIDEO_SIDE,
2510
+ minAspect: SEEDANCE_MIN_VIDEO_ASPECT,
2511
+ maxAspect: SEEDANCE_MAX_VIDEO_ASPECT,
2512
+ } : isSeedanceModel ? {
2510
2513
  minFramePixels: SEEDANCE_MIN_VIDEO_FRAME_PIXELS,
2511
2514
  minSide: SEEDANCE_MIN_VIDEO_SIDE,
2512
2515
  maxSide: SEEDANCE_MAX_VIDEO_SIDE,
@@ -2515,22 +2518,38 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2515
2518
  } : {}),
2516
2519
  });
2517
2520
  if (!valid.ok) { console.error(`❌ ${valid.error}`); process.exit(1); }
2518
- inputVideoMeta = valid.meta;
2521
+ inputVideoMeta ||= valid.meta;
2519
2522
  process.stderr.write(`📹 Uploading ${path.basename(video)} (${(fs.statSync(video).size/1024/1024).toFixed(1)}MB)...\n`);
2520
- videoUrl = await uploadFileViaSignedUrl(baseUrl, headers, undefined, video, valid.mime);
2521
- if (!videoUrl) process.exit(1);
2523
+ const uploaded = await uploadFileViaSignedUrl(baseUrl, headers, undefined, video, valid.mime);
2524
+ if (!uploaded) process.exit(1);
2525
+ videoUrls.push(uploaded);
2522
2526
  process.stderr.write(`📹 Uploaded: ${path.basename(video)}\n`);
2523
2527
  }
2528
+ const audioUrls = [];
2529
+ for (const audio of audios) {
2530
+ if (isHttpUrl(audio)) { audioUrls.push(audio); continue; }
2531
+ const valid = validateAudioReferenceFile(audio, { maxDuration: isSeedance25 ? 30 : MAX_AUDIO_REFERENCE_DURATION });
2532
+ if (!valid.ok) { console.error(`❌ ${valid.error}`); process.exit(1); }
2533
+ process.stderr.write(`🎵 Uploading ${path.basename(audio)}...\n`);
2534
+ const uploaded = await uploadFileViaSignedUrl(baseUrl, headers, undefined, audio, valid.mime, { uploadKind: 'audio' });
2535
+ if (!uploaded) process.exit(1);
2536
+ audioUrls.push(uploaded);
2537
+ }
2524
2538
  // Standalone MCP tool (no project timeline write)
2525
2539
  process.stderr.write('🎬 Submitting video...\n');
2526
- const vArgs = videoUrl
2527
- ? { videoUrl, editPrompt: script, images, videoModel: selectedVideoModel, videoResolution, referType: (selectedVideoModel === 'seedance' || selectedVideoModel === 'seedance-fast' || selectedVideoModel === 'seedance-mini') ? 'feature' : 'base' }
2528
- : { script, images, videoModel: selectedVideoModel, videoResolution };
2529
- const effectiveDuration = duration || (inputVideoMeta?.duration ? Math.min(MAX_VIDEO_PROVIDER_REFERENCE_DURATION, Math.round(inputVideoMeta.duration)) : undefined);
2540
+ const resolvedOperation = videoOperation || (isSeedance25 && videoUrls.length ? 'edit' : 'generate');
2541
+ const vArgs = isSeedance25
2542
+ ? { script, images, videoUrls, audioUrls, videoModel: selectedVideoModel, videoResolution, operation: resolvedOperation, extendDirection, outputFormat, generateAudio, contentFilter, webSearch }
2543
+ : isMinimaxH3
2544
+ ? { script, images, videoUrls, audioUrls, videoModel: selectedVideoModel, videoResolution }
2545
+ : videoUrls[0]
2546
+ ? { videoUrl: videoUrls[0], editPrompt: script, images, videoModel: selectedVideoModel, videoResolution, referType: isSeedanceModel ? 'feature' : 'base' }
2547
+ : { script, images, videoModel: selectedVideoModel, videoResolution };
2548
+ const effectiveDuration = resolvedOperation === 'edit' ? undefined : duration || (inputVideoMeta?.duration ? Math.min(providerMaxDuration, Math.round(inputVideoMeta.duration)) : undefined);
2530
2549
  if (effectiveDuration) vArgs.duration = effectiveDuration;
2531
2550
  if (aspectRatio) vArgs.aspectRatio = aspectRatio;
2532
- if (keepOriginalSound && videoUrl) vArgs.keepOriginalSound = true;
2533
- const result = await callMcpTool(baseUrl, headers, videoUrl ? 'makaron_edit_video' : 'makaron_create_video', vArgs);
2551
+ if (keepOriginalSound && videoUrls.length && !isSeedance25) vArgs.keepOriginalSound = true;
2552
+ const result = await callMcpTool(baseUrl, headers, videoUrls.length && !isSeedance25 && !isMinimaxH3 ? 'makaron_edit_video' : 'makaron_create_video', vArgs);
2534
2553
  const text = result?.content?.find(c => c.type === 'text')?.text;
2535
2554
  if (text) {
2536
2555
  console.log(text);
@@ -2574,8 +2593,9 @@ if (!command || command === '--help' || command === '-h' || command === 'help')
2574
2593
  console.log(`Video commands:
2575
2594
  video script --image <file> [--image <file>] "direction" Write video script
2576
2595
  video create --script "..." --video-model seedance-fast Native text-to-video (no image required)
2596
+ video create --script "..." --video-model minimax-h3 --video-resolution 2k MiniMax H3 native 2K text-to-video
2577
2597
  video create --script "..." --image <url> [--duration 10] Submit video task
2578
- video create --script "..." --video <public-url> [--video-model seedance-fast|seedance-mini|seedance|kling|google-omni] Edit a video (standalone; Grok does not support video refs)
2598
+ 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)
2579
2599
  video status <taskId> Check video status
2580
2600
  video status --snapshot <snapshotId> [--wait] Check v2 video snapshot
2581
2601
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makaron-cli",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "description": "Talk to Makaron Agent from the terminal — create projects, edit images, generate videos",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -83,12 +83,9 @@ npx makaron-cli chat --project <id> --json -b "<prompt>"
83
83
  # Auto-create project (with or without images)
84
84
  npx makaron-cli chat --project auto --image photo.jpg --json -b "make it cinematic"
85
85
  npx makaron-cli chat --project auto --image img1.jpg --image img2.jpg --json -b "combine these"
86
-
87
- # Choose each model role explicitly
88
- npx makaron-cli chat --project auto --agent-model deepseek-v4-pro --image-model qwen "design a product poster"
89
86
  ```
90
87
 
91
- Model flags are role-specific: `--agent-model` controls reasoning and tool use, `--image-model` controls image generation/editing, and `--video-model` controls video generation. `--agent-model` accepts `auto|gpt-5.6-terra|gpt-5.6-sol|gpt-5.6-luna|grok-4.5|deepseek-v4-pro`. `auto` currently uses GPT-5.6 Terra. `MAKARON_AGENT_MODEL` can set the default for automation; the command flag takes precedence. The legacy `--model` flag remains temporarily supported with a deprecation warning.
88
+ `chat` always routes agent, image, and video models automatically. Never pass `--agent-model`, `--image-model`, `--video-model`, or the legacy `--model` flag to `chat`; the CLI rejects them before starting a run. Model flags remain available only on explicit low-level commands such as `edit` and `video create`.
92
89
 
93
90
  Returns immediately:
94
91
  ```json
@@ -105,7 +102,7 @@ Returns immediately:
105
102
  | Fix one moment in a video from a screenshot | `npx makaron-cli chat --project <id> --image screenshot.png "@4 this frame should be Paris; only fix this moment"` |
106
103
  | Cut or assemble video | `npx makaron-cli chat --project <id> --video clip.mp4 "cut out the dead air and keep the best 20 seconds"` |
107
104
  | Add music | `npx makaron-cli chat --project <id> "add calm piano background music"` |
108
- | Beat-sync video from audio | `npx makaron-cli chat --project auto --audio beat.mp3 --video-model seedance-fast --video-resolution 480p "make a beat-synced video"` |
105
+ | Beat-sync video from audio | `npx makaron-cli chat --project auto --audio beat.mp3 "use Seedance Mini at 480p to make a beat-synced video"` |
109
106
  | Create motion design | `npx makaron-cli chat --project <id> "make an animated Instagram story with this image"` |
110
107
 
111
108
  ### Marketplace skills
@@ -179,13 +176,13 @@ Attach a short song, beat, or voice recording when the video should follow audio
179
176
  ```bash
180
177
  npx makaron-cli chat --project auto \
181
178
  --audio beat.mp3 \
182
- --video-model seedance-fast \
183
- --video-resolution 480p \
184
- -b "make a 15s beat-synced video"
179
+ -b "use Seedance Mini at 480p to make a 15s beat-synced video"
185
180
  ```
186
181
 
187
182
  `--audio` accepts repeatable local files or public URLs. Local MP3/WAV files must be 2-15s and <=15MB; reference audio currently works with Seedance video generation.
188
183
 
184
+ `chat` intentionally has no video model or resolution flags. State both in the chat message so the Agent selects a compatible provider and resolution together. Use `video create` only when you explicitly need direct provider controls.
185
+
189
186
  ### Fix one video moment from a screenshot
190
187
 
191
188
  When a video is mostly good but one moment needs a local fix, attach a screenshot of the problem frame and describe the correction in normal language:
@@ -266,8 +263,9 @@ npx makaron-cli analyze --video input.mp4 "describe the key actions and pacing"
266
263
  npx makaron-cli video create --script "Shot 1 (5s): <<<image_1>>> ..." --image https://...jpg --duration 5 --video-model kling
267
264
  npx makaron-cli video create --script "Shot 1 (15s): <<<image_1>>> and <<<image_2>>> build a neon one-person studio" --image https://...jpg --image https://...webp --duration 15 --video-model seedance-mini --video-resolution 480p --aspect 9:16
268
265
 
269
- # 3b. Native SeeDance text-to-video (no image required)
266
+ # 3b. Native SeeDance or MiniMax H3 text-to-video (no image required)
270
267
  npx makaron-cli video create --script "Shot 1 (5s): A neon one-person studio wakes at dawn" --duration 5 --video-model seedance-fast --aspect 16:9
268
+ npx makaron-cli video create --script "Shot 1 (15s): A premium creative editor comes alive" --duration 15 --video-model minimax-h3 --video-resolution 2k --aspect 16:9
271
269
 
272
270
  # 3c. Edit a video from a local file or public URL
273
271
  npx makaron-cli video create --script "make it funny" --video input.mp4 --duration 5 --video-model seedance-fast
@@ -283,9 +281,11 @@ npx makaron-cli video status <taskId>
283
281
  npx makaron-cli chat --project <id|auto> --video input.mp4 -b "make it funny"
284
282
  ```
285
283
 
286
- Options for `video create`: `--script "..."`, `--script-file <path>`, `--image <url>` (repeatable, up to 7), `--video <file|url>`, `--duration <seconds>`, `--aspect 9:16|16:9|1:1`, `--video-model seedance-fast|seedance-mini|seedance|kling|grok|google-omni`, `--video-resolution auto|480p|720p|1080p|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; 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.
284
+ 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, and up to 9 image, up to 3 video, and up to 3 audio references through Makaron Agent/chat. H3 defaults to public 2k output; 768p requires provider preview access plus `MINIMAX_H3_ENABLE_768P=true` on the Makaron server. 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.
285
+
286
+ 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.
287
287
 
288
- Video edit model behavior: `--video-model kling --video` uses Kling base/direct edit internally; `--video-model seedance-fast --video`, `--video-model seedance-mini --video`, or `--video-model seedance --video` uses the SeeDance video-reference path and requires target <=15s, <=50MB, width/height 300-6000px, aspect ratio 0.4-2.5, and frame pixels 409,600-2,086,876. `--video-model google-omni --video` uses Gemini Omni direct video editing and accepts one reference video in Makaron. Output duration is clamped to 3-10s. Grok does not support video references.
288
+ Video edit model behavior: `--video-model kling --video` uses Kling base/direct edit internally; `--video-model seedance-fast --video`, `--video-model seedance-mini --video`, or `--video-model seedance --video` uses the SeeDance video-reference path and requires target <=15s, <=50MB, width/height 300-6000px, aspect ratio 0.4-2.5, and frame pixels 409,600-2,086,876. `--video-model minimax-h3 --video` uses H3 feature/reference mode: up to 3 video references totaling <=15s, each <=50MB with width/height 256-5760px and aspect ratio 0.4-2.5. `--video-model google-omni --video` uses Gemini Omni direct video editing and accepts one reference video in Makaron. Output duration is clamped to 3-10s. Grok does not support video references.
289
289
 
290
290
  ### `music` — Music generation
291
291
 
@@ -416,7 +416,7 @@ send_message "All done!"
416
416
  ## Important Notes
417
417
 
418
418
  - One project = one conversation thread. All history is preserved.
419
- - One run at a time per project. New message interrupts previous run.
419
+ - One active Agent Run at a time per project. A new message received while it is active is appended to that same Agent Run and processed at a durable work-unit boundary; it does not interrupt the execution or create a second owner for an in-progress Studio workflow.
420
420
  - Multi-image: `create --image a.jpg --image b.jpg` or `chat --image ref.jpg`.
421
421
  - Provider-generated videos can take 3-5 minutes; Grok is usually around 30-40 seconds; Gemini Omni is usually around 30-70 seconds plus Storage handoff. Remotion compositions should be converted with `materialize` / `responses get --materialize`, and timing should be read from `duration_seconds`, `render_seconds`, and `realtime_ratio`.
422
422
  - Music takes ~60 seconds. Appears in output when done.