@remixmate/cli 0.9.71 → 0.9.73

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.
Files changed (181) hide show
  1. package/LICENSE +45 -21
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/dist/argv.js +1 -51
  5. package/dist/auth/auth-lock.js +1 -100
  6. package/dist/auth/auto-login.js +7 -75
  7. package/dist/auth/commands.js +40 -290
  8. package/dist/auth/credential-store.js +1 -143
  9. package/dist/auth/device-flow-runner.js +13 -110
  10. package/dist/auth/device-flow.js +1 -132
  11. package/dist/auth/ensure.js +1 -62
  12. package/dist/auth/environment.js +1 -69
  13. package/dist/auth/pending-store.js +1 -45
  14. package/dist/auth/resolve.js +1 -44
  15. package/dist/billing.js +3 -76
  16. package/dist/capabilities.js +1 -75
  17. package/dist/cli.js +39 -211
  18. package/dist/diagnostics.js +2 -70
  19. package/dist/doctor.js +9 -188
  20. package/dist/errors.js +1 -33
  21. package/dist/exec.js +4 -47
  22. package/dist/handlers/gen-digital-human.js +33 -264
  23. package/dist/handlers/gen-image.js +9 -113
  24. package/dist/handlers/gen-post.js +15 -188
  25. package/dist/handlers/gen-video.js +7 -185
  26. package/dist/handlers/gen-voice.js +19 -133
  27. package/dist/handlers/index.js +1 -20
  28. package/dist/handlers/shared.js +1 -66
  29. package/dist/handlers/template-init.js +1 -21
  30. package/dist/http.js +3 -155
  31. package/dist/index.js +1 -8
  32. package/dist/install.js +40 -448
  33. package/dist/manifest.json +53 -13
  34. package/dist/progress.js +2 -15
  35. package/dist/project/commands.js +34 -156
  36. package/dist/project/host.js +1 -151
  37. package/dist/project/resolve.js +1 -65
  38. package/dist/project/store.js +2 -97
  39. package/dist/project/take.js +1 -106
  40. package/dist/project/trace.js +5 -278
  41. package/dist/registry.js +3 -70
  42. package/dist/runner.js +7 -225
  43. package/dist/skill-schema.js +1 -194
  44. package/dist/template/args.js +1 -69
  45. package/dist/template/check.js +2 -30
  46. package/dist/template/commands.js +34 -163
  47. package/dist/template/constants.js +1 -46
  48. package/dist/template/init.js +5 -133
  49. package/dist/template/list.js +1 -46
  50. package/dist/template/preview.js +7 -318
  51. package/dist/template/proc.js +1 -43
  52. package/dist/template/project.js +6 -161
  53. package/dist/template/publish.js +5 -185
  54. package/dist/template/render-client.js +2 -79
  55. package/dist/template/upgrade.js +4 -123
  56. package/dist/text.js +1 -15
  57. package/package.json +2 -35
  58. package/skills/doc-parse/scripts/extract_via_render.py +32 -32
  59. package/skills/export-jianying/scripts/gen_jianying_draft.py +188 -188
  60. package/skills/gen-post/SKILL.md +23 -13
  61. package/skills/gen-post/skill.json +9 -10
  62. package/skills/gen-script/SKILL.md +23 -1
  63. package/skills/gen-script/scripts/gen_script.py +644 -551
  64. package/skills/gen-script/skill.json +12 -0
  65. package/skills/gen-script/version.json +1 -1
  66. package/skills/prepare-video-assets/scripts/prepare_video_assets.py +21 -21
  67. package/skills/render-video/scripts/_chrome_vendor.py +17 -17
  68. package/skills/render-video/scripts/_digital_human_segments.py +34 -34
  69. package/skills/render-video/scripts/_video_probe.py +33 -33
  70. package/skills/render-video/scripts/_vod_polling.py +13 -13
  71. package/skills/render-video/scripts/remote_renderer_client.py +42 -42
  72. package/skills/render-video/scripts/render_video.py +639 -639
  73. package/skills/render-video/scripts/required_props.py +37 -37
  74. package/skills/render-video/scripts/upload_video.py +35 -35
  75. package/skills/render-video/version.json +1 -1
  76. package/skills/template-registry/SKILL.md +16 -0
  77. package/skills/template-registry/scripts/countdown_spec.py +92 -92
  78. package/skills/template-registry/scripts/doc_extract.py +40 -40
  79. package/skills/template-registry/scripts/list_templates.py +303 -191
  80. package/skills/template-registry/scripts/log_diagnostics.py +1 -1
  81. package/skills/template-registry/scripts/match_template.py +87 -87
  82. package/skills/template-registry/scripts/payload_hydrator.py +89 -89
  83. package/skills/template-registry/scripts/registry_loader.py +159 -159
  84. package/skills/template-registry/scripts/render_job_client.py +75 -75
  85. package/skills/template-registry/scripts/showcase_loader.py +44 -44
  86. package/skills/template-registry/skill.json +4 -1
  87. package/skills/template-registry/version.json +1 -1
  88. package/skills/template-registry/video_dsl/runtime/__init__.py +8 -8
  89. package/skills/template-registry/video_dsl/runtime/dsl_validator.py +329 -329
  90. package/skills/template-registry/video_dsl/runtime/narration_budget.py +36 -36
  91. package/skills/template-registry/video_dsl/runtime/payload_contract.py +7 -7
  92. package/skills/template-registry/video_dsl/runtime/prompt_enhancer.py +98 -98
  93. package/skills/template-registry/video_dsl/runtime/timeline_compiler.py +127 -127
  94. package/skills/template-registry/video_dsl/schema/video-dsl-v1alpha1.json +14 -1
  95. package/skills/video-parser/scripts/analyze_video.py +173 -173
  96. package/skills/video-parser/scripts/deconstruct_video.py +91 -91
  97. package/skills/video-parser/scripts/parse_via_render.py +21 -21
  98. package/skills/web-screenshot/scripts/_media_screenshot/__init__.py +4 -4
  99. package/skills/web-screenshot/scripts/_media_screenshot/bootstrap.py +7 -7
  100. package/skills/web-screenshot/scripts/_media_screenshot/browser.py +4 -4
  101. package/skills/web-screenshot/scripts/_media_screenshot/cli_args.py +4 -4
  102. package/skills/web-screenshot/scripts/_media_screenshot/js_loader.py +2 -2
  103. package/skills/web-screenshot/scripts/_media_screenshot/overlay.py +1 -1
  104. package/skills/web-screenshot/scripts/_media_screenshot/reader.py +40 -40
  105. package/skills/web-screenshot/scripts/_media_screenshot/recording.py +11 -11
  106. package/skills/web-screenshot/scripts/_media_screenshot/scenes/__init__.py +8 -8
  107. package/skills/web-screenshot/scripts/_media_screenshot/scenes/arrow.py +2 -2
  108. package/skills/web-screenshot/scripts/_media_screenshot/scenes/caption.py +1 -1
  109. package/skills/web-screenshot/scripts/_media_screenshot/scenes/click.py +1 -1
  110. package/skills/web-screenshot/scripts/_media_screenshot/scenes/code_lines.py +5 -5
  111. package/skills/web-screenshot/scripts/_media_screenshot/scenes/focus.py +1 -1
  112. package/skills/web-screenshot/scripts/_media_screenshot/scenes/highlight.py +3 -3
  113. package/skills/web-screenshot/scripts/_media_screenshot/scenes/hover.py +1 -1
  114. package/skills/web-screenshot/scripts/_media_screenshot/scenes/redact.py +1 -1
  115. package/skills/web-screenshot/scripts/_media_screenshot/scenes/scroll.py +1 -1
  116. package/skills/web-screenshot/scripts/_media_screenshot/scenes/sequence.py +1 -1
  117. package/skills/web-screenshot/scripts/_media_screenshot/scenes/title_card.py +1 -1
  118. package/skills/web-screenshot/scripts/_media_screenshot/scenes/type.py +1 -1
  119. package/skills/web-screenshot/scripts/_media_screenshot/scenes/wait.py +1 -1
  120. package/skills/web-screenshot/scripts/_media_screenshot/scenes/zoom.py +2 -2
  121. package/skills/web-screenshot/scripts/_media_screenshot/screenshot.py +15 -15
  122. package/skills/web-screenshot/scripts/_media_screenshot/storyboard.py +2 -2
  123. package/skills/web-screenshot/scripts/_media_screenshot/template.py +11 -11
  124. package/skills/web-screenshot/scripts/_media_screenshot/trim.py +10 -10
  125. package/skills/web-screenshot/scripts/_media_screenshot/urlguard.py +22 -22
  126. package/skills/web-screenshot/scripts/_media_upload.py +33 -33
  127. package/skills/web-screenshot/scripts/read_page.py +15 -15
  128. package/skills/web-screenshot/scripts/record.py +26 -26
  129. package/skills/web-screenshot/scripts/screenshot.py +5 -5
  130. package/dist/argv.d.ts +0 -15
  131. package/dist/auth/auth-lock.d.ts +0 -26
  132. package/dist/auth/auto-login.d.ts +0 -20
  133. package/dist/auth/commands.d.ts +0 -8
  134. package/dist/auth/credential-store.d.ts +0 -60
  135. package/dist/auth/device-flow-runner.d.ts +0 -58
  136. package/dist/auth/device-flow.d.ts +0 -52
  137. package/dist/auth/ensure.d.ts +0 -55
  138. package/dist/auth/environment.d.ts +0 -38
  139. package/dist/auth/pending-store.d.ts +0 -33
  140. package/dist/auth/resolve.d.ts +0 -30
  141. package/dist/billing.d.ts +0 -44
  142. package/dist/capabilities.d.ts +0 -63
  143. package/dist/cli.d.ts +0 -13
  144. package/dist/diagnostics.d.ts +0 -24
  145. package/dist/doctor.d.ts +0 -22
  146. package/dist/errors.d.ts +0 -29
  147. package/dist/exec.d.ts +0 -18
  148. package/dist/handlers/gen-digital-human.d.ts +0 -17
  149. package/dist/handlers/gen-image.d.ts +0 -20
  150. package/dist/handlers/gen-post.d.ts +0 -21
  151. package/dist/handlers/gen-video.d.ts +0 -19
  152. package/dist/handlers/gen-voice.d.ts +0 -26
  153. package/dist/handlers/index.d.ts +0 -20
  154. package/dist/handlers/shared.d.ts +0 -26
  155. package/dist/handlers/template-init.d.ts +0 -10
  156. package/dist/http.d.ts +0 -72
  157. package/dist/index.d.ts +0 -9
  158. package/dist/install.d.ts +0 -71
  159. package/dist/progress.d.ts +0 -23
  160. package/dist/project/commands.d.ts +0 -19
  161. package/dist/project/host.d.ts +0 -91
  162. package/dist/project/resolve.d.ts +0 -43
  163. package/dist/project/store.d.ts +0 -31
  164. package/dist/project/take.d.ts +0 -50
  165. package/dist/project/trace.d.ts +0 -98
  166. package/dist/registry.d.ts +0 -30
  167. package/dist/runner.d.ts +0 -39
  168. package/dist/skill-schema.d.ts +0 -138
  169. package/dist/template/args.d.ts +0 -25
  170. package/dist/template/check.d.ts +0 -23
  171. package/dist/template/commands.d.ts +0 -25
  172. package/dist/template/constants.d.ts +0 -39
  173. package/dist/template/init.d.ts +0 -28
  174. package/dist/template/list.d.ts +0 -23
  175. package/dist/template/preview.d.ts +0 -60
  176. package/dist/template/proc.d.ts +0 -26
  177. package/dist/template/project.d.ts +0 -47
  178. package/dist/template/publish.d.ts +0 -43
  179. package/dist/template/render-client.d.ts +0 -39
  180. package/dist/template/upgrade.d.ts +0 -44
  181. package/dist/text.d.ts +0 -8
@@ -27,11 +27,18 @@ prompt overrides from the web panel apply here too.
27
27
 
28
28
  Default is all three. Each platform is one LLM call, run concurrently, charged separately.
29
29
 
30
- ## Generate
30
+ ## Where the inputs come from
31
+
32
+ **You fill the video context; the user only says how they want it to read.** Take
33
+ `--topic` / `--hook` / `--source-url` / `--duration` / `--aspect-ratio` from the conversation —
34
+ the video's title, the script, the page it was made from, the render result. Don't ask the
35
+ user for them. The copy is written only from what you pass — anything missing is treated as
36
+ "not provided", never invented — so pass everything you know.
37
+
38
+ The user's own words ("标题去掉 emoji", "语气轻松一点", "只要小红书") go to `--instruction`
39
+ (and `--platform` when they name platforms). If they gave no request, just generate.
31
40
 
32
- The copy is written only from what you pass — anything missing is treated as "not provided",
33
- never invented. So pass what you know about the video: `--topic` is the main input, and
34
- `--hook` / `--source-url` / `--duration` / `--aspect-ratio` sharpen it.
41
+ ## Generate
35
42
 
36
43
  ```bash
37
44
  remixmate gen-post \
@@ -45,15 +52,18 @@ remixmate gen-post \
45
52
  remixmate gen-post --topic "<topic>" --platform xhs --json-output
46
53
  ```
47
54
 
48
- After running `render-video` in the same session, you already know the topic, hook, duration
49
- and aspect ratio from the script — reuse them rather than asking the user again.
55
+ ```bash
56
+ # The user's request shapes a fresh generation on every platform
57
+ remixmate gen-post --topic "<topic>" --instruction "语气轻松一点,标题不要 emoji"
58
+ ```
50
59
 
51
60
  ## Rewrite
52
61
 
53
- `--instruction` rewrites an existing caption instead of starting over. One platform only;
54
- pass the current caption as the draft. Fields the instruction doesn't mention are kept.
55
- Compliance rules still win: asking for superlatives, guarantees or off-platform links gets a
56
- compliant rewording, not a literal one.
62
+ When a caption was already generated earlier in the conversation and the user asks to change
63
+ it, pass that caption back as the draft: `--instruction` plus `--title` / `--description` /
64
+ `--tag` rewrites it instead of starting over. One platform per call. Fields the instruction
65
+ doesn't mention are kept. Compliance rules still win either way: asking for superlatives,
66
+ guarantees or off-platform links gets a compliant rewording, not a literal one.
57
67
 
58
68
  ```bash
59
69
  remixmate gen-post --platform douyin \
@@ -66,14 +76,14 @@ remixmate gen-post --platform douyin \
66
76
 
67
77
  | Flag | Description | Default |
68
78
  |------|-------------|---------|
69
- | `--topic` | What the video is about (required unless `--instruction`) | — |
79
+ | `--topic` | What the video is about (required unless rewriting) | — |
70
80
  | `--platform` | `douyin` / `xiaohongshu` / `tiktok` / `all`; repeatable or comma-separated | `all` |
71
81
  | `--hook` | Opening hook line | none |
72
82
  | `--source-url` | Project/source URL, context only | none |
73
83
  | `--duration` | Seconds | none |
74
84
  | `--aspect-ratio` | e.g. `9:16` | `9:16` |
75
85
  | `--language` | Output language | per platform (see table) |
76
- | `--instruction` | Rewrite request, ≤ 500 chars | none |
86
+ | `--instruction` | The user's request, ≤ 500 chars; rewrites when a draft is given | none |
77
87
  | `--title` / `--description` / `--tag` | Current caption to rewrite | none |
78
88
  | `--prompt` | Replace the platform prompt for this run; placeholders `{{topic}}` `{{hook}}` `{{sourceUrl}}` `{{durationSec}}` `{{aspectRatio}}` `{{language}}` | saved/default prompt |
79
89
  | `--render-id` / `--video-project-id` | Save the result to a studio take (shows in the web publish panel) | not saved |
@@ -101,4 +111,4 @@ Each platform charges credits. Relay the footer when it appears:
101
111
  - **Token missing / 401**: set `PRIV_TOKEN` or run `remixmate login`.
102
112
  - **`不支持的平台`**: the platform code is not one the backend knows.
103
113
  - **`模型响应超时` / timeout**: retry; generating fewer platforms at once also helps.
104
- - **`--instruction` errors**: pass exactly one `--platform` and the current caption.
114
+ - **Rewrite errors**: a draft (`--title` / `--description` / `--tag`) needs `--instruction` and exactly one `--platform`.
@@ -4,7 +4,7 @@
4
4
  "tier": "tool",
5
5
  "category": "consuming",
6
6
  "title": "Social Post Copy",
7
- "description": "Write the text of a social post for a finished video — title, description and hashtags — per platform (text only; it does not upload or publish the video): Douyin (抖音), Xiaohongshu (小红书) and TikTok. Same prompts as the web studio's publish panel, including the platform's length limits and ad-law / community-guideline compliance rules, and the user's saved prompt overrides. Generates all three platforms by default; pass `platform` to pick. Give it the video's topic plus any hook, source URL, duration and aspect ratio you know — it only writes from what it is given. With `instruction` plus the current title/description/tags it rewrites an existing caption instead. Each platform is one LLM call and costs credits.",
7
+ "description": "Write the text of a social post for a finished video — title, description and hashtags — per platform (text only; it does not upload or publish the video): Douyin (抖音), Xiaohongshu (小红书) and TikTok. Same prompts as the web studio's publish panel, including the platform's length limits and ad-law / community-guideline compliance rules, and the user's saved prompt overrides. Generates all three platforms by default; pass `platform` to pick. Fill the video context yourself from the conversation — topic, hook, source URL, duration, aspect ratio — rather than asking the user; it only writes from what it is given. `instruction` carries the user's own request: alone it shapes a fresh generation, and with the current title/description/tags (from an earlier run in the conversation) it rewrites that caption instead. Each platform is one LLM call and costs credits.",
8
8
  "auth": "required",
9
9
  "envVars": [
10
10
  "PRIV_TOKEN",
@@ -20,7 +20,7 @@
20
20
  "properties": {
21
21
  "topic": {
22
22
  "type": "string",
23
- "description": "What the video is about — the main input for the copy (required unless rewriting with `instruction`)"
23
+ "description": "What the video is about — the main input for the copy. Take it from the conversation (video title, script, source page). Required unless rewriting an existing caption."
24
24
  },
25
25
  "platform": {
26
26
  "type": "array",
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "instruction": {
53
53
  "type": "string",
54
- "description": "Rewrite request for an existing caption, e.g. 'shorter title, drop the emoji'. Requires exactly one platform plus the current title / description / tag. Max 500 characters."
54
+ "description": "The user's request for how the copy should read, e.g. 'shorter title, drop the emoji'. Alone: applied as an extra requirement to a fresh generation. With the current title / description / tag: rewrites that caption (exactly one platform). Max 500 characters."
55
55
  },
56
56
  "title": {
57
57
  "type": "string",
@@ -89,22 +89,21 @@
89
89
  },
90
90
  "ui": {
91
91
  "primary": [
92
- "topic",
93
92
  "platform",
94
- "hook"
93
+ "instruction"
95
94
  ],
96
- "advanced": [
95
+ "advanced": [],
96
+ "hidden": [
97
+ "topic",
98
+ "hook",
97
99
  "source_url",
98
100
  "duration",
99
101
  "aspect_ratio",
100
102
  "language",
101
- "instruction",
102
103
  "title",
103
104
  "description",
104
105
  "tag",
105
- "prompt"
106
- ],
107
- "hidden": [
106
+ "prompt",
108
107
  "render_id",
109
108
  "video_project_id",
110
109
  "json_output"
@@ -41,6 +41,25 @@ The full schema is `template-registry` skill's `video_dsl/schema/video-dsl-v1alp
41
41
 
42
42
  **Per-template reference DSLs do not ship with this package.** `video_dsl/schema/examples/` is a local-only directory: it is absent from the published npm package (and has never existed in the repo). Do not go looking for examples — the authoritative per-template contract ships inside the registry's `template.json`, see below.
43
43
 
44
+ ## Agent behavior: template selection comes before the script
45
+
46
+ The template decides the scene structure, the layouts and the fields the script must fill, so it is settled **before** `gen_script` runs — swapping templates after the user has read a script means rewriting all of it. Every call that passes `--template-id` also passes `--template-source`:
47
+
48
+ | How the template was chosen | `--template-source` | Confirm with the user? |
49
+ |---|---|---|
50
+ | The user named it: its id or name, a pasted template detail-page prompt or link, or it was settled earlier in this conversation | `user-explicit` | No — go straight to the script |
51
+ | The user named none; you offered candidates and the user picked or approved one in the chat | `user-confirmed` (+ `--template-candidates` for each id you offered) | Already done |
52
+ | You picked it and the user has not seen it yet | — | **Yes — do not call gen_script.** `--template-source auto` is refused |
53
+
54
+ When the user named no template:
55
+
56
+ 1. List templates with `template_registry` and let its hard constraints drop the ones that cannot serve the request: `filter_aspect` / `filter_language`, `user_media` (the user handed over images / videos, or did not), `source_doc` (a source document, by kind), `narration`. Set only what the request pins down. Each dropped template comes back in `excluded` with its reason.
57
+ 2. Rank what is left against the request using each template's `llmHint`, `description` and `styleTags`; its `notFor` lists the requests it is the wrong pick for, which is what separates close siblings. A Top-N / countdown-shaped request favours templates whose `capabilities.sceneStrategy` is `countdown`. Use coarse levels (recommended / also fits), not precise numeric scores — they suggest more certainty than the ranking has.
58
+ 3. Show 2–3 candidates, recommended first: name, one line on why it fits, its detail-page link (`pageUrl`) so the user can watch samples. When two candidates differ mainly in look, say so — that is a choice for the user's eyes, not yours. When only one template fits, still say which one you will use and ask. **End the turn.**
59
+ 4. After the user answers, call `gen_script` with that template, `--template-source user-confirmed` and `--template-candidates` for every id you offered. If the user names a template outside the shortlist, that is `user-explicit`.
60
+
61
+ Never mark a template `user-confirmed` the user has not seen and approved. The value is recorded at `meta.templateSelection` and is how a later turn knows the template is already settled.
62
+
44
63
  ## Agent behavior: DSL generation when a template is selected
45
64
 
46
65
  **When the user explicitly specifies a template id, the agent must first read that template's full definition from the registry, then generate the DSL in the template's native shape. The agent must not generate the DSL from scratch ignoring the template definition, and must not produce a generic DSL first and rely on `template-registry` to force-match the template later.**
@@ -405,7 +424,8 @@ Env vars `STUB_IMAGE_URL` / `STUB_VIDEO_URL` also work — their priority is low
405
424
 
406
425
  1. **Script path**: read the system-injected `Base directory for this skill: <path>` as `<SkillDir>`. Every command below uses `<SkillDir>/scripts/gen_script.py`; never hard-code paths.
407
426
  2. **Understand the request**: extract topic, duration, style, audience, etc.
408
- 3. **If the user specifies a template, read it first**: load the matching `template.json` via `template-registry` and confirm its template-specific fields and asset requirements. Do not skip this step.
427
+ 3. **Settle the template**: if the user named one, that is `--template-source user-explicit`; otherwise offer candidates and wait for the user's pick (`user-confirmed`) — see "Agent behavior: template selection comes before the script".
428
+ 3b. **Read the template first**: load the matching `template.json` via `template-registry` and confirm its template-specific fields and asset requirements. Do not skip this step.
409
429
  4. **Generate the DSL**: pick the flags the target template's `capabilities` call for (see *Common CLI flags*); the template's `llmHint` says what to fill in afterwards.
410
430
  5. **Schema validation**: make sure the output DSL conforms to v1alpha1.
411
431
  6. **User confirmation**: show the script summary and wait for confirmation, per the rules above.
@@ -455,6 +475,8 @@ python3 <SkillDir>/scripts/gen_script.py \
455
475
  | `--speed` | Narration speech rate (0.5–2.0), written to `global.narration.speed` and applied when `prepare_video_assets` calls gen-voice. Pass it whenever the user picked a speed (the replicate form's 语速 field sends one). Above ~1.3 subtitle alignment drifts and the delivery turns mechanical — shorten the script instead. | `1.0` |
456
476
  | `--variant` | Template visual variant id (a key of the template's `variants`; `template-registry --list-templates` prints them as `variantIds`). Written to `meta.templateVariant`, which takes precedence over the fuzzy `--style` match. Pass it whenever the user picked a style — the replicate card shows it as `名字(id)`, e.g. `视觉风格: 紫色科技(tech-purple)`; pass the id in the parentheses. Requires `--template-id`; unknown ids are rejected. | template default |
457
477
  | `--background-preset` | Scene background preset, one of the template's `customPayloadSchema.background.preset` values. Written to every scene's `customPayload.background.preset` (other keys of the template's default background are kept). Pass it whenever the user picked a background, e.g. `背景样式: 纯色(solid)` → `solid`. `image` / `video` also need `customPayload.background.assetRef`. Requires `--template-id`; unsupported values are rejected. | template default |
478
+ | `--template-source` | How `--template-id` was chosen: `user-explicit` / `user-confirmed` / `auto`, written to `meta.templateSelection.source`. `auto` is refused — confirm with the user first (see "Agent behavior: template selection comes before the script"). Omitted = not recorded, with a stderr notice. Requires `--template-id`. | — |
479
+ | `--template-candidates` | Repeatable. Template ids offered to the user, recommended first → `meta.templateSelection.candidates`. With `user-confirmed`, `--template-id` must be one of them. | — |
458
480
  | `--allow-digital-human` | Whether to allow digital-human assets. | off |
459
481
  | `--allow-ai-video` | Whether to allow AI-generated video assets. | off |
460
482
  | `--validate` | Validate-only mode: only validate the input DSL. | — |