@remixmate/cli 0.1.0 → 0.1.2

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 (126) hide show
  1. package/README.md +100 -83
  2. package/README.zh-CN.md +183 -0
  3. package/dist/handlers/gen-digital-human.d.ts +12 -0
  4. package/dist/handlers/gen-digital-human.js +157 -0
  5. package/dist/handlers/gen-image.js +5 -41
  6. package/dist/handlers/gen-video.d.ts +18 -0
  7. package/dist/handlers/gen-video.js +153 -0
  8. package/dist/handlers/gen-voice.js +2 -12
  9. package/dist/handlers/index.js +4 -2
  10. package/dist/handlers/shared.d.ts +26 -0
  11. package/dist/handlers/shared.js +66 -0
  12. package/dist/http.d.ts +4 -2
  13. package/dist/http.js +5 -3
  14. package/dist/manifest.json +38 -24
  15. package/dist/registry.d.ts +5 -16
  16. package/dist/registry.js +11 -17
  17. package/dist/skill-schema.d.ts +65 -0
  18. package/dist/skill-schema.js +53 -0
  19. package/package.json +5 -4
  20. package/skills/export-jianying/scripts/gen_jianying_draft.py +4 -4
  21. package/skills/export-jianying/skill.json +1 -0
  22. package/skills/gen-digital-human/SKILL.md +23 -46
  23. package/skills/gen-digital-human/skill.json +4 -2
  24. package/skills/gen-digital-human/version.json +1 -1
  25. package/skills/gen-image/SKILL.md +2 -2
  26. package/skills/gen-image/skill.json +3 -1
  27. package/skills/gen-image/version.json +1 -1
  28. package/skills/gen-script/SKILL.md +13 -13
  29. package/skills/gen-script/scripts/gen_script.py +50 -12
  30. package/skills/gen-script/skill.json +3 -1
  31. package/skills/gen-video/SKILL.md +22 -33
  32. package/skills/gen-video/skill.json +4 -2
  33. package/skills/gen-video/version.json +1 -1
  34. package/skills/gen-voice/SKILL.md +1 -1
  35. package/skills/gen-voice/skill.json +1 -0
  36. package/skills/gen-voice/version.json +1 -1
  37. package/skills/prepare-video-assets/SKILL.md +2 -2
  38. package/skills/prepare-video-assets/skill.json +2 -1
  39. package/skills/render-video/scripts/render_video.py +8 -8
  40. package/skills/render-video/skill.json +1 -0
  41. package/skills/{template-bind → template-registry}/README.md +4 -4
  42. package/skills/{template-bind → template-registry}/SKILL.md +14 -12
  43. package/skills/template-registry/scripts/list_templates.py +214 -0
  44. package/skills/{template-bind → template-registry}/scripts/match_template.py +4 -3
  45. package/skills/{template-bind → template-registry}/scripts/registry_loader.py +1 -1
  46. package/skills/{template-bind → template-registry}/scripts/template_paths.py +7 -7
  47. package/skills/{template-bind → template-registry}/skill.json +8 -5
  48. package/skills/template-registry/version.json +7 -0
  49. package/skills/{template-bind → template-registry}/video_dsl/README.md +2 -2
  50. package/skills/{template-bind → template-registry}/video_dsl/runtime/__init__.py +1 -1
  51. package/skills/video-parser/SKILL.md +47 -160
  52. package/skills/video-parser/skill.json +4 -4
  53. package/skills/video-parser/version.json +1 -1
  54. package/skills/web-capture/SKILL.md +407 -116
  55. package/skills/web-capture/scripts/_media_screenshot/__init__.py +21 -0
  56. package/skills/web-capture/scripts/_media_screenshot/bootstrap.py +34 -0
  57. package/skills/web-capture/scripts/_media_screenshot/browser.py +86 -0
  58. package/skills/web-capture/scripts/_media_screenshot/cli_args.py +111 -0
  59. package/skills/web-capture/scripts/_media_screenshot/js/arrow.js +86 -0
  60. package/skills/web-capture/scripts/_media_screenshot/js/caption.js +27 -0
  61. package/skills/web-capture/scripts/_media_screenshot/js/clear_overlay.js +5 -0
  62. package/skills/web-capture/scripts/_media_screenshot/js/cursor_bootstrap.js +26 -0
  63. package/skills/web-capture/scripts/_media_screenshot/js/cursor_hide.js +6 -0
  64. package/skills/web-capture/scripts/_media_screenshot/js/cursor_move.js +12 -0
  65. package/skills/web-capture/scripts/_media_screenshot/js/cursor_ripple.js +25 -0
  66. package/skills/web-capture/scripts/_media_screenshot/js/element_zoom.js +72 -0
  67. package/skills/web-capture/scripts/_media_screenshot/js/element_zoom_restore.js +21 -0
  68. package/skills/web-capture/scripts/_media_screenshot/js/fade_out_overlays.js +10 -0
  69. package/skills/web-capture/scripts/_media_screenshot/js/focus.js +38 -0
  70. package/skills/web-capture/scripts/_media_screenshot/js/highlight.js +97 -0
  71. package/skills/web-capture/scripts/_media_screenshot/js/overlay_bootstrap.js +19 -0
  72. package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_in.js +54 -0
  73. package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_out.js +11 -0
  74. package/skills/web-capture/scripts/_media_screenshot/js/page_zoom_restore.js +13 -0
  75. package/skills/web-capture/scripts/_media_screenshot/js/redact.js +33 -0
  76. package/skills/web-capture/scripts/_media_screenshot/js/scroll.js +26 -0
  77. package/skills/web-capture/scripts/_media_screenshot/js/scroll_through.js +18 -0
  78. package/skills/web-capture/scripts/_media_screenshot/js/sequence.js +76 -0
  79. package/skills/web-capture/scripts/_media_screenshot/js/settled_check.js +15 -0
  80. package/skills/web-capture/scripts/_media_screenshot/js/title_card.js +71 -0
  81. package/skills/web-capture/scripts/_media_screenshot/js_loader.py +14 -0
  82. package/skills/web-capture/scripts/_media_screenshot/overlay.py +17 -0
  83. package/skills/web-capture/scripts/_media_screenshot/recording.py +100 -0
  84. package/skills/web-capture/scripts/_media_screenshot/scenes/__init__.py +39 -0
  85. package/skills/web-capture/scripts/_media_screenshot/scenes/arrow.py +50 -0
  86. package/skills/web-capture/scripts/_media_screenshot/scenes/caption.py +20 -0
  87. package/skills/web-capture/scripts/_media_screenshot/scenes/click.py +35 -0
  88. package/skills/web-capture/scripts/_media_screenshot/scenes/code_lines.py +54 -0
  89. package/skills/web-capture/scripts/_media_screenshot/scenes/focus.py +24 -0
  90. package/skills/web-capture/scripts/_media_screenshot/scenes/highlight.py +54 -0
  91. package/skills/web-capture/scripts/_media_screenshot/scenes/hover.py +28 -0
  92. package/skills/web-capture/scripts/_media_screenshot/scenes/redact.py +32 -0
  93. package/skills/web-capture/scripts/_media_screenshot/scenes/scroll.py +32 -0
  94. package/skills/web-capture/scripts/_media_screenshot/scenes/sequence.py +43 -0
  95. package/skills/web-capture/scripts/_media_screenshot/scenes/title_card.py +20 -0
  96. package/skills/web-capture/scripts/_media_screenshot/scenes/type.py +42 -0
  97. package/skills/web-capture/scripts/_media_screenshot/scenes/wait.py +9 -0
  98. package/skills/web-capture/scripts/_media_screenshot/scenes/zoom.py +72 -0
  99. package/skills/web-capture/scripts/_media_screenshot/screenshot.py +166 -0
  100. package/skills/web-capture/scripts/_media_screenshot/storyboard.py +88 -0
  101. package/skills/web-capture/scripts/_media_screenshot/template.py +119 -0
  102. package/skills/web-capture/scripts/_media_screenshot/trim.py +82 -0
  103. package/skills/web-capture/scripts/record.py +186 -0
  104. package/skills/web-capture/scripts/screenshot.py +94 -0
  105. package/skills/web-capture/skill.json +15 -14
  106. package/skills/web-capture/templates/github-code-tour.json +59 -0
  107. package/skills/web-capture/templates/github-readme-tour.json +77 -0
  108. package/skills/web-capture/templates/github-repo-intro.json +74 -0
  109. package/skills/web-capture/version.json +2 -2
  110. package/dist/handlers/template-bind.d.ts +0 -15
  111. package/dist/handlers/template-bind.js +0 -149
  112. package/skills/gen-digital-human/scripts/gen_digital_human_video.py +0 -574
  113. package/skills/gen-video/scripts/gen_video.py +0 -591
  114. package/skills/template-bind/version.json +0 -7
  115. package/skills/web-capture/scripts/web_capture.py +0 -461
  116. /package/skills/{template-bind → template-registry}/scripts/check_contracts.py +0 -0
  117. /package/skills/{template-bind → template-registry}/scripts/render_job_client.py +0 -0
  118. /package/skills/{template-bind → template-registry}/scripts/sync_registry.py +0 -0
  119. /package/skills/{template-bind → template-registry}/video_dsl/runtime/dsl_validator.py +0 -0
  120. /package/skills/{template-bind → template-registry}/video_dsl/runtime/prompt_enhancer.py +0 -0
  121. /package/skills/{template-bind → template-registry}/video_dsl/runtime/template_binder.py +0 -0
  122. /package/skills/{template-bind → template-registry}/video_dsl/runtime/timeline_compiler.py +0 -0
  123. /package/skills/{template-bind → template-registry}/video_dsl/schema/render-plan-v1alpha1.json +0 -0
  124. /package/skills/{template-bind → template-registry}/video_dsl/schema/template-binding-v1alpha1.json +0 -0
  125. /package/skills/{template-bind → template-registry}/video_dsl/schema/template-definition-v1alpha1.json +0 -0
  126. /package/skills/{template-bind → template-registry}/video_dsl/schema/video-dsl-v1alpha1.json +0 -0
@@ -12,7 +12,7 @@ Usage:
12
12
 
13
13
  Environment variables:
14
14
  VIDEO_DSL_SCHEMA_PATH - DSL schema file path
15
- (default: skills/template-bind/video_dsl/schema/video-dsl-v1alpha1.json)
15
+ (default: skills/template-registry/video_dsl/schema/video-dsl-v1alpha1.json)
16
16
  """
17
17
 
18
18
  import argparse
@@ -24,20 +24,19 @@ import uuid
24
24
 
25
25
  SCHEMA_PATH = os.environ.get(
26
26
  "VIDEO_DSL_SCHEMA_PATH",
27
- "skills/template-bind/video_dsl/schema/video-dsl-v1alpha1.json",
27
+ "skills/template-registry/video_dsl/schema/video-dsl-v1alpha1.json",
28
28
  )
29
29
 
30
30
  # prompt_enhancer 路径动态添加
31
- _TEMPLATE_DSL_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "template-bind", "video_dsl")
31
+ _TEMPLATE_DSL_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "template-registry", "video_dsl")
32
32
  if os.path.isdir(_TEMPLATE_DSL_DIR):
33
33
  sys.path.insert(0, os.path.abspath(os.path.join(_TEMPLATE_DSL_DIR, "..")))
34
34
 
35
- # Shared Python lib lives under skills/template-bind/scripts/ — the de-facto
36
- # cross-skill module location (registry_loader, template_paths, etc.). Named
37
- # generically here so its host skill could be renamed without touching every
38
- # caller. See AGENTS.md for the convention.
35
+ # Shared Python lib lives under skills/template-registry/scripts/ — the de-facto
36
+ # cross-skill module location (registry_loader, template_paths, etc.). See
37
+ # AGENTS.md for the convention.
39
38
  _SHARED_SCRIPTS_DIR = os.path.join(
40
- os.path.dirname(__file__), "..", "..", "template-bind", "scripts"
39
+ os.path.dirname(__file__), "..", "..", "template-registry", "scripts"
41
40
  )
42
41
  if os.path.isdir(_SHARED_SCRIPTS_DIR):
43
42
  sys.path.insert(0, os.path.abspath(_SHARED_SCRIPTS_DIR))
@@ -58,7 +57,7 @@ except ImportError:
58
57
  _HAS_REGISTRY_LOADER = False
59
58
 
60
59
  try:
61
- # Centralized monorepo-path resolver living in template-bind/scripts/;
60
+ # Centralized monorepo-path resolver living in template-registry/scripts/;
62
61
  # the import works because the same sys.path.insert above pointed at it.
63
62
  from template_paths import monorepo_template_src_dir as _monorepo_template_src_dir
64
63
  except ImportError:
@@ -326,7 +325,7 @@ def _load_template_config(template_id: str) -> dict | None:
326
325
  解析顺序(与 match_template / template_binder 保持一致):
327
326
  1. 通过 registry_loader 从 monorepo template-library/packages/metadata/registry.json
328
327
  (或 VIDEO_TEMPLATE_REGISTRY[_URL] 环境变量)加载,并按 templateId 匹配。
329
- 2. 兜底:旧路径 apps/ab-skill/skills/template-bind/video_dsl/templates/<id>/template.json
328
+ 2. 兜底:旧路径 template-registry/video_dsl/templates/<id>/template.json
330
329
  (仅在仓库还残留旧目录时使用)。
331
330
  返回完整 template dict(含 supportedAspectRatios / assetRequirements / slotMapping 等),
332
331
  找不到时返回 None。
@@ -343,7 +342,7 @@ def _load_template_config(template_id: str) -> dict | None:
343
342
 
344
343
  # 兜底:旧的本地目录布局
345
344
  legacy_dir = os.path.join(
346
- os.path.dirname(__file__), "..", "..", "template-bind", "video_dsl", "templates"
345
+ os.path.dirname(__file__), "..", "..", "template-registry", "video_dsl", "templates"
347
346
  )
348
347
  legacy_file = os.path.join(legacy_dir, template_id, "template.json")
349
348
  if os.path.isfile(legacy_file):
@@ -408,7 +407,7 @@ def _locate_template_dir(template_id: str) -> str | None:
408
407
  """定位模板源码目录(template-library/packages/templates/src/<id>/)。
409
408
 
410
409
  路径解析已集中到 ``template_paths.monorepo_template_src_dir``;
411
- 当 helper 不可用(template-bind/scripts/ 不在 sys.path)时回退到 None,
410
+ 当 helper 不可用(template-registry/scripts/ 不在 sys.path)时回退到 None,
412
411
  与原始函数"找不到就返回 None"的语义一致。
413
412
  """
414
413
  if _monorepo_template_src_dir is None:
@@ -1055,6 +1054,11 @@ Examples:
1055
1054
  default=None,
1056
1055
  help="On-screen subheadline / project name (e.g. 'Pixelle-Video'). Stored at meta.subheadline and pushed into textLayers[role=subheadline]. Independent from CC subtitles (global.subtitle).",
1057
1056
  )
1057
+ parser.add_argument(
1058
+ "--skip-asset-generation",
1059
+ action="store_true",
1060
+ help="Skill-creator / template-creator helper: when set, every produced AssetRef is marked as already generated with a stub URL — no gen-image / gen-voice / gen-video calls are needed. Implies --stub-image-url + --stub-video-url with default sentinels (https://placeholder.local/stub.png|.mp4) when those flags are absent, and additionally rewrites every gen-voice asset to source=existing + status=generated + a placeholder audio URL. Useful when a downstream agent only wants the DSL shape (e.g. to feed into try_render with all assets pre-stubbed).",
1061
+ )
1058
1062
  parser.add_argument(
1059
1063
  "--stub-image-url",
1060
1064
  default=None,
@@ -1158,6 +1162,22 @@ Examples:
1158
1162
  print(f"⚠️ STUB_VIDEO_URL env var detected ({env_v}); using it as the video stub. Prefer passing --stub-video-url explicitly, or unset the env var.", file=sys.stderr)
1159
1163
  stub_video_url = env_v
1160
1164
 
1165
+ # --skip-asset-generation 是为下游"只想要 DSL shape"的 agent 设计的
1166
+ # 一键开关:等价于 --stub-image-url + --stub-video-url + 把 gen-voice 资产
1167
+ # 也写成 source=existing + status=generated。当用户没显式提供 stub URL 时
1168
+ # 用一组 sentinel 占位(https://placeholder.local/...),模板创作 / 调试场景
1169
+ # 不会真的去 fetch 这些 URL。
1170
+ if args.skip_asset_generation:
1171
+ if not stub_image_url:
1172
+ stub_image_url = "https://placeholder.local/stub.png"
1173
+ if not stub_video_url:
1174
+ stub_video_url = "https://placeholder.local/stub.mp4"
1175
+ print(
1176
+ "ℹ️ --skip-asset-generation: forcing all assets to source=existing/status=generated "
1177
+ f"(image={stub_image_url}, video={stub_video_url}, audio=https://placeholder.local/stub.mp3)",
1178
+ file=sys.stderr,
1179
+ )
1180
+
1161
1181
  dsl = build_dsl(
1162
1182
  topic=args.topic,
1163
1183
  platform=args.platform,
@@ -1178,6 +1198,24 @@ Examples:
1178
1198
  caption_lines=args.caption_lines,
1179
1199
  )
1180
1200
 
1201
+ # Post-process for --skip-asset-generation: rewrite all gen-voice / gen-digital-human
1202
+ # assets to be already-generated stubs. Image / video are already covered by the
1203
+ # stub_image_url / stub_video_url params threaded through build_dsl above.
1204
+ if args.skip_asset_generation:
1205
+ _AUDIO_STUB = "https://placeholder.local/stub.mp3"
1206
+ _VIDEO_STUB = stub_video_url # same sentinel for digital-human placeholder
1207
+ for asset in dsl.get("assets", []):
1208
+ src = asset.get("source")
1209
+ if src in ("gen-voice",):
1210
+ asset["source"] = "existing"
1211
+ asset["status"] = "generated"
1212
+ asset["url"] = _AUDIO_STUB
1213
+ # payload 留作 reference(renderer 不会再读它,因为 status=generated)
1214
+ elif src in ("gen-digital-human",):
1215
+ asset["source"] = "existing"
1216
+ asset["status"] = "generated"
1217
+ asset["url"] = _VIDEO_STUB
1218
+
1181
1219
  errors = validate_dsl(dsl)
1182
1220
  if errors:
1183
1221
  print("❌ generated DSL failed validation:", file=sys.stderr)
@@ -2,6 +2,7 @@
2
2
  "name": "gen-script",
3
3
  "toolName": "gen_script",
4
4
  "tier": "orchestration",
5
+ "category": "authoring",
5
6
  "title": "Video Script Generation",
6
7
  "description": "Video script generation: turn a topic into a structured Video DSL (JSON) that describes the full video — scene structure, asset requirements, and narrative flow.",
7
8
  "envVars": ["DEFAULT_IMAGE_MODEL", "DEFAULT_VIDEO_MODEL", "STUB_IMAGE_URL", "STUB_VIDEO_URL"],
@@ -34,7 +35,8 @@
34
35
  "description": "Bottom typewriter text lines for templates that support a caption/typewriter area (e.g. spotlight-card). Each element is one line of text. Supports **emphasis** syntax (rendered with accent color). **Must** pass when the user explicitly provides bullet-point text / bottom copy for the video."
35
36
  },
36
37
  "stub_image_url": { "type": "string", "description": "Test-mode image stub URL. Only pass when the user explicitly says things like 'just testing / don't actually generate / use a placeholder image / stub URL / save credits' AND provides a concrete URL. With this set, every image AssetRef in the produced DSL is written as source=existing, status=generated, url=<this URL> — no gen-image call. Do not pass otherwise; if the user expressed the intent without a URL, ask for one — do not invent one." },
37
- "stub_video_url": { "type": "string", "description": "Test-mode video stub URL. Only pass when the user explicitly says things like 'just testing / don't actually generate the video / placeholder clip / save credits' AND provides a concrete URL. With this set, every video AssetRef in the produced DSL is written as source=existing, status=generated, url=<this URL> — no gen-video call. Do not pass otherwise; if the user expressed the intent without a URL, ask for one — do not invent one." }
38
+ "stub_video_url": { "type": "string", "description": "Test-mode video stub URL. Only pass when the user explicitly says things like 'just testing / don't actually generate the video / placeholder clip / save credits' AND provides a concrete URL. With this set, every video AssetRef in the produced DSL is written as source=existing, status=generated, url=<this URL> — no gen-video call. Do not pass otherwise; if the user expressed the intent without a URL, ask for one — do not invent one." },
39
+ "skip_asset_generation": { "type": "boolean", "description": "All-in-one switch for downstream agents (e.g. template-creator) that only want the DSL shape: every produced AssetRef is marked as already generated with placeholder URLs (image: https://placeholder.local/stub.png, video: stub.mp4, audio: stub.mp3). Implies the equivalent of --stub-image-url + --stub-video-url with sentinel defaults plus the same rewrite for gen-voice / gen-digital-human assets. Useful when the agent only needs to inspect DSL structure or feed it into try_render_local with all assets pre-stubbed." }
38
40
  },
39
41
  "required": ["topic"]
40
42
  }
@@ -17,11 +17,13 @@ triggers:
17
17
 
18
18
  # AI Video Generation Skill
19
19
 
20
- Wraps ab-api's `POST /model/genVideo` (the same endpoint the web "Lingchuang AI Video" tool uses), authenticated with the **Tianyan privateToken**, routed through LiteLLM to **Seedance** or **Veo**.
20
+ Wraps ab-api's `POST /model/genVideo` (the same endpoint the web "Lingchuang AI Video" tool uses), authenticated with the **Tianyan privateToken**, routed through LiteLLM to **Seedance** or **Veo**. Generation is async — the handler submits the task and polls `/model/getVideoStatus` until completion.
21
+
22
+ > This skill was migrated from a Python script to an ab-skill CLI HTTP handler (`entry.type: http`). The agent invocation is unchanged (same tool name `gen_video`, same params as in `skill.json`); local repro goes through `ab-skill gen-video ...`.
21
23
 
22
24
  ## Models
23
25
 
24
- Aligned with `gen_video.py`'s `GEN_VIDEO_MODEL_PRESETS` and the frontend `AI_VIDEO_MODELS`:
26
+ Aligned with the handler's `MODEL_ALIASES` and the frontend `AI_VIDEO_MODELS`:
25
27
 
26
28
  | LiteLLM `model` | Display name | Provider | Duration | Notes |
27
29
  |-----------------|--------------|----------|----------|-------|
@@ -49,29 +51,28 @@ Aligned with `gen_video.py`'s `GEN_VIDEO_MODEL_PRESETS` and the frontend `AI_VID
49
51
 
50
52
  ## Auth & environment
51
53
 
52
- No skill-local env file — the executing process inherits the system environment. Examples below say `python`; on macOS you may need `python3`.
54
+ No skill-local env file — the executing process inherits the system environment.
53
55
 
54
56
  - **Enterprise OpenClaw**: auth is already injected, **no need** for `PRIV_TOKEN` / `--priv-token`.
55
- - **Other environments**: configure the token. Without a token, non-interactive runs fail; interactive ones may prompt.
57
+ - **Other environments**: configure the token. Without a token, non-interactive runs fail.
56
58
 
57
59
  | Env var | Description | Default |
58
60
  |---------|-------------|---------|
59
61
  | `PRIV_TOKEN` | Tianyan token; `--priv-token` overrides | none |
60
62
  | `MM_VIDEO_MODEL` | Default model id | `doubao-seedance-1-5-pro-251215` |
61
- | `MM_API_BASE_URL` | API root | see `gen_video.py` default |
63
+ | `MM_API_BASE_URL` | API root; `--api-base-url` overrides | `http://localhost:2999/api` |
62
64
  | `AGENT_NAME` | Optional `x-invoke-agent` header | none |
63
65
 
64
66
  ## Operations
65
67
 
66
- 1. **Script path**: read the system-injected `Base directory for this skill: <path>` as `<SkillDir>` and always use `<SkillDir>/scripts/gen_video.py`. Do not hardcode paths.
67
- 2. **Prompt**: include camera language ("aerial shot", "slow motion", "push-in") and dynamic descriptions for better results. Chinese or English both work.
68
- 3. By default only the URL is printed; pass `--download` (and optional `--output`) to save locally.
69
- 4. **Async job**: video generation is async; the script polls until completion (typically 1–3 minutes).
68
+ 1. **Prompt**: include camera language ("aerial shot", "slow motion", "push-in") and dynamic descriptions for better results. Chinese or English both work. For pure image-to-video, an empty prompt with first/last frame is allowed.
69
+ 2. **Async job**: video generation is async; the handler polls until completion (typically 1–3 minutes) and emits `__progress__` lines.
70
+ 3. **Surface results**: stdout prints the video URL on its own line; show it directly to the user (no download needed the URL is cloud-persisted).
70
71
 
71
72
  ### Seedance text-to-video (default model)
72
73
 
73
74
  ```bash
74
- python3 <SkillDir>/scripts/gen_video.py \
75
+ ab-skill gen-video \
75
76
  --prompt "<video description>" \
76
77
  --duration 5 \
77
78
  --ratio "16:9"
@@ -79,8 +80,10 @@ python3 <SkillDir>/scripts/gen_video.py \
79
80
 
80
81
  ### Seedance first/last frame + audio
81
82
 
83
+ Frame images accept local file paths, HTTPS URLs, or data URIs (local files are base64-encoded into a data URI).
84
+
82
85
  ```bash
83
- python3 <SkillDir>/scripts/gen_video.py \
86
+ ab-skill gen-video \
84
87
  --prompt "<transition description>" \
85
88
  --first-frame ./start.png \
86
89
  --last-frame ./end.png \
@@ -91,7 +94,7 @@ python3 <SkillDir>/scripts/gen_video.py \
91
94
  ### Veo 3.1 high-resolution
92
95
 
93
96
  ```bash
94
- python3 <SkillDir>/scripts/gen_video.py \
97
+ ab-skill gen-video \
95
98
  --model veo \
96
99
  --prompt "<video description>" \
97
100
  --duration 8 \
@@ -102,7 +105,7 @@ python3 <SkillDir>/scripts/gen_video.py \
102
105
  ### Veo 3.1 Fast for rapid iteration
103
106
 
104
107
  ```bash
105
- python3 <SkillDir>/scripts/gen_video.py \
108
+ ab-skill gen-video \
106
109
  --model veo-fast \
107
110
  --prompt "<video description>" \
108
111
  --duration 6
@@ -110,8 +113,10 @@ python3 <SkillDir>/scripts/gen_video.py \
110
113
 
111
114
  ### Veo with reference images
112
115
 
116
+ Pass `--reference` multiple times (Veo only, up to 3).
117
+
113
118
  ```bash
114
- python3 <SkillDir>/scripts/gen_video.py \
119
+ ab-skill gen-video \
115
120
  --model veo \
116
121
  --prompt "<video description>" \
117
122
  --reference ./ref1.png \
@@ -119,19 +124,6 @@ python3 <SkillDir>/scripts/gen_video.py \
119
124
  --duration 8
120
125
  ```
121
126
 
122
- ### Download to disk
123
-
124
- ```bash
125
- python3 <SkillDir>/scripts/gen_video.py \
126
- --prompt "<video description>" \
127
- --download \
128
- --output "output_video.mp4"
129
- ```
130
-
131
- 5. **Surface results**: without `--download`, print the video URL; with `--download`, mention the local path.
132
-
133
- For the full flag list: `python3 <SkillDir>/scripts/gen_video.py --help`.
134
-
135
127
  ## Common CLI flags
136
128
 
137
129
  | Flag | Description | Default |
@@ -149,11 +141,8 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_video.py --help`.
149
141
  | `--negative-prompt` | Negative prompt (mainly Veo) | none |
150
142
  | `--seed` | Random seed | none |
151
143
  | `--person-generation` | Person policy: `allow_all` / `dont_allow` (Veo) | none |
152
- | `--download` | Download the video to disk | off |
153
- | `-o` / `--output` | Download path (only effective with `--download`) | `generated_video.mp4` |
154
- | `--poll-interval` | Polling interval (seconds) | `10` |
155
- | `--max-wait` | Max wait time (seconds) | `300` |
156
- | `--private-token` | Override token | see above |
144
+ | `--api-base-url` | Override API root | see above |
145
+ | `--priv-token` | Override token | see above |
157
146
 
158
147
  ## Prompt tips
159
148
 
@@ -166,5 +155,5 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_video.py --help`.
166
155
  - **401** / **token missing** (non-OpenClaw): set `PRIV_TOKEN`.
167
156
  - **Business `code != 0`**: read `msg` on stderr.
168
157
  - **429**: rate-limited; retry later.
169
- - **Generation timeout**: increase `--max-wait` or retry later.
158
+ - **Generation timeout**: the handler caps polling at ~5 minutes; retry later if it times out.
170
159
  - **Network**: verify connectivity and `MM_API_BASE_URL`.
@@ -2,10 +2,11 @@
2
2
  "name": "gen-video",
3
3
  "toolName": "gen_video",
4
4
  "tier": "atomic",
5
+ "category": "asset",
5
6
  "title": "AI Video Generation",
6
7
  "description": "AI video generation: produce a short video clip from a text prompt. Supports Seedance and Veo models, plus first/last frame and reference images.",
7
8
  "envVars": ["PRIV_TOKEN", "MM_API_BASE_URL", "AGENT_NAME", "MM_VIDEO_MODEL"],
8
- "scriptPath": "scripts/gen_video.py",
9
+ "entry": { "type": "http", "handler": "gen-video" },
9
10
  "parameters": {
10
11
  "type": "object",
11
12
  "properties": {
@@ -17,7 +18,8 @@
17
18
  "first_frame": { "type": "string", "description": "First-frame image path or URL" },
18
19
  "last_frame": { "type": "string", "description": "Last-frame image path or URL" },
19
20
  "reference": { "type": "string", "description": "Reference image (Veo only)" },
20
- "generate_audio": { "type": "boolean", "description": "Generate native audio" }
21
+ "generate_audio": { "type": "boolean", "description": "Generate native audio" },
22
+ "json_output": { "type": "boolean", "description": "Emit a JSON result ({ url }) instead of human-readable output" }
21
23
  },
22
24
  "required": ["prompt"]
23
25
  }
@@ -2,6 +2,6 @@
2
2
  "skillName": "gen-video",
3
3
  "repoName": "agent-skill-media-maker",
4
4
  "skillId": "339",
5
- "version": "V5",
5
+ "version": "V7",
6
6
  "skillDescription": "AI 生视频技能,根据文字描述生成素材视频(调用 ab-api /model/genVideo,支持 Seedance 与 Veo)。\n\n当用户提到以下任何需求时,立即使用本 skill:\n- AI 生视频、文生视频、文字生成视频、生成一段视频、AI 制作视频\n- 使用 doubao / 豆包 / seedance、Veo、Google 等生成视频\n- 用户提供视频提示词并希望生成视频\n- 图生视频、首帧生成视频、参考图生成视频\n\n即使用户没有明确说「使用 AI」,只要他们想要根据描述生成视频,也要使用本 skill。"
7
7
  }
@@ -29,7 +29,7 @@ There is no skill-local env file — the executing process inherits the system e
29
29
  | Env var | Description | Default |
30
30
  |---------|-------------|---------|
31
31
  | `PRIV_TOKEN` | Tianyan token; `--priv-token` overrides | none |
32
- | `MM_API_BASE_URL` | API root | see `gen_voice.py` default |
32
+ | `MM_API_BASE_URL` | API root; `--api-base-url` overrides | `http://localhost:2999/api` |
33
33
  | `AGENT_NAME` | Optional `x-invoke-agent` header | none |
34
34
 
35
35
  ## Operations
@@ -2,6 +2,7 @@
2
2
  "name": "gen-voice",
3
3
  "toolName": "gen_voice",
4
4
  "tier": "atomic",
5
+ "category": "asset",
5
6
  "title": "Text-to-Speech (Minimax)",
6
7
  "description": "Text-to-speech (TTS): synthesize narration audio from text via the Minimax TTS model. Returns the persisted audio URL — no download needed.",
7
8
  "envVars": ["PRIV_TOKEN", "MM_API_BASE_URL", "AGENT_NAME"],
@@ -2,6 +2,6 @@
2
2
  "skillName": "gen-voice",
3
3
  "repoName": "agent-skill-media-maker",
4
4
  "skillId": "338",
5
- "version": "V5",
5
+ "version": "V6",
6
6
  "skillDescription": "语音合成(TTS)技能,将文字转为语音音频(调用 ab-api /tool/minimaxT2aV2,基于 Minimax TTS)。\n\n当用户提到以下任何需求时,立即使用本 skill:\n- AI 配音、语音合成、文字转语音、TTS、文本转音频、生成语音\n- 使用 minimax 语音合成\n- 用户想要将一段文字朗读出来、生成音频\n\n即使用户没有明确说「使用 AI」,只要他们想要将文字转为语音,也要使用本 skill。"
7
7
  }
@@ -79,7 +79,7 @@ python3 <SkillDir>/scripts/prepare_video_assets.py \
79
79
  --template-id html-slide
80
80
  ```
81
81
 
82
- `--template-id` automatically calls template-bind internally; or pass `--binding my-video.binding.json` if you have a pre-generated binding.
82
+ `--template-id` automatically calls template-registry internally; or pass `--binding my-video.binding.json` if you have a pre-generated binding.
83
83
 
84
84
  ## Image-URL handling (agent rules)
85
85
 
@@ -189,4 +189,4 @@ The Asset Resolver handles each `AssetRef` in this order:
189
189
  ## See also
190
190
 
191
191
  - **`render_video`** — the Phase 3 skill that consumes this skill's `job_id` and produces the final video.
192
- - **`template-bind`** — Lists available templates. Called internally by this skill when `--template-id` is provided.
192
+ - **`template-registry`** — Lists available templates. Called internally by this skill when `--template-id` is provided.
@@ -2,6 +2,7 @@
2
2
  "name": "prepare-video-assets",
3
3
  "toolName": "prepare_video_assets",
4
4
  "tier": "orchestration",
5
+ "category": "authoring",
5
6
  "title": "Video Asset Preparation",
6
7
  "description": "Resolves and generates every asset (image / audio / video) referenced by a Video DSL, persists a RenderPlan to the database, and returns a job_id for the subsequent render_video call. This is Phase 1 of the two-phase video pipeline; Phase 3 (Remotion render) lives in render_video.",
7
8
  "envVars": ["PRIV_TOKEN", "MM_API_BASE_URL", "MM_BACKEND_API_URL", "AGENT_NAME", "REMOTION_RENDER_API_URL", "REMOTION_RENDER_MODE", "REMOTION_OUTPUT_DIR", "ASSET_CACHE_DIR"],
@@ -11,7 +12,7 @@
11
12
  "properties": {
12
13
  "dsl_json": { "type": "string", "description": "DSL JSON as an inline string (preferred — no disk write needed; required for multi-user concurrent flows). Pass the full DSL JSON, or — when a gen_script skeleton is cached in the session — a minimal JSON with only scenes[].audio.narration.text overrides (the agent layer merges narration onto the cached skeleton)." },
13
14
  "dsl": { "type": "string", "description": "DSL file path (legacy fallback; prefer dsl_json inline)." },
14
- "template_id": { "type": "string", "description": "Template id. When provided, the script invokes template-bind internally; no separate binding step is needed." },
15
+ "template_id": { "type": "string", "description": "Template id. When provided, the script invokes template-registry internally; no separate binding step is needed." },
15
16
  "binding_json": { "type": "string", "description": "TemplateBinding JSON as an inline string (alternative to template_id; no file needed)." },
16
17
  "binding": { "type": "string", "description": "TemplateBinding file path (optional; auto-generated when template_id is provided)." },
17
18
  "save_job": { "type": "boolean", "description": "Persist the RenderPlan to the database (default true). On success the stdout contains '📦 render job jobId: N'. Auto-degrades to false when PRIV_TOKEN is missing, falling back to file mode. Pass false to opt out explicitly." },
@@ -38,17 +38,17 @@ from datetime import datetime, timezone
38
38
  from typing import Optional
39
39
 
40
40
  # ── Cross-skill dependency ────────────────────────────────────────────────
41
- # Reach into `skills/template-bind/` — that directory is the de-facto home
41
+ # Reach into `skills/template-registry/` — that directory is the de-facto home
42
42
  # for shared Python code in ab-skill (timeline-compilation, registry loader,
43
- # render-job HTTP client, etc.). Naming it `_SHARED_LIB_DIR` rather than
44
- # `_TEMPLATE_BIND_DIR` reflects its actual role: it hosts much more than
45
- # template-binding now (see AGENTS.md "skills/template-bind/scripts/" note).
43
+ # render-job HTTP client, etc.). Naming it `_SHARED_LIB_DIR` reflects its
44
+ # actual role: it hosts much more than template lookup (see AGENTS.md
45
+ # "skills/template-registry/scripts/" note).
46
46
  #
47
47
  # If signatures of the functions below change, also update:
48
- # - skills/template-bind/video_dsl/runtime/timeline_compiler.py (the source)
48
+ # - skills/template-registry/video_dsl/runtime/timeline_compiler.py (the source)
49
49
  # - any other caller discoverable via `grep -r "split_subtitle\|segment_narration"`
50
50
  # ───────────────────────────────────────────────────────────────────────────
51
- _SHARED_LIB_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "template-bind")
51
+ _SHARED_LIB_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "template-registry")
52
52
  # Single sys.path setup for both cross-skill import surfaces of the shared lib:
53
53
  # - <shared> for `video_dsl.runtime.*`
54
54
  # - <shared>/scripts for `registry_loader`, `match_template`,
@@ -1779,7 +1779,7 @@ def auto_bind_template(dsl: dict, template_id: str) -> dict:
1779
1779
  """Auto-generate TemplateBinding from DSL + template-id by importing
1780
1780
  match_template.py's binding logic. Eliminates the need for a separate
1781
1781
  match_template.py invocation step."""
1782
- # template-bind/scripts is on sys.path via the module-top setup.
1782
+ # template-registry/scripts is on sys.path via the module-top setup.
1783
1783
  try:
1784
1784
  import match_template
1785
1785
  except ImportError as e:
@@ -1885,7 +1885,7 @@ Examples:
1885
1885
  if not private_token:
1886
1886
  LogPrint("❌ --job-id mode requires PRIV_TOKEN or --priv-token", file=sys.stderr)
1887
1887
  sys.exit(1)
1888
- # render_job_client lives in skills/template-bind/scripts/ (the shared
1888
+ # render_job_client lives in skills/template-registry/scripts/ (the shared
1889
1889
  # location for cross-skill helpers); it is already on sys.path via the
1890
1890
  # module-top setup.
1891
1891
  from render_job_client import get_plan as rjc_get_plan
@@ -2,6 +2,7 @@
2
2
  "name": "render-video",
3
3
  "toolName": "render_video",
4
4
  "tier": "orchestration",
5
+ "category": "authoring",
5
6
  "title": "Remotion Video Renderer",
6
7
  "description": "Loads a persisted RenderPlan by job_id and drives the Remotion engine to produce the final video. Assets must already be generated via prepare_video_assets — this skill never resolves or regenerates assets.",
7
8
  "envVars": ["PRIV_TOKEN", "MM_API_BASE_URL", "MM_BACKEND_API_URL", "AGENT_NAME", "REMOTION_RENDER_API_URL", "REMOTION_RENDER_MODE", "REMOTION_OUTPUT_DIR", "ASSET_CACHE_DIR"],
@@ -1,4 +1,4 @@
1
- # template-bind
1
+ # template-registry
2
2
 
3
3
  CLI 暴露面是「列出可用模板」(`--list-templates`)。把 Video DSL 场景绑到具体模板 / 生成 TemplateBinding 的 Python 逻辑由本 skill 提供为**库**(`scripts/match_template.py`),被 `render-video` / `prepare-video-assets` 通过 `sys.path` 内联 import,**没有独立 CLI**。
4
4
 
@@ -20,7 +20,7 @@ ab-api 响应包装格式 `{code, msg, data}` 由 `registry_loader._fetch_http`
20
20
 
21
21
  ## 新增模板工作流
22
22
 
23
- 新增模板**不需要改 ab-skill / template-bind 代码**:
23
+ 新增模板**不需要改 ab-skill / template-registry 代码**:
24
24
 
25
25
  1. 在 template-library 仓库定义新模板(`template.json` + 组件代码)。
26
26
  2. template-library CI 校验 schema + 契约。
@@ -50,13 +50,13 @@ python3 <SkillDir>/scripts/check_contracts.py
50
50
  | 模块 | 谁在用 | 作用 |
51
51
  |---|---|---|
52
52
  | `template_paths.py` | registry_loader / template_binder / gen-script / check_contracts | 统一计算 monorepo / template-library 路径,代替 4 个 caller 各自数 `..` |
53
- | `registry_loader.py` | template-bind handler / match_template / render-video / gen-script / dsl_validator | 加载 registry(HTTP + cache + file) |
53
+ | `registry_loader.py` | template-registry / match_template / render-video / gen-script / dsl_validator | 加载 registry(HTTP + cache + file) |
54
54
  | `match_template.py` | render-video(`auto_bind_template`) | DSL → TemplateBinding 算法 |
55
55
  | `render_job_client.py` | render-video / export-jianying | ab-api renderJob HTTP 客户端 |
56
56
  | `check_contracts.py` | 维护脚本 | template-library ↔ remotion-renderer 契约校验 |
57
57
  | `sync_registry.py` | 维护脚本 | 把 registry 摘要落盘供 LLM prompt 使用 |
58
58
 
59
- sibling skill 通过 `sys.path.insert(0, "<…>/template-bind/scripts")` 然后直接 `import` 模块名,模式见 `render_video.py` 顶部的"Single sys.path setup"段。
59
+ sibling skill 通过 `sys.path.insert(0, "<…>/template-registry/scripts")` 然后直接 `import` 模块名,模式见 `render_video.py` 顶部的"Single sys.path setup"段。
60
60
 
61
61
  ## 详细使用说明
62
62
 
@@ -1,17 +1,14 @@
1
1
  ---
2
- name: template-bind
2
+ name: template-registry
3
3
  description: |
4
- Video-template registry and binding skill. Stores every video-template definition and produces a TemplateBinding for a given template id.
4
+ Video-template registry skill. Stores every video-template definition and lists the available templates (templateId / name / aspect ratio / style tags).
5
5
 
6
6
  Use this skill as soon as the user mentions any of these intents:
7
7
  - View available templates / list every template
8
- - Bind a template to a DSL (a template-id must be supplied)
9
8
 
10
- Also use this skill whenever the agent has a Video DSL and needs to produce a TemplateBinding.
9
+ Note: DSL→TemplateBinding is no longer a separate exposed step once prepare_video_assets receives a template_id it builds the binding internally.
11
10
  triggers:
12
11
  - View available templates / list every template
13
- - Bind a template to a DSL (a template-id must be supplied)
14
- - Agent has a Video DSL and needs a TemplateBinding
15
12
  ---
16
13
 
17
14
  # Video Template Registry & Binding Skill
@@ -28,7 +25,7 @@ Stores every video-template definition, loads a template by **template-id**, and
28
25
 
29
26
  Template metadata lives in the standalone **template-library** monorepo and ships via the `@ab-templates/metadata` package.
30
27
 
31
- template-bind reads `template-library/packages/metadata/registry.json` to load every template definition (with the full slotMapping, compositions, etc.).
28
+ template-registry reads `template-library/packages/metadata/registry.json` to load every template definition (with the full slotMapping, compositions, etc.).
32
29
 
33
30
  ```
34
31
  template-library/packages/
@@ -76,11 +73,11 @@ Resolution order (see `scripts/registry_loader.py` for the canonical implementat
76
73
 
77
74
  ## Steps
78
75
 
79
- > This skill is now a built-in handler of the ab-skill CLI (`entry.type: builtin`). The agent tool name `template_bind` is still the only entry; locally reproduce via `ab-skill template-bind --list-templates`.
76
+ > This skill is a Python skill of the ab-skill CLI (`entry.type: python` → `scripts/list_templates.py`). The agent tool name `template_registry` is the only entry; locally reproduce via `ab-skill template-registry --list-templates`. The list command delegates to `scripts/registry_loader.py` — the same loader (with caching + stable/beta gating) that `render-video` and `gen-script` import in-process, so there is a single registry-reading implementation.
80
77
  >
81
- > The Python binding logic that maps DSL → TemplateBinding lives in `scripts/match_template.py` but is **no longer exposed as a CLI** — it is only consumed as a Python library by `render-video`'s `render_video.py` via `import match_template`. The `template-bind` skill itself no longer has a Python entry script.
78
+ > The Python binding logic that maps DSL → TemplateBinding lives in `scripts/match_template.py` but is **not exposed as a CLI** — it is only consumed as a Python library by `render-video`'s `render_video.py` via `import match_template`.
82
79
 
83
- 1. **List available templates**: run `ab-skill template-bind --list-templates` to view the templates in the registry along with their supported aspect ratios / style tags, and decide which `templateId` to pick.
80
+ 1. **List available templates**: run `ab-skill template-registry --list-templates` to view the templates in the registry along with their supported aspect ratios / style tags, and decide which `templateId` to pick.
84
81
  2. **Write the DSL**: when generating the Video DSL, put the chosen `templateId` into `meta.templateId` (the canonical location). Use `meta.templateVariant` / `renderHints.templateVariant` to explicitly select a variant. The legacy `renderHints.templatePreference[0]` is still tolerated by `match_template.py` and `dsl_validator._pick_template_id` during transition, but new authors should write `meta.templateId`.
85
82
  3. **Produce the TemplateBinding**: there is no standalone CLI for DSL → TemplateBinding; `prepare_video_assets` calls `match_template.build_binding(template, dsl)` inline during the asset-resolution pipeline and embeds the binding into the RenderPlan it hands to the renderer — no separate `*.binding.json` file is written.
86
83
 
@@ -89,7 +86,7 @@ Resolution order (see `scripts/registry_loader.py` for the canonical implementat
89
86
  ### List available templates
90
87
 
91
88
  ```bash
92
- ab-skill template-bind --list-templates
89
+ ab-skill template-registry --list-templates
93
90
  ```
94
91
 
95
92
  ### Sync the registry cache (optional, used for offline / LLM prompt)
@@ -123,7 +120,12 @@ print(json.dumps(binding, ensure_ascii=False, indent=2))
123
120
 
124
121
  | Flag | Description | Default |
125
122
  |------|-------------|---------|
126
- | `--list-templates` | List every available template and exit (currently the only CLI verb). | — |
123
+ | `--list-templates` | List every available template (currently the only CLI verb). | — |
124
+ | `--filter-tag` | Keep only templates whose `styleTags` match this substring (case-insensitive). | none |
125
+ | `--filter-aspect` | Keep only templates declaring this aspect ratio (e.g. `9:16`). | none |
126
+ | `--filter-language` | Keep only templates whose `contentLanguage` includes this code (`zh`/`en`); language-agnostic templates always show. | none |
127
+ | `--include-beta` | Also show `status: beta` templates (same effect as `ENABLE_BETA_TEMPLATES=1`). | off |
128
+ | `--json-output` | Emit `{ "templates": [...] }` instead of the table. | off |
127
129
 
128
130
  ## Props extraction rules
129
131