@remixmate/cli 0.12.8 → 0.13.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.
@@ -54,15 +54,15 @@
54
54
  },
55
55
  "background_preset": {
56
56
  "type": "string",
57
- "description": "Scene background preset, one of the template's customPayloadSchema.background.preset values. Written to every scene's customPayload.background.preset. **Must** pass when the user picked a background: the replicate card shows `背景样式: 纯色(solid)` → pass `solid`. Without it the scene keeps the template default. Requires template_id; unsupported values are rejected. `image` / `video` need the user's file: pass it as background_asset (which also sets the preset)."
57
+ "description": "Scene background preset, one of the template's customPayloadSchema.background.preset values. Written to every scene's customPayload.background.preset. **Must** pass when the user picked a background: the replicate card shows `背景样式: <名称>(<id>)` → pass `<id>`. Without it the scene keeps the template default. Requires template_id; unsupported values are rejected. `image` / `video` need the user's file: pass it as background_asset (which also sets the preset)."
58
58
  },
59
59
  "sequence_preset": {
60
60
  "type": "string",
61
- "description": "Image-sequence style preset, one of the template's customPayloadSchema.sequence.preset values (image-to-video: vlog / news / poster / cinematic / fast-cut). Written to customPayload.sequence.preset; the preset sets transitions, motion, text layout and pacing (fast-cut shortens every image to 1.5s, and the scene duration follows). **Must** pass when the user picked a style preset: the replicate card shows `风格预设: 快剪(fast-cut)` → pass `fast-cut`; `none` keeps the template defaults. Without it the choice is silently dropped. Only for templates declaring capabilities.payloadDefaults.sequence; unsupported values are rejected."
61
+ "description": "Style preset for templates declaring capabilities.mediaBinding.options.preset; one of that option's enum in the template's customPayloadSchema. Written next to the template's media list; the preset sets transitions, motion, text layout and pacing, and the scene duration follows. **Must** pass when the user picked a style preset: the replicate card shows `风格预设: <名称>(<id>)` → pass `<id>`; `none` keeps the template defaults. Without it the choice is silently dropped. Rejected on templates without that option; unsupported values are rejected."
62
62
  },
63
63
  "sequence_fit": {
64
64
  "type": "string",
65
- "description": "How image-sequence media fill the frame, one of customPayloadSchema.sequence.fit (cover = fill the frame and crop, contain = show the whole picture over a blurred backdrop). Written to customPayload.sequence.fit and beats the preset's own fit. **Must** pass when the user picked it: `显示方式: 完整显示(contain)` → pass `contain`; `auto` keeps the template / preset default. Only for templates declaring capabilities.payloadDefaults.sequence."
65
+ "description": "Media fill mode for templates declaring capabilities.mediaBinding.options.fit; one of that option's enum in the template's customPayloadSchema (its descriptions explain each value). Beats the preset's own fit. **Must** pass when the user picked it: `显示方式: <名称>(<id>)` → pass `<id>`; `auto` keeps the template / preset default."
66
66
  },
67
67
  "background_asset": {
68
68
  "type": "string",
@@ -73,7 +73,7 @@
73
73
  "items": {
74
74
  "type": "string"
75
75
  },
76
- "description": "Template-specific card choices as `KEY=VALUE`, written to every scene's customPayload and locked so the dsl_json you save cannot overwrite them. KEY is a dotted path into the template's customPayloadSchema (e.g. `grade=四年级`, `watermarkText=WorkBuddy 实战课`, `preset=course`, `carousel.fit=cover`, `templateData.revealMode=progressive`, `cardStyle.championFx=false`); VALUE is the id inside the card line's parentheses, or the text verbatim for free-text fields. Booleans take true/false, numbers are range-checked, enums are checked — an undeclared key or value is rejected with the allowed list. **Must** pass every card line that the system prompt maps to a payload key; without it the choice is silently dropped. Requires template_id."
76
+ "description": "Template-specific card choices as `KEY=VALUE`, written to every scene's customPayload and locked so the dsl_json you save cannot overwrite them. KEY is a dotted path into the template's customPayloadSchema (e.g. `<field>=<value>`, `<object>.<field>=<value>`); VALUE is the id inside the card line's parentheses, or the text verbatim for free-text fields. Booleans take true/false, numbers are range-checked, enums are checked — an undeclared key or value is rejected with the allowed list. **Must** pass every card line that the system prompt maps to a payload key; without it the choice is silently dropped. Requires template_id."
77
77
  },
78
78
  "motion": {
79
79
  "type": "string",
@@ -87,6 +87,17 @@
87
87
  ],
88
88
  "description": "Camera motion for every scene (scenes[].animationHints.motion), replacing the skeleton's alternating push-in / pull-out. **Must** pass when the user picked one: `运镜效果: 缓慢推近(kenburns-in)` → `kenburns-in`."
89
89
  },
90
+ "ending_payload": {
91
+ "type": "array",
92
+ "items": {
93
+ "type": "string"
94
+ },
95
+ "description": "Like payload, but `KEY=VALUE` is written only to the ending scene and locked there (e.g. the replicate card's 片尾引导 line → `<object>.<field>=<closing line>`, key as the card shows it). On countdown templates (Top-N lists) it also appends the ending scene after #1 — fill that scene's narration (a closing line) and its item field with the #1 entry. Without it a countdown ends on the #1 card. Requires template_id."
96
+ },
97
+ "avatar_id": {
98
+ "type": "string",
99
+ "description": "Digital-human avatar id (`dh_xxx`, the replicate card's 数字人主讲 / 数字人讲师 line) for templates declaring capabilities.digitalHuman. Adds one gen-digital-human asset referenced by every scene's visuals.avatar.assetRef: one continuous presenter whose lips follow the narration. Placement stays the template default; adjust with payload `digitalHuman.<field>=…`. Copy the id verbatim, never invent one. Costs digital-human credits, so pass it only when the user picked an avatar. Requires template_id."
100
+ },
90
101
  "font_id": {
91
102
  "type": "string",
92
103
  "description": "Font library key (font.uniq_id) for the on-screen text and subtitles. Written to global.font.fontId; match_template folds it into the binding's typography and ab-render resolves and installs the real font before rendering. **Must** pass when the user picked a font: the replicate card shows it as `名字(id)`, e.g. `字体: <名字>(<uniqId>)` → pass the id in the parentheses. Pass the opaque key, never a CSS family name or the display name — those fall back to the template font with no error. When the user names a font without its id, call gen_script with list_fonts=true first and take the id from that list; do not invent ids. Without it the choice is silently dropped and the video renders in the template's own font. Omit to follow the template's font pairing."
@@ -132,7 +143,7 @@
132
143
  "items": {
133
144
  "type": "string"
134
145
  },
135
- "description": "Media URLs for the template's image/video carousel. When provided together with a template_id whose capabilities.payloadStyle=carousel-caption, these URLs are placed into customPayload.sequence.items when payloadDefaults.sequence is declared, otherwise customPayload.carousel.items, as existing assets — NO AI image generation is triggered. **Must** pass when the user explicitly provides image/video URLs for such a template. Each element is a full URL string. Image sequences (payloadDefaults.sequence) accept video URLs too (.mp4/.mov/.webm): gen_script probes each clip's real length, marks it type=video and plays it whole and muted; an unreadable video is rejected."
146
+ "description": "Media URLs for the template's image/video list. When provided together with a template_id whose capabilities.payloadStyle=carousel-caption, these URLs are written as existing assets into the media list the template declares in capabilities.mediaBinding.itemsPath — NO AI image generation is triggered. **Must** pass when the user explicitly provides image/video URLs for such a template. Each element is a full URL string. Video URLs (.mp4/.mov/.webm) are accepted too; when the template declares mediaBinding.videoDurationKey gen_script probes each clip's real length and writes it, and an unreadable video is rejected."
136
147
  },
137
148
  "scene_images": {
138
149
  "type": "array",
@@ -146,7 +157,7 @@
146
157
  "items": {
147
158
  "type": "string"
148
159
  },
149
- "description": "On-screen caption lines for templates that declare a caption area (capabilities.payloadDefaults.caption). For image sequences (payloadDefaults.sequence), lines map in order to sequence.items[].caption, with at most one line per image. A replicate asset line's `(… desc: <text>)` suffix is the user's caption for that image: pass it here in the same order (use an empty string for images without one). Otherwise each element is one line. Line-count limits and whether **emphasis** is parsed are declared by the template — read its llmHint, which gen_script prints in full on stderr. **Must** pass when the user explicitly provides bullet-point text / bottom copy. **Also must pass — written by you — when the user did NOT provide any copy but the template is typewriter-driven** (capabilities.durationStrategy=fit-caption): such templates have no narration, so these lines are both the video's content and the thing that decides its duration. Draft them from the material you researched (repo README, page screenshots, the topic). Leaving this empty for a fit-caption template is rejected: nothing auto-generates caption text, and an empty caption renders a titled carousel with no words at all."
160
+ "description": "On-screen caption lines for carousel-caption templates; capabilities.mediaBinding.captions says where they go — one text block, or one caption per media item in order (at most one line per item). A replicate asset line's `(… desc: <text>)` suffix is the user's caption for that image: pass it here in the same order (use an empty string for images without one). Otherwise each element is one line. Line-count limits and whether **emphasis** is parsed are declared by the template — read its llmHint, which gen_script prints in full on stderr. **Must** pass when the user explicitly provides bullet-point text / bottom copy. **Also must pass — written by you — when the user did NOT provide any copy but the template is typewriter-driven** (capabilities.durationStrategy=fit-caption): such templates have no narration, so these lines are both the video's content and the thing that decides its duration. Draft them from the material you researched (repo README, page screenshots, the topic). Leaving this empty for a fit-caption template is rejected: nothing auto-generates caption text, and an empty caption renders a titled carousel with no words at all."
150
161
  },
151
162
  "stub_image_url": {
152
163
  "type": "string",
@@ -190,6 +201,8 @@
190
201
  "sequence_fit",
191
202
  "background_asset",
192
203
  "payload",
204
+ "ending_payload",
205
+ "avatar_id",
193
206
  "motion",
194
207
  "font_id",
195
208
  "font_name",
@@ -2,6 +2,6 @@
2
2
  "skillName": "gen-script",
3
3
  "repoName": "agent-skill-media-maker",
4
4
  "skillId": "474",
5
- "version": "V22",
5
+ "version": "V23",
6
6
  "skillDescription": "Video-script generation skill. Turns a user-supplied topic into a structured Video DSL (JSON) that describes the full video — scene structure, asset requirements, and narrative flow.\n\nUse this skill as soon as the user mentions any of these intents:\n- Write a video script, generate a video script, plan a video, write storyboards\n- Create a short video, plan video content, generate a Video DSL\n- Turn a topic into a video structure / video content plan\n\nEven when the user does not say \"generate the DSL\", use this skill whenever they want to turn a topic into a structured video plan.\n\n⚠️ Stop-and-confirm gate: after this skill returns a DSL, show the full script and wait for the user's explicit confirmation. Never call `prepare_video_assets` in the same turn."
7
7
  }
@@ -9,7 +9,6 @@
9
9
 
10
10
 
11
11
 
12
-
13
12
  from __future__ import annotations
14
13
 
15
14
  import builtins
@@ -248,6 +248,15 @@ def poll_render(
248
248
  timeout=request_timeout,
249
249
  )
250
250
  except (urllib.error.URLError, OSError, ConnectionError) as exc:
251
+
252
+
253
+ if isinstance(exc, urllib.error.HTTPError) and exc.code < 500:
254
+ body = ""
255
+ try:
256
+ body = exc.read().decode("utf-8")
257
+ except Exception:
258
+ pass
259
+ raise RemoteRenderError(f"HTTP {exc.code} {status_path}: {body[:200]}") from exc
251
260
  consecutive_errors += 1
252
261
  print(
253
262
  f" ⚠️ polling network error ({consecutive_errors}/{max_consecutive_errors}): {exc}",
@@ -260,13 +269,6 @@ def poll_render(
260
269
  ) from exc
261
270
  time.sleep(interval)
262
271
  continue
263
- except urllib.error.HTTPError as exc:
264
- body = ""
265
- try:
266
- body = exc.read().decode("utf-8")
267
- except Exception:
268
- pass
269
- raise RemoteRenderError(f"HTTP {exc.code} {status_path}: {body[:200]}") from exc
270
272
 
271
273
  consecutive_errors = 0
272
274