@remixmate/cli 0.1.1 → 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.
- package/dist/manifest.json +13 -2
- package/dist/skill-schema.d.ts +18 -0
- package/dist/skill-schema.js +4 -0
- package/package.json +1 -1
- package/skills/export-jianying/skill.json +1 -0
- package/skills/gen-digital-human/skill.json +1 -0
- package/skills/gen-image/skill.json +1 -0
- package/skills/gen-script/scripts/gen_script.py +39 -0
- package/skills/gen-script/skill.json +3 -1
- package/skills/gen-video/skill.json +1 -0
- package/skills/gen-voice/skill.json +1 -0
- package/skills/prepare-video-assets/skill.json +1 -0
- package/skills/render-video/skill.json +1 -0
- package/skills/template-registry/scripts/list_templates.py +87 -2
- package/skills/template-registry/skill.json +3 -1
- package/skills/video-parser/skill.json +1 -0
- package/skills/web-capture/skill.json +1 -0
package/dist/manifest.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"generatedAt": "2026-06-08T08:37:23.147Z",
|
|
5
5
|
"skills": [
|
|
6
6
|
{
|
|
7
7
|
"id": "export-jianying",
|
|
8
8
|
"tier": "orchestration",
|
|
9
|
+
"category": "consuming",
|
|
9
10
|
"title": "Jianying (CapCut) Draft Export",
|
|
10
11
|
"summary": "Jianying (CapCut) draft export: package asset URLs into a draft ZIP that Jianying can import. Supports automatic conversion from a RenderPlan.",
|
|
11
12
|
"triggers": [
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
{
|
|
29
30
|
"id": "gen-digital-human",
|
|
30
31
|
"tier": "atomic",
|
|
32
|
+
"category": "asset",
|
|
31
33
|
"title": "Digital-Human Talking-Head",
|
|
32
34
|
"summary": "Digital-human video: list available avatars; produce a talking-head video from text via TTS, or drive an avatar from an existing audio URL.",
|
|
33
35
|
"triggers": [
|
|
@@ -50,6 +52,7 @@
|
|
|
50
52
|
{
|
|
51
53
|
"id": "gen-image",
|
|
52
54
|
"tier": "atomic",
|
|
55
|
+
"category": "asset",
|
|
53
56
|
"title": "AI Image Generation",
|
|
54
57
|
"summary": "AI image generation: produce an image from a text prompt. Supports Seedream and Gemini models, plus image-to-image with reference images.",
|
|
55
58
|
"triggers": [
|
|
@@ -73,6 +76,7 @@
|
|
|
73
76
|
{
|
|
74
77
|
"id": "gen-script",
|
|
75
78
|
"tier": "orchestration",
|
|
79
|
+
"category": "authoring",
|
|
76
80
|
"title": "Video Script Generation",
|
|
77
81
|
"summary": "Video script generation: turn a topic into a structured Video DSL (JSON) that describes the full video — scene structure, asset requirements, and narrative flow.",
|
|
78
82
|
"triggers": [
|
|
@@ -95,6 +99,7 @@
|
|
|
95
99
|
{
|
|
96
100
|
"id": "gen-video",
|
|
97
101
|
"tier": "atomic",
|
|
102
|
+
"category": "asset",
|
|
98
103
|
"title": "AI Video Generation",
|
|
99
104
|
"summary": "AI video generation: produce a short video clip from a text prompt. Supports Seedance and Veo models, plus first/last frame and reference images.",
|
|
100
105
|
"triggers": [
|
|
@@ -117,6 +122,7 @@
|
|
|
117
122
|
{
|
|
118
123
|
"id": "gen-voice",
|
|
119
124
|
"tier": "atomic",
|
|
125
|
+
"category": "asset",
|
|
120
126
|
"title": "Text-to-Speech (Minimax)",
|
|
121
127
|
"summary": "Text-to-speech (TTS): synthesize narration audio from text via the Minimax TTS model. Returns the persisted audio URL — no download needed.",
|
|
122
128
|
"triggers": [
|
|
@@ -138,6 +144,7 @@
|
|
|
138
144
|
{
|
|
139
145
|
"id": "prepare-video-assets",
|
|
140
146
|
"tier": "orchestration",
|
|
147
|
+
"category": "authoring",
|
|
141
148
|
"title": "Video Asset Preparation",
|
|
142
149
|
"summary": "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.",
|
|
143
150
|
"triggers": [
|
|
@@ -165,6 +172,7 @@
|
|
|
165
172
|
{
|
|
166
173
|
"id": "render-video",
|
|
167
174
|
"tier": "orchestration",
|
|
175
|
+
"category": "authoring",
|
|
168
176
|
"title": "Remotion Video Renderer",
|
|
169
177
|
"summary": "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.",
|
|
170
178
|
"triggers": [
|
|
@@ -192,6 +200,7 @@
|
|
|
192
200
|
{
|
|
193
201
|
"id": "template-registry",
|
|
194
202
|
"tier": "orchestration",
|
|
203
|
+
"category": "authoring",
|
|
195
204
|
"title": "Video Template Registry",
|
|
196
205
|
"summary": "List all available video templates (templateId / name / aspect ratio / style tags). Template-to-DSL binding is no longer exposed as a separate step — once prepare_video_assets receives a template_id it runs the full DSL→RenderPlan pipeline internally.",
|
|
197
206
|
"triggers": [
|
|
@@ -212,6 +221,7 @@
|
|
|
212
221
|
{
|
|
213
222
|
"id": "video-parser",
|
|
214
223
|
"tier": "tool",
|
|
224
|
+
"category": "consuming",
|
|
215
225
|
"title": "Video Deconstruction",
|
|
216
226
|
"summary": "Video deconstruction: split a video into reusable assets (audio extraction, ASR transcript, keyframe extraction, scene segmentation).",
|
|
217
227
|
"triggers": [
|
|
@@ -233,6 +243,7 @@
|
|
|
233
243
|
{
|
|
234
244
|
"id": "web-capture",
|
|
235
245
|
"tier": "tool",
|
|
246
|
+
"category": "consuming",
|
|
236
247
|
"title": "Web Page Capture",
|
|
237
248
|
"summary": "Drive a headless browser (Playwright Python) to capture any URL to local files: full-page / element / region screenshots, fixed-duration / condition-triggered / auto-scroll recordings, and storyboard videos (highlight / focus / zoom / scroll / virtual-cursor click / caption / title-card / arrow / numbered sequence / redact / code-line highlight). Two entry scripts: scripts/screenshot.py (stills) and scripts/record.py (webm video, storyboards, templates).",
|
|
238
249
|
"triggers": [
|
package/dist/skill-schema.d.ts
CHANGED
|
@@ -21,12 +21,30 @@ export type SkillEntry = {
|
|
|
21
21
|
type: 'builtin';
|
|
22
22
|
handler: string;
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Skill 类别 — 区分"创作期 / 消费期 / 元数据型" skill。
|
|
26
|
+
*
|
|
27
|
+
* - "authoring": 创建 / 编辑模板期间使用,例如 template-registry / gen-script /
|
|
28
|
+
* render-video(用于 try_render) / prepare-video-assets。
|
|
29
|
+
* - "consuming": 消费已有模板生成媒体,例如 export-jianying / video-parser /
|
|
30
|
+
* web-capture(与"创建模板"无关,是消费侧场景)。
|
|
31
|
+
* - "asset": 生成单一类型素材的原子 skill:gen-image / gen-voice /
|
|
32
|
+
* gen-video / gen-digital-human。authoring 也会用,但通过 stub
|
|
33
|
+
* 方式占位;consuming 场景下是真调用。
|
|
34
|
+
* - "meta": 元 skill(如未来加入 doc-only 的 template-creator)。
|
|
35
|
+
*
|
|
36
|
+
* 下游消费方(如 ab-template-studio)按 category 自动挑选白名单,避免每加一个
|
|
37
|
+
* skill 就要改两侧 hardcode。
|
|
38
|
+
*/
|
|
39
|
+
export type SkillCategory = 'authoring' | 'consuming' | 'asset' | 'meta';
|
|
40
|
+
export declare const CATEGORY_VALUES: readonly ["authoring", "consuming", "asset", "meta"];
|
|
24
41
|
export interface RawSkillJson {
|
|
25
42
|
name: string;
|
|
26
43
|
toolName: string;
|
|
27
44
|
description: string;
|
|
28
45
|
title?: string;
|
|
29
46
|
tier?: string;
|
|
47
|
+
category?: SkillCategory;
|
|
30
48
|
parameters?: Record<string, unknown>;
|
|
31
49
|
scriptPath?: string;
|
|
32
50
|
entry?: SkillEntry;
|
package/dist/skill-schema.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* human-readable problems (empty = OK). The runtime loader skips + warns;
|
|
12
12
|
* the build treats them as fatal.
|
|
13
13
|
*/
|
|
14
|
+
export const CATEGORY_VALUES = ['authoring', 'consuming', 'asset', 'meta'];
|
|
14
15
|
export const TIER_VALUES = ['atomic', 'orchestration', 'tool'];
|
|
15
16
|
export const REQUIRED_SKILL_JSON_FIELDS = ['name', 'tier', 'title', 'description'];
|
|
16
17
|
/**
|
|
@@ -39,6 +40,9 @@ export function validateSkillJson(raw, skillId) {
|
|
|
39
40
|
if (raw.tier != null && !TIER_VALUES.includes(raw.tier)) {
|
|
40
41
|
errors.push(`skill.json.tier must be one of ${TIER_VALUES.join(' | ')}, got '${raw.tier}'`);
|
|
41
42
|
}
|
|
43
|
+
if (raw.category != null && !CATEGORY_VALUES.includes(raw.category)) {
|
|
44
|
+
errors.push(`skill.json.category must be one of ${CATEGORY_VALUES.join(' | ')}, got '${raw.category}'`);
|
|
45
|
+
}
|
|
42
46
|
if (raw.name && raw.name !== skillId) {
|
|
43
47
|
errors.push(`skill.json.name='${raw.name}' does not match directory name '${skillId}'`);
|
|
44
48
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remixmate/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "AI media generation skills for Claude Code / Codex — 11 skills covering image, video, voice, digital human, web capture, script, template registry, rendering, Jianying export, and video deconstruction.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"name": "export-jianying",
|
|
3
3
|
"toolName": "export_jianying",
|
|
4
4
|
"tier": "orchestration",
|
|
5
|
+
"category": "consuming",
|
|
5
6
|
"title": "Jianying (CapCut) Draft Export",
|
|
6
7
|
"description": "Jianying (CapCut) draft export: package asset URLs into a draft ZIP that Jianying can import. Supports automatic conversion from a RenderPlan.",
|
|
7
8
|
"envVars": ["PRIV_TOKEN", "MM_API_BASE_URL", "AGENT_NAME"],
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"name": "gen-digital-human",
|
|
3
3
|
"toolName": "gen_digital_human",
|
|
4
4
|
"tier": "atomic",
|
|
5
|
+
"category": "asset",
|
|
5
6
|
"title": "Digital-Human Talking-Head",
|
|
6
7
|
"description": "Digital-human video: list available avatars; produce a talking-head video from text via TTS, or drive an avatar from an existing audio URL.",
|
|
7
8
|
"envVars": ["PRIV_TOKEN", "MM_API_BASE_URL", "AGENT_NAME"],
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"name": "gen-image",
|
|
3
3
|
"toolName": "gen_image",
|
|
4
4
|
"tier": "atomic",
|
|
5
|
+
"category": "asset",
|
|
5
6
|
"title": "AI Image Generation",
|
|
6
7
|
"description": "AI image generation: produce an image from a text prompt. Supports Seedream and Gemini models, plus image-to-image with reference images.",
|
|
7
8
|
"envVars": ["PRIV_TOKEN", "MM_API_BASE_URL", "AGENT_NAME", "MM_IMAGE_MODEL"],
|
|
@@ -1054,6 +1054,11 @@ Examples:
|
|
|
1054
1054
|
default=None,
|
|
1055
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).",
|
|
1056
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
|
+
)
|
|
1057
1062
|
parser.add_argument(
|
|
1058
1063
|
"--stub-image-url",
|
|
1059
1064
|
default=None,
|
|
@@ -1157,6 +1162,22 @@ Examples:
|
|
|
1157
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)
|
|
1158
1163
|
stub_video_url = env_v
|
|
1159
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
|
+
|
|
1160
1181
|
dsl = build_dsl(
|
|
1161
1182
|
topic=args.topic,
|
|
1162
1183
|
platform=args.platform,
|
|
@@ -1177,6 +1198,24 @@ Examples:
|
|
|
1177
1198
|
caption_lines=args.caption_lines,
|
|
1178
1199
|
)
|
|
1179
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
|
+
|
|
1180
1219
|
errors = validate_dsl(dsl)
|
|
1181
1220
|
if errors:
|
|
1182
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
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
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"],
|
|
@@ -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,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"],
|
|
@@ -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"],
|
|
@@ -15,12 +15,18 @@ in-process by ``render-video``; it is intentionally NOT exposed as a CLI verb.
|
|
|
15
15
|
|
|
16
16
|
Flags:
|
|
17
17
|
--list-templates (accepted; listing is the only verb)
|
|
18
|
+
--list-examples list *.dsl.json / *.binding.json reference
|
|
19
|
+
examples grouped by templateId (consumed
|
|
20
|
+
by downstream agents that want to read a
|
|
21
|
+
template's reference shape before producing
|
|
22
|
+
new DSL)
|
|
18
23
|
--filter-tag <substr> keep templates whose styleTags match
|
|
19
24
|
--filter-aspect <ratio> keep templates supporting this aspect ratio
|
|
20
25
|
--filter-language <zh|en|...> keep templates tagged with this content lang
|
|
21
26
|
(templates with no contentLanguage are kept)
|
|
22
27
|
--include-beta also show beta templates (else stable-only)
|
|
23
|
-
--json-output emit {"templates": [...]}
|
|
28
|
+
--json-output emit {"templates": [...]} or {"examples": [...]}
|
|
29
|
+
instead of a table
|
|
24
30
|
"""
|
|
25
31
|
|
|
26
32
|
from __future__ import annotations
|
|
@@ -29,6 +35,7 @@ import argparse
|
|
|
29
35
|
import json
|
|
30
36
|
import os
|
|
31
37
|
import sys
|
|
38
|
+
from pathlib import Path
|
|
32
39
|
|
|
33
40
|
# When run as `python3 <skillDir>/scripts/list_templates.py`, this script's own
|
|
34
41
|
# directory is sys.path[0], so the sibling shared modules import directly.
|
|
@@ -61,17 +68,69 @@ def _status_of(tpl: dict) -> str:
|
|
|
61
68
|
return "stable"
|
|
62
69
|
|
|
63
70
|
|
|
71
|
+
# ----- Examples discovery (--list-examples) ---------------------------------
|
|
72
|
+
#
|
|
73
|
+
# Examples live under <SkillDir>/video_dsl/schema/examples/ as `*.dsl.json` and
|
|
74
|
+
# `*.binding.json` files. Naming convention (per gen-script SKILL.md) is
|
|
75
|
+
# `<templateId>.dsl.json` / `<templateId>.binding.json`, occasionally with
|
|
76
|
+
# variant suffixes (`<templateId>.<variant>.dsl.json`).
|
|
77
|
+
#
|
|
78
|
+
# We do not parse the JSON content here (downstream agents read the raw files
|
|
79
|
+
# they care about); we just enumerate paths so the agent doesn't have to guess
|
|
80
|
+
# the directory layout. When the directory does not exist (e.g. inside a slim
|
|
81
|
+
# package distribution), we return an empty list — non-fatal.
|
|
82
|
+
|
|
83
|
+
# Resolve the examples directory relative to this script.
|
|
84
|
+
# <skill>/scripts/list_templates.py → <skill>/video_dsl/schema/examples/
|
|
85
|
+
_EXAMPLES_DIR = Path(__file__).resolve().parent.parent / "video_dsl" / "schema" / "examples"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _collect_examples() -> list[dict]:
|
|
89
|
+
if not _EXAMPLES_DIR.is_dir():
|
|
90
|
+
return []
|
|
91
|
+
by_template: dict[str, dict] = {}
|
|
92
|
+
for entry in sorted(_EXAMPLES_DIR.iterdir()):
|
|
93
|
+
if not entry.is_file():
|
|
94
|
+
continue
|
|
95
|
+
name = entry.name
|
|
96
|
+
# Recognise *.dsl.json / *.binding.json
|
|
97
|
+
if name.endswith(".dsl.json"):
|
|
98
|
+
kind = "dsl"
|
|
99
|
+
base = name[: -len(".dsl.json")]
|
|
100
|
+
elif name.endswith(".binding.json"):
|
|
101
|
+
kind = "binding"
|
|
102
|
+
base = name[: -len(".binding.json")]
|
|
103
|
+
else:
|
|
104
|
+
continue
|
|
105
|
+
# Variant: 'foo.bar.dsl.json' → templateId='foo', variant='bar'
|
|
106
|
+
if "." in base:
|
|
107
|
+
template_id, variant = base.split(".", 1)
|
|
108
|
+
else:
|
|
109
|
+
template_id, variant = base, None
|
|
110
|
+
bucket = by_template.setdefault(template_id, {"templateId": template_id, "files": []})
|
|
111
|
+
bucket["files"].append({
|
|
112
|
+
"kind": kind,
|
|
113
|
+
"variant": variant,
|
|
114
|
+
"path": str(entry.relative_to(_EXAMPLES_DIR.parent.parent.parent)), # relative to skill dir
|
|
115
|
+
"absolutePath": str(entry),
|
|
116
|
+
"sizeBytes": entry.stat().st_size,
|
|
117
|
+
})
|
|
118
|
+
return list(by_template.values())
|
|
119
|
+
|
|
120
|
+
|
|
64
121
|
def main() -> None:
|
|
65
122
|
ap = argparse.ArgumentParser(
|
|
66
123
|
description="List available video templates from the registry.",
|
|
67
124
|
)
|
|
68
125
|
ap.add_argument("--list-templates", action="store_true",
|
|
69
126
|
help="List every available template (the only CLI verb).")
|
|
127
|
+
ap.add_argument("--list-examples", action="store_true",
|
|
128
|
+
help="List reference examples (*.dsl.json / *.binding.json) grouped by templateId.")
|
|
70
129
|
ap.add_argument("--filter-tag", help="Keep templates whose styleTags match this substring.")
|
|
71
130
|
ap.add_argument("--filter-aspect", help="Keep templates supporting this aspect ratio (e.g. 9:16).")
|
|
72
131
|
ap.add_argument("--filter-language", help="Keep templates tagged with this content language (zh|en|...).")
|
|
73
132
|
ap.add_argument("--include-beta", action="store_true", help="Also show beta templates (default: stable only).")
|
|
74
|
-
ap.add_argument("--json-output", action="store_true", help='Emit {"templates": [...]}
|
|
133
|
+
ap.add_argument("--json-output", action="store_true", help='Emit JSON ({"templates":[...]} or {"examples":[...]}) instead of a table.')
|
|
75
134
|
args = ap.parse_args()
|
|
76
135
|
|
|
77
136
|
# --include-beta flips registry_loader's documented status gate via env, so
|
|
@@ -79,6 +138,32 @@ def main() -> None:
|
|
|
79
138
|
if args.include_beta:
|
|
80
139
|
os.environ["ENABLE_BETA_TEMPLATES"] = "1"
|
|
81
140
|
|
|
141
|
+
# ----- examples mode -----------------------------------------------------
|
|
142
|
+
if args.list_examples:
|
|
143
|
+
examples = _collect_examples()
|
|
144
|
+
if args.json_output:
|
|
145
|
+
print(json.dumps({"examples": examples}, ensure_ascii=False))
|
|
146
|
+
return
|
|
147
|
+
if not examples:
|
|
148
|
+
print(
|
|
149
|
+
f"⚠️ No examples found under {_EXAMPLES_DIR}.\n"
|
|
150
|
+
" This package may have shipped without reference examples; "
|
|
151
|
+
"check the cli source repo or upgrade @remixmate/cli.",
|
|
152
|
+
)
|
|
153
|
+
return
|
|
154
|
+
print(f"\n{'Template ID':<28} Files")
|
|
155
|
+
print(f"{'-' * 28} {'-' * 60}")
|
|
156
|
+
for bucket in examples:
|
|
157
|
+
tid = str(bucket["templateId"])[:28].ljust(28)
|
|
158
|
+
files = bucket["files"]
|
|
159
|
+
for i, f in enumerate(files):
|
|
160
|
+
marker = tid if i == 0 else " " * 28
|
|
161
|
+
kind = f["kind"]
|
|
162
|
+
variant = f"@{f['variant']}" if f.get("variant") else ""
|
|
163
|
+
print(f"{marker} [{kind}{variant}] {f['path']} ({f['sizeBytes']}B)")
|
|
164
|
+
print(f"\n{sum(len(b['files']) for b in examples)} example file(s) across {len(examples)} template(s)")
|
|
165
|
+
return
|
|
166
|
+
|
|
82
167
|
try:
|
|
83
168
|
templates = load_visible_templates()
|
|
84
169
|
except RuntimeError as exc:
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"name": "template-registry",
|
|
3
3
|
"toolName": "template_registry",
|
|
4
4
|
"tier": "orchestration",
|
|
5
|
+
"category": "authoring",
|
|
5
6
|
"title": "Video Template Registry",
|
|
6
7
|
"description": "List all available video templates (templateId / name / aspect ratio / style tags). Template-to-DSL binding is no longer exposed as a separate step — once prepare_video_assets receives a template_id it runs the full DSL→RenderPlan pipeline internally.",
|
|
7
8
|
"envVars": ["PRIV_TOKEN", "VIDEO_TEMPLATE_REGISTRY", "VIDEO_TEMPLATE_REGISTRY_URL", "VIDEO_TEMPLATE_REGISTRY_HTTP_METHOD"],
|
|
@@ -10,11 +11,12 @@
|
|
|
10
11
|
"type": "object",
|
|
11
12
|
"properties": {
|
|
12
13
|
"list_templates": { "type": "boolean", "description": "List available templates (default behavior; also implied when other flags are passed)." },
|
|
14
|
+
"list_examples": { "type": "boolean", "description": "List the *.dsl.json / *.binding.json reference examples shipped under template-registry/video_dsl/schema/examples/, grouped by templateId. Useful for downstream agents (e.g. a creation agent) that want to read a template's reference shape before producing new DSL." },
|
|
13
15
|
"filter_tag": { "type": "string", "description": "Show only templates whose styleTags contain (or are contained in) this string. Case-insensitive. E.g. 'tech' / '科普' / 'walkthrough'." },
|
|
14
16
|
"filter_aspect": { "type": "string", "description": "Show only templates that declare this aspect ratio. E.g. '9:16' / '16:9' / '1:1'." },
|
|
15
17
|
"filter_language": { "type": "string", "description": "Show only templates whose contentLanguage includes this code ('zh' or 'en'). Templates with no declared language are always shown (treated as language-agnostic)." },
|
|
16
18
|
"include_beta": { "type": "boolean", "description": "Also list templates with status='beta'. Default off (only 'stable' shows). The ENABLE_BETA_TEMPLATES env var has the same effect process-wide." },
|
|
17
|
-
"json_output": { "type": "boolean", "description": "Emit a JSON result ({ templates: [...] }) instead of the human-readable table." }
|
|
19
|
+
"json_output": { "type": "boolean", "description": "Emit a JSON result ({ templates: [...] } or { examples: [...] }) instead of the human-readable table." }
|
|
18
20
|
},
|
|
19
21
|
"required": []
|
|
20
22
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"name": "video-parser",
|
|
3
3
|
"toolName": "video_parser",
|
|
4
4
|
"tier": "tool",
|
|
5
|
+
"category": "consuming",
|
|
5
6
|
"title": "Video Deconstruction",
|
|
6
7
|
"description": "Video deconstruction: split a video into reusable assets (audio extraction, ASR transcript, keyframe extraction, scene segmentation).",
|
|
7
8
|
"envVars": ["RENDER_API_URL", "PRIV_TOKEN", "CONVERSATION_ID"],
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"name": "web-capture",
|
|
3
3
|
"toolName": "web_capture",
|
|
4
4
|
"tier": "tool",
|
|
5
|
+
"category": "consuming",
|
|
5
6
|
"title": "Web Page Capture",
|
|
6
7
|
"description": "Drive a headless browser (Playwright Python) to capture any URL to local files: full-page / element / region screenshots, fixed-duration / condition-triggered / auto-scroll recordings, and storyboard videos (highlight / focus / zoom / scroll / virtual-cursor click / caption / title-card / arrow / numbered sequence / redact / code-line highlight). Two entry scripts: scripts/screenshot.py (stills) and scripts/record.py (webm video, storyboards, templates).",
|
|
7
8
|
"envVars": ["WEB_CAPTURE_BROWSER", "WEB_CAPTURE_OUTPUT_BASE", "WEB_CAPTURE_NO_SANDBOX", "WEB_CAPTURE_ALLOW_PRIVATE_HOSTS", "PLAYWRIGHT_BROWSERS_PATH"],
|