@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
package/dist/registry.js CHANGED
@@ -1,29 +1,21 @@
1
1
  /**
2
2
  * Skill registry — scan skills/ and load skill.json definitions.
3
3
  *
4
- * skill.json schema:
5
- * { name, toolName, description, parameters, entry?, scriptPath? }
6
- *
7
- * `entry` is the dispatcher hint. Missing entry falls back to the legacy
8
- * top-level scriptPath, treated as { type:'python', scriptPath } so older
9
- * skills keep working without a touch.
4
+ * Validation and entry-normalization live in `skill-schema.ts` (shared with
5
+ * the build-time manifest generator and smoke test). A record that fails
6
+ * validation is skipped with a warning rather than crashing the whole CLI.
10
7
  */
11
8
  import { readdirSync, readFileSync, existsSync, statSync } from 'node:fs';
12
9
  import path from 'node:path';
13
10
  import { fileURLToPath } from 'node:url';
11
+ import { normalizeEntry, validateSkillJson, } from './skill-schema.js';
14
12
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
13
  export const SKILLS_DIR = path.resolve(__dirname, '..', 'skills');
16
- function normalizeEntry(raw) {
17
- if (raw.entry)
18
- return raw.entry;
19
- if (raw.scriptPath)
20
- return { type: 'python', scriptPath: raw.scriptPath };
21
- return null;
22
- }
23
14
  function loadOne(skillDir) {
24
15
  const skillJsonPath = path.join(skillDir, 'skill.json');
25
16
  if (!existsSync(skillJsonPath))
26
17
  return null;
18
+ const skillId = path.basename(skillDir);
27
19
  let raw;
28
20
  try {
29
21
  raw = JSON.parse(readFileSync(skillJsonPath, 'utf-8'));
@@ -32,16 +24,18 @@ function loadOne(skillDir) {
32
24
  console.error(`[remixmate] failed to parse ${skillJsonPath}:`, err);
33
25
  return null;
34
26
  }
35
- const entry = normalizeEntry(raw);
36
- if (!entry) {
37
- console.warn(`[remixmate] skipping ${raw.name}: missing entry/scriptPath`);
27
+ const errors = validateSkillJson(raw, skillId);
28
+ if (errors.length > 0) {
29
+ console.warn(`[remixmate] skipping ${skillId}:\n${errors.map((e) => ` - ${e}`).join('\n')}`);
38
30
  return null;
39
31
  }
32
+ // validateSkillJson guarantees a resolvable entry.
33
+ const entry = normalizeEntry(raw);
40
34
  const def = {
41
35
  name: raw.name,
42
36
  toolName: raw.toolName,
43
37
  description: raw.description,
44
- parameters: raw.parameters,
38
+ parameters: raw.parameters ?? {},
45
39
  entry,
46
40
  skillDir,
47
41
  };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Single source of truth for skill.json shape + validation.
3
+ *
4
+ * Imported directly by `registry.ts` (runtime loader) and — via the compiled
5
+ * `dist/skill-schema.js` — by `scripts/build-manifest.mjs` and `scripts/smoke.mjs`.
6
+ * Previously each of those reimplemented `normalizeEntry` and its own subset of
7
+ * field checks, so "valid at build" ≠ "loadable at runtime". Centralizing here
8
+ * means one definition of a well-formed skill.
9
+ *
10
+ * Error policy is the caller's choice: `validateSkillJson` returns a list of
11
+ * human-readable problems (empty = OK). The runtime loader skips + warns;
12
+ * the build treats them as fatal.
13
+ */
14
+ export type SkillEntry = {
15
+ type: 'python';
16
+ scriptPath: string;
17
+ } | {
18
+ type: 'http';
19
+ handler: string;
20
+ } | {
21
+ type: 'builtin';
22
+ handler: string;
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"];
41
+ export interface RawSkillJson {
42
+ name: string;
43
+ toolName: string;
44
+ description: string;
45
+ title?: string;
46
+ tier?: string;
47
+ category?: SkillCategory;
48
+ parameters?: Record<string, unknown>;
49
+ scriptPath?: string;
50
+ entry?: SkillEntry;
51
+ envVars?: string[];
52
+ }
53
+ export declare const TIER_VALUES: readonly ["atomic", "orchestration", "tool"];
54
+ export declare const REQUIRED_SKILL_JSON_FIELDS: readonly ["name", "tier", "title", "description"];
55
+ /**
56
+ * Resolve the dispatcher entry. A missing `entry` falls back to the legacy
57
+ * top-level `scriptPath`, treated as `{ type: 'python', scriptPath }` so older
58
+ * skills keep working untouched. Returns null when neither is present.
59
+ */
60
+ export declare function normalizeEntry(raw: Pick<RawSkillJson, 'entry' | 'scriptPath'>): SkillEntry | null;
61
+ /**
62
+ * Validate a parsed skill.json against the directory it lives in. Returns an
63
+ * array of problem strings; an empty array means the record is well-formed.
64
+ */
65
+ export declare function validateSkillJson(raw: RawSkillJson, skillId: string): string[];
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Single source of truth for skill.json shape + validation.
3
+ *
4
+ * Imported directly by `registry.ts` (runtime loader) and — via the compiled
5
+ * `dist/skill-schema.js` — by `scripts/build-manifest.mjs` and `scripts/smoke.mjs`.
6
+ * Previously each of those reimplemented `normalizeEntry` and its own subset of
7
+ * field checks, so "valid at build" ≠ "loadable at runtime". Centralizing here
8
+ * means one definition of a well-formed skill.
9
+ *
10
+ * Error policy is the caller's choice: `validateSkillJson` returns a list of
11
+ * human-readable problems (empty = OK). The runtime loader skips + warns;
12
+ * the build treats them as fatal.
13
+ */
14
+ export const CATEGORY_VALUES = ['authoring', 'consuming', 'asset', 'meta'];
15
+ export const TIER_VALUES = ['atomic', 'orchestration', 'tool'];
16
+ export const REQUIRED_SKILL_JSON_FIELDS = ['name', 'tier', 'title', 'description'];
17
+ /**
18
+ * Resolve the dispatcher entry. A missing `entry` falls back to the legacy
19
+ * top-level `scriptPath`, treated as `{ type: 'python', scriptPath }` so older
20
+ * skills keep working untouched. Returns null when neither is present.
21
+ */
22
+ export function normalizeEntry(raw) {
23
+ if (raw.entry)
24
+ return raw.entry;
25
+ if (raw.scriptPath)
26
+ return { type: 'python', scriptPath: raw.scriptPath };
27
+ return null;
28
+ }
29
+ /**
30
+ * Validate a parsed skill.json against the directory it lives in. Returns an
31
+ * array of problem strings; an empty array means the record is well-formed.
32
+ */
33
+ export function validateSkillJson(raw, skillId) {
34
+ const errors = [];
35
+ for (const field of REQUIRED_SKILL_JSON_FIELDS) {
36
+ const value = raw[field];
37
+ if (value == null || value === '')
38
+ errors.push(`skill.json missing required field '${field}'`);
39
+ }
40
+ if (raw.tier != null && !TIER_VALUES.includes(raw.tier)) {
41
+ errors.push(`skill.json.tier must be one of ${TIER_VALUES.join(' | ')}, got '${raw.tier}'`);
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
+ }
46
+ if (raw.name && raw.name !== skillId) {
47
+ errors.push(`skill.json.name='${raw.name}' does not match directory name '${skillId}'`);
48
+ }
49
+ if (!normalizeEntry(raw)) {
50
+ errors.push("skill.json missing 'entry' (or legacy 'scriptPath')");
51
+ }
52
+ return errors;
53
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@remixmate/cli",
3
- "version": "0.1.0",
4
- "description": "AI media generation skills for Claude Code / Codex — 9 skills covering image, video, voice, digital human, script, template binding, rendering, Jianying export, and video deconstruction.",
3
+ "version": "0.1.2",
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",
7
7
  "types": "dist/index.d.ts",
@@ -15,13 +15,14 @@
15
15
  "LICENSE"
16
16
  ],
17
17
  "scripts": {
18
- "build": "tsc && node scripts/build-manifest.mjs",
18
+ "build": "node scripts/clean-dist.mjs && tsc && node scripts/build-manifest.mjs",
19
19
  "prepare": "npm run build",
20
20
  "list": "node dist/cli.js --list",
21
21
  "smoke": "node scripts/smoke.mjs",
22
+ "test:cli": "npm run build && node --test test/*.test.mjs",
22
23
  "test:validators": "PYTHONDONTWRITEBYTECODE=1 python3 scripts/test-validators.py",
23
24
  "test:template-pipeline": "PYTHONDONTWRITEBYTECODE=1 python3 scripts/test-template-pipeline.py",
24
- "test:contracts": "PYTHONDONTWRITEBYTECODE=1 python3 skills/template-bind/scripts/check_contracts.py",
25
+ "test:contracts": "PYTHONDONTWRITEBYTECODE=1 python3 skills/template-registry/scripts/check_contracts.py",
25
26
  "clean": "node scripts/clean.mjs"
26
27
  },
27
28
  "keywords": [
@@ -986,13 +986,13 @@ Scene fields:
986
986
  if not PRIVATE_TOKEN:
987
987
  print("❌ --from-job-id mode requires PRIV_TOKEN", file=sys.stderr)
988
988
  sys.exit(1)
989
- # render_job_client lives in skills/template-bind/scripts/ — the
989
+ # render_job_client lives in skills/template-registry/scripts/ — the
990
990
  # shared location for cross-skill Python helpers (matches the pattern
991
991
  # render-video uses for the same import).
992
- _template_bind_scripts = os.path.join(
993
- os.path.dirname(__file__), "..", "..", "template-bind", "scripts"
992
+ _template_registry_scripts = os.path.join(
993
+ os.path.dirname(__file__), "..", "..", "template-registry", "scripts"
994
994
  )
995
- sys.path.insert(0, _template_bind_scripts)
995
+ sys.path.insert(0, _template_registry_scripts)
996
996
  from render_job_client import get_plan as rjc_get_plan
997
997
  try:
998
998
  render_plan_str = rjc_get_plan(args.from_job_id, PRIVATE_TOKEN)
@@ -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"],
@@ -19,7 +19,9 @@ triggers:
19
19
 
20
20
  # Digital-Human Skill
21
21
 
22
- Wraps ab-api's digital-human endpoints (the same ones the web studio uses), authenticated with the **Tianyan privateToken**. Two providers: **Jimeng** (image-driven) and **HiFly** (video-driven).
22
+ Wraps ab-api's digital-human endpoints (the same ones the web studio uses), authenticated with the **Tianyan privateToken**. Two providers: **Jimeng** (image-driven) and **HiFly** (video-driven). Generation is async — the handler submits the task and polls `/digital-human/video/status` until completion.
23
+
24
+ > 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_digital_human`, same params as in `skill.json`); local repro goes through `ab-skill gen-digital-human ...`.
23
25
 
24
26
  ## Capabilities
25
27
 
@@ -34,54 +36,52 @@ Wraps ab-api's digital-human endpoints (the same ones the web studio uses), auth
34
36
 
35
37
  ## Auth & environment
36
38
 
37
- No skill-local env file — the executing process inherits the system environment. Examples below say `python`; on macOS you may need `python3`.
39
+ No skill-local env file — the executing process inherits the system environment.
38
40
 
39
41
  - **Enterprise OpenClaw**: auth is already injected, **no need** for `PRIV_TOKEN` / `--priv-token`.
40
- - **Other environments**: configure the token. Without a token, non-interactive runs fail; interactive ones may prompt.
42
+ - **Other environments**: configure the token. Without a token, non-interactive runs fail.
41
43
 
42
44
  | Env var | Description | Default |
43
45
  |---------|-------------|---------|
44
46
  | `PRIV_TOKEN` | Tianyan token; `--priv-token` overrides | none |
45
- | `MM_API_BASE_URL` | API root | see `gen_digital_human_video.py` default |
47
+ | `MM_API_BASE_URL` | API root; `--api-base-url` overrides | `http://localhost:2999/api` |
46
48
  | `AGENT_NAME` | Optional `x-invoke-agent` header | none |
47
49
 
48
50
  ## Operations
49
51
 
50
- **Script path**: read the system-injected `Base directory for this skill: <path>` as `<SkillDir>`. Always use `<SkillDir>/scripts/gen_digital_human_video.py`. Do not hardcode paths.
52
+ By default only the URL is printed; generation is async and the handler polls until done (typically 1–5 minutes), emitting `__progress__` lines. The resulting video URL is cloud-persisted — show it directly, no download needed.
51
53
 
52
54
  ### 1. List avatars
53
55
 
54
56
  ```bash
55
- python3 <SkillDir>/scripts/gen_digital_human_video.py --list-avatars
57
+ ab-skill gen-digital-human --list-avatars
56
58
  ```
57
59
 
58
60
  Optional filters:
59
61
 
60
62
  ```bash
61
63
  # Filter by source (jimeng = image-driven, hifly = video-driven)
62
- python3 <SkillDir>/scripts/gen_digital_human_video.py --list-avatars --source jimeng
63
- python3 <SkillDir>/scripts/gen_digital_human_video.py --list-avatars --source hifly
64
+ ab-skill gen-digital-human --list-avatars --source jimeng
65
+ ab-skill gen-digital-human --list-avatars --source hifly
64
66
 
65
67
  # Filter by gender
66
- python3 <SkillDir>/scripts/gen_digital_human_video.py --list-avatars --gender female
68
+ ab-skill gen-digital-human --list-avatars --gender female
67
69
 
68
70
  # Show your custom avatars
69
- python3 <SkillDir>/scripts/gen_digital_human_video.py --list-avatars --mine
71
+ ab-skill gen-digital-human --list-avatars --mine
70
72
 
71
73
  # Filter by name
72
- python3 <SkillDir>/scripts/gen_digital_human_video.py --list-avatars --name "alice"
74
+ ab-skill gen-digital-human --list-avatars --name "alice"
73
75
  ```
74
76
 
75
- > Custom avatars require `--mine`. When generating a video the script auto-falls back from the public list to `mine: true` if needed.
77
+ > Custom avatars require `--mine`. When generating a video the handler auto-falls back from the public list to `mine: true` if needed.
76
78
 
77
79
  ### 2. Generate a digital-human video
78
80
 
79
- By default only the URL is printed; pass `--download` (and optional `--output`) to save locally. Generation is async; the script polls until done (typically 1–5 minutes).
80
-
81
81
  #### TTS mode
82
82
 
83
83
  ```bash
84
- python3 <SkillDir>/scripts/gen_digital_human_video.py \
84
+ ab-skill gen-digital-human \
85
85
  --avatar-id 7 \
86
86
  --text "Hi everyone, welcome to the live stream — today I'll introduce a new product." \
87
87
  --voice-id "male-qn-qingse"
@@ -90,7 +90,7 @@ python3 <SkillDir>/scripts/gen_digital_human_video.py \
90
90
  #### TTS + custom voice + aspect ratio
91
91
 
92
92
  ```bash
93
- python3 <SkillDir>/scripts/gen_digital_human_video.py \
93
+ ab-skill gen-digital-human \
94
94
  --avatar-id 7 \
95
95
  --text "Hi class, here's our brand-new course." \
96
96
  --voice-id "female-shaonv" \
@@ -100,37 +100,19 @@ python3 <SkillDir>/scripts/gen_digital_human_video.py \
100
100
  #### Audio-driven mode
101
101
 
102
102
  ```bash
103
- python3 <SkillDir>/scripts/gen_digital_human_video.py \
103
+ ab-skill gen-digital-human \
104
104
  --avatar-id 39 \
105
105
  --source hifly \
106
106
  --audio-url "https://example.com/voice.mp3" \
107
107
  --aspect-ratio "16:9"
108
108
  ```
109
109
 
110
- #### Download to disk
111
-
112
- ```bash
113
- python3 <SkillDir>/scripts/gen_digital_human_video.py \
114
- --avatar-id 7 \
115
- --text "Hello world" \
116
- --download \
117
- --output "digital_human_output.mp4"
118
- ```
119
-
120
110
  ### 3. Check job status
121
111
 
122
112
  ```bash
123
- # Status only
124
- python3 <SkillDir>/scripts/gen_digital_human_video.py \
125
- --check-status --generation-id 123
126
-
127
- # Download once it's done
128
- python3 <SkillDir>/scripts/gen_digital_human_video.py \
129
- --check-status --generation-id 123 --download --output result.mp4
113
+ ab-skill gen-digital-human --check-status --generation-id 123
130
114
  ```
131
115
 
132
- For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py --help`.
133
-
134
116
  ## Common CLI flags
135
117
 
136
118
  ### List avatars
@@ -155,11 +137,8 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
155
137
  | `--source` | `jimeng` / `hifly` (inferable from avatar) | auto |
156
138
  | `--aspect-ratio` | `9:16` / `16:9` / `3:4` / `1:1` | avatar's default |
157
139
  | `--prompt` | Action prompt (e.g. "more hand gestures") | none |
158
- | `--download` | Download the video locally | off |
159
- | `-o` / `--output` | Download path (only with `--download`) | `digital_human_video.mp4` |
160
- | `--poll-interval` | Polling interval (seconds) | `5` |
161
- | `--max-wait` | Max wait time (seconds) | `600` |
162
- | `--private-token` | Override token | see env vars |
140
+ | `--api-base-url` | Override API root | see env vars |
141
+ | `--priv-token` | Override token | see env vars |
163
142
 
164
143
  ### Check status
165
144
 
@@ -167,8 +146,6 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
167
146
  |------|-------------|---------|
168
147
  | `--check-status` | Enter status-check mode | — |
169
148
  | `--generation-id` | Job id (required) | — |
170
- | `--download` | Download when finished | off |
171
- | `-o` / `--output` | Download path | `digital_human_video.mp4` |
172
149
 
173
150
  ## Typical flows
174
151
 
@@ -180,7 +157,7 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
180
157
  3. Confirm or polish the speech text
181
158
  4. (Optional) pick a voice → use gen-voice --list-voices
182
159
  5. Generate → --avatar-id <id> --text "..." --voice-id "female-shaonv"
183
- 6. Show URL or local path
160
+ 6. Show URL
184
161
  ```
185
162
 
186
163
  ### Flow B — Audio-driven
@@ -189,7 +166,7 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
189
166
  1. List avatars → --list-avatars [--mine]
190
167
  2. Prepare an audio URL (gen-voice can produce one)
191
168
  3. Generate → --avatar-id <id> --audio-url "https://..." [--source hifly]
192
- 4. Show URL or local path
169
+ 4. Show URL
193
170
  ```
194
171
 
195
172
  ## Text guidance (TTS)
@@ -203,7 +180,7 @@ For the full flag list: `python3 <SkillDir>/scripts/gen_digital_human_video.py -
203
180
  - **401** / **token missing** (non-OpenClaw): set `PRIV_TOKEN`.
204
181
  - **Business `code != 0`**: read `msg` on stderr.
205
182
  - **429**: rate-limited; retry later.
206
- - **Generation timeout**: increase `--max-wait`, or use `--check-status` later.
183
+ - **Generation timeout**: the handler caps polling at ~10 minutes; use `--check-status --generation-id <id>` later.
207
184
  - **Empty TTS text**: provide non-empty `--text` or use `--audio-url`.
208
185
  - **Invalid voice id**: re-check via `gen-voice --list-voices`.
209
186
  - **Avatar id not found**: re-check via `--list-avatars` (or `--list-avatars --mine`).
@@ -2,10 +2,11 @@
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"],
8
- "scriptPath": "scripts/gen_digital_human_video.py",
9
+ "entry": { "type": "http", "handler": "gen-digital-human" },
9
10
  "parameters": {
10
11
  "type": "object",
11
12
  "properties": {
@@ -16,7 +17,8 @@
16
17
  "text": { "type": "string", "description": "Narration text (TTS mode)" },
17
18
  "audio_url": { "type": "string", "description": "Audio URL (audio-driven mode)" },
18
19
  "voice_id": { "type": "string", "description": "Voice id" },
19
- "aspect_ratio": { "type": "string", "description": "Aspect ratio" }
20
+ "aspect_ratio": { "type": "string", "description": "Aspect ratio" },
21
+ "json_output": { "type": "boolean", "description": "Emit a JSON result (generate: { url, generationId }; list: { avatars }; check-status: { status, url }) instead of human-readable output" }
20
22
  },
21
23
  "required": []
22
24
  }
@@ -2,6 +2,6 @@
2
2
  "skillName": "gen-digital-human",
3
3
  "repoName": "agent-skill-media-maker",
4
4
  "skillId": "336",
5
- "version": "V5",
5
+ "version": "V7",
6
6
  "skillDescription": "数字人口播视频技能,支持查询形象、TTS 口播、音频驱动口播和查询生成状态(调用 ab-api 数字人接口,即梦 / 飞影)。\n\n当用户提到以下任何需求时,立即使用本 skill:\n- 数字人、数字人视频、数字人口播、生成数字人视频\n- 用户提供已有音频 URL(MP3 等)、用外链音频驱动数字人口型\n- AI 主播、虚拟主播、虚拟人物视频、口播视频\n- 让数字人说话、让虚拟人说一段话、让 AI 人物播报\n- 查看/列出数字人形象、有哪些数字人可以用\n- 使用即梦/飞影数字人\n\n即使用户没有明确说「使用 AI」,只要他们想要让一个虚拟人物朗读/播报一段文字并生成视频,也要使用本 skill。"
7
7
  }
@@ -23,7 +23,7 @@ Wraps ab-api's `POST /model/genImg` (the same endpoint the web studio uses), aut
23
23
 
24
24
  ## Models and sizes
25
25
 
26
- Aligned with `gen_image.py`'s `GEN_IMG_MODEL_PRESETS` and the backend `ModelGenImgDTO`:
26
+ Aligned with the gen-image handler's model presets and the backend `ModelGenImgDTO`:
27
27
 
28
28
  | LiteLLM `model` | Display name | Provider |
29
29
  |-----------------|--------------|----------|
@@ -46,7 +46,7 @@ No skill-local env file — the executing process inherits the system environmen
46
46
  |---------|-------------|---------|
47
47
  | `PRIV_TOKEN` | Tianyan token; `--priv-token` overrides | none |
48
48
  | `MM_IMAGE_MODEL` | Default model id | `doubao/doubao-seedream-4-5-251128` |
49
- | `MM_API_BASE_URL` | API root | see `gen_image.py` default |
49
+ | `MM_API_BASE_URL` | API root; `--api-base-url` overrides | `http://localhost:2999/api` |
50
50
  | `AGENT_NAME` | Optional `x-invoke-agent` header | none |
51
51
 
52
52
  ## Operations
@@ -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"],
@@ -15,7 +16,8 @@
15
16
  "resolution": { "type": "string", "enum": ["1K", "2K", "4K"], "description": "Output resolution (Gemini only)" },
16
17
  "n": { "type": "number", "description": "Number of images, 1-4" },
17
18
  "reference": { "type": "string", "description": "Reference image path or URL" },
18
- "negative_prompt": { "type": "string", "description": "Negative prompt — content to avoid" }
19
+ "negative_prompt": { "type": "string", "description": "Negative prompt — content to avoid" },
20
+ "json_output": { "type": "boolean", "description": "Emit a JSON result ({ urls: [...] }) instead of human-readable output" }
19
21
  },
20
22
  "required": ["prompt"]
21
23
  }
@@ -2,6 +2,6 @@
2
2
  "skillName": "gen-image",
3
3
  "repoName": "agent-skill-media-maker",
4
4
  "skillId": "337",
5
- "version": "V6",
5
+ "version": "V8",
6
6
  "skillDescription": "AI 生图技能,根据文字描述生成图片,也支持参考图进行图生图(调用 ab-api /model/genImg,支持 Seedream 与 Gemini)。\n\n当用户提到以下任何需求时,立即使用本 skill:\n- AI 生图、AI 画图、文生图、文字生成图片、生成图像、帮我画、生成一张图\n- 图生图、以图生图、参考图、风格迁移、图片变体\n- 使用 doubao / 豆包 / seedream、Gemini 等生成图片\n- 用户提供图片提示词并希望生成图片\n\n即使用户没有明确说「使用 AI」,只要他们想要根据描述生成图片,也要使用本 skill。"
7
7
  }
@@ -28,11 +28,11 @@ Turns a user-supplied **topic** into a **Video DSL v1alpha1** JSON describing wh
28
28
 
29
29
  ## DSL schema
30
30
 
31
- The full schema is `template-bind` skill's `video_dsl/schema/video-dsl-v1alpha1.json`; examples live in `video_dsl/schema/examples/` (locate them through `template-bind`'s `Base directory for this skill`).
31
+ The full schema is `template-registry` skill's `video_dsl/schema/video-dsl-v1alpha1.json`; examples live in `video_dsl/schema/examples/` (locate them through `template-registry`'s `Base directory for this skill`).
32
32
 
33
33
  ## Agent behavior: DSL generation when a template is selected
34
34
 
35
- **When the user explicitly specifies a template id, the agent must first read the existing `*.dsl.json` and `*.binding.json` examples in `template-bind`'s `video_dsl/schema/examples/`, then generate the DSL in the template's native shape using both those examples and the template's `template.json`. The agent must not generate the DSL from scratch ignoring the examples, and must not produce a generic DSL first and rely on `template-bind` to force-match the template later.**
35
+ **When the user explicitly specifies a template id, the agent must first read the existing `*.dsl.json` and `*.binding.json` examples in `template-registry`'s `video_dsl/schema/examples/`, then generate the DSL in the template's native shape using both those examples and the template's `template.json`. The agent must not generate the DSL from scratch ignoring the examples, and must not produce a generic DSL first and rely on `template-registry` to force-match the template later.**
36
36
 
37
37
  The intent is to reuse the validated example shapes already in the repo and to avoid the failure mode where "the generic DSL looks compatible on the surface, but is missing template-specific fields, has the wrong nesting, or binds incorrectly — only to fail later at binding or render time". Examples:
38
38
 
@@ -41,7 +41,7 @@ The intent is to reuse the validated example shapes already in the repo and to a
41
41
 
42
42
  ### Mandatory steps
43
43
 
44
- 1. Visit `template-bind/video_dsl/schema/examples/` and locate the closest existing `*.dsl.json` and `*.binding.json` for the requested template.
44
+ 1. Visit `template-registry/video_dsl/schema/examples/` and locate the closest existing `*.dsl.json` and `*.binding.json` for the requested template.
45
45
  2. Read those examples and understand the actual DSL shape, the `templateData` fields, the scene organization, and the binding style the template uses.
46
46
  3. Read the template's `template.json`.
47
47
  4. Combine the examples and `template.json` to understand the template's `slotMapping`, `requiredProps`, `optionalProps`, `propExtractors`, `assetRequirements`, `supportedAspectRatios`, and `scenePatterns`.
@@ -51,15 +51,15 @@ The intent is to reuse the validated example shapes already in the repo and to a
51
51
 
52
52
  ### Hard constraints
53
53
 
54
- - **Forbidden**: the user specified a template, but the agent generated the DSL without reading any of the existing examples under `template-bind/video_dsl/schema/examples/`.
54
+ - **Forbidden**: the user specified a template, but the agent generated the DSL without reading any of the existing examples under `template-registry/video_dsl/schema/examples/`.
55
55
  - **Forbidden**: only reading `template.json` while ignoring the existing `*.dsl.json` and `*.binding.json` examples.
56
- - **Forbidden**: the user specified a template, but the agent first generated a generic DSL and then passed `--template-id` to `template-bind` to force-bind it.
56
+ - **Forbidden**: the user specified a template, but the agent first generated a generic DSL and then passed `--template-id` to `template-registry` to force-bind it.
57
57
  - **Forbidden**: continuing into binding / rendering despite knowing that template-specific fields, scene shapes, or binding details are missing.
58
58
  - **Forbidden**: silently degrading to a generic DSL because the current script cannot support a template, leaving the failure to the downstream stage.
59
59
 
60
60
  ### When a template is not yet supported
61
61
 
62
- If `template-bind/video_dsl/schema/examples/` has no matching example for the requested template, or `gen_script.py` cannot yet build the required DSL shape, the agent must clearly tell the user "this template is not yet supported for auto-generation from existing examples" and explain what key fields, structure, or binding info are missing. Possible next steps:
62
+ If `template-registry/video_dsl/schema/examples/` has no matching example for the requested template, or `gen_script.py` cannot yet build the required DSL shape, the agent must clearly tell the user "this template is not yet supported for auto-generation from existing examples" and explain what key fields, structure, or binding info are missing. Possible next steps:
63
63
 
64
64
  1. Ask the user to switch to a template that has an example and is already supported.
65
65
  2. Have the agent take the closest `*.dsl.json` / `*.binding.json` as a reference and hand-craft the required DSL structure for this template, then show it to the user for confirmation.
@@ -67,7 +67,7 @@ If `template-bind/video_dsl/schema/examples/` has no matching example for the re
67
67
 
68
68
  ### Design principle
69
69
 
70
- When the user specifies a template, `gen-script`'s goal is no longer "produce a generally-compatible DSL" but "produce a template-native DSL based on the existing examples in `template-bind`".
70
+ When the user specifies a template, `gen-script`'s goal is no longer "produce a generally-compatible DSL" but "produce a template-native DSL based on the existing examples in `template-registry`".
71
71
 
72
72
  ## Authentication & environment
73
73
 
@@ -75,16 +75,16 @@ This skill does not hit any external API; no token required. The script only doe
75
75
 
76
76
  | Env var | Description | Default |
77
77
  |---------|-------------|---------|
78
- | `VIDEO_DSL_SCHEMA_PATH` | DSL schema file path. | Reads `template-bind` skill's `video_dsl/schema/video-dsl-v1alpha1.json` by default. |
78
+ | `VIDEO_DSL_SCHEMA_PATH` | DSL schema file path. | Reads `template-registry` skill's `video_dsl/schema/video-dsl-v1alpha1.json` by default. |
79
79
 
80
80
  ## Agent behavior: script confirmation
81
81
 
82
- **After the agent has generated a DSL it must first show the script summary to the user and get explicit confirmation before forwarding to downstream skills (template-bind / prepare-video-assets / render-video).** This lets the user review and adjust the scene structure, narration text, etc. before any asset is produced.
82
+ **After the agent has generated a DSL it must first show the script summary to the user and get explicit confirmation before forwarding to downstream skills (template-registry / prepare-video-assets / render-video).** This lets the user review and adjust the scene structure, narration text, etc. before any asset is produced.
83
83
 
84
84
  ### Confirmation flow
85
85
 
86
86
  1. After the agent generates or modifies the DSL, **show the script summary first; do not pass it downstream yet**.
87
- 2. Wait for the user to explicitly confirm (e.g. "OK", "looks good", "continue with template binding") before handing it to `prepare-video-assets` (or `template-bind` for a list-only lookup).
87
+ 2. Wait for the user to explicitly confirm (e.g. "OK", "looks good", "continue with template binding") before handing it to `prepare-video-assets` (or `template-registry` for a list-only lookup).
88
88
  3. If the user asks for changes (adjust narration, add or remove scenes, change durations), the agent updates the DSL and shows the summary again, then waits for confirmation once more.
89
89
 
90
90
  ### Summary content
@@ -174,7 +174,7 @@ Env vars `STUB_IMAGE_URL` / `STUB_VIDEO_URL` also work — their priority is low
174
174
 
175
175
  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.
176
176
  2. **Understand the request**: extract topic, target platform, duration, style, audience, etc.
177
- 3. **If the user specifies a template, read it first**: load the matching `template.json` via `template-bind` and confirm its template-specific fields and asset requirements. Do not skip this step.
177
+ 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.
178
178
  4. **Generate the DSL**: pick the right command or DSL shape for the target template (see the per-template commands below).
179
179
  5. **Schema validation**: make sure the output DSL conforms to v1alpha1.
180
180
  6. **User confirmation**: show the script summary and wait for confirmation, per the rules above.
@@ -208,7 +208,7 @@ python3 <SkillDir>/scripts/gen_script.py \
208
208
  --output output.dsl.json
209
209
  ```
210
210
 
211
- 5. **Result handling**: pass the generated DSL to `template-bind` for template lookup, or directly to `prepare-video-assets` (which auto-invokes template binding when `template_id` is provided).
211
+ 5. **Result handling**: pass the generated DSL to `template-registry` for template lookup, or directly to `prepare-video-assets` (which auto-invokes template binding when `template_id` is provided).
212
212
 
213
213
  ## Common CLI flags
214
214
 
@@ -280,4 +280,4 @@ Mirrors the `gen-image` skill and `GEN_IMG_MODEL_PRESETS` in `gen_image.py`. **O
280
280
  | `knowledge_card_script.json` | Intermediate knowledge-card script result. |
281
281
  | `script_knowledge_card.json` | Full knowledge-card script example. |
282
282
 
283
- These JSON files are reference data for development / debugging; they do not participate in runtime logic. The authoritative DSL examples live under `template-bind/video_dsl/schema/examples/`.
283
+ These JSON files are reference data for development / debugging; they do not participate in runtime logic. The authoritative DSL examples live under `template-registry/video_dsl/schema/examples/`.