9 Commits

Author SHA1 Message Date
Eve 89d28b99bc feat: add heygen-translate skill (video translation / dubbing) (#82)
* feat: add heygen-translate skill (video translation / dubbing)

Adds a third skill, heygen-translate/, for translating and dubbing existing
videos into 175+ languages with voice cloning and lip-sync. Built on the
same independent-skill structure as heygen-avatar and heygen-video.

What:
- heygen-translate/SKILL.md (4-phase workflow: Discovery → Pre-flight →
  Submit+Poll → Deliver) with the same API Mode Detection ladder as
  heygen-video (OpenClaw plugin → CLI w/ HEYGEN_API_KEY → MCP → CLI
  fallback). All operations shown with MCP and CLI side-by-side, no raw
  curl.
- heygen-translate/references/troubleshooting.md (errors → action map,
  polling patterns, harness-specific notes for Claude Code / OpenClaw /
  Cursor)
- heygen-translate/references/language-locale-guide.md (regional variant
  defaults, formality registers, RTL caption collisions, tonal
  compression/expansion table, lip-sync ceiling per language)
- heygen-translate/references/proofreads-workflow.md (the high-stakes
  review-edit-render path: extract SRT → glossary discipline → register
  fixes → upload edited SRT → final render)
- heygen-translate/references/asset-routing.md (URL vs asset_id vs local
  upload routing, HEAD-check pattern, auth-walled URL fallbacks, 32 MB
  limit handling)

Replaces PR #46 with the new repo structure (independent skills, no root
SKILL.md, references inside the skill, validate-skills.yml self-contained
checks, MCP+CLI transport not raw API).

Why:
- PR #46's SKILL.md frontmatter declared 'allowed-tools: mcp__heygen__*'
  but every example used raw curl against api.heygen.com. Mismatch fixed
  here by using the heygen video-translate CLI (with MCP fallthrough)
  per the established pattern in heygen-avatar/heygen-video.
- PR #46 was authored against the pre-#79 structure (root SKILL.md +
  shared references/). Repo restructured 24h ago — each skill now owns
  its own SKILL.md and references/. This PR matches.
- PR #46 lacked embedded translation expertise. This SKILL.md adds:
  speaker-count discipline, source-quality triage, locale-pair gotchas
  (formality registers in ja/ko/de/th/hi, RTL caption collisions,
  tonal compression for en→zh/ja/ko, regional variants for es/pt/zh),
  lip-sync ceiling, captions burned-in vs sidecar, audio-only as a
  different deliverable not a workaround, cost/time math, and a
  failure-mode decoder.
- PR #46 used 'video-translate/' breaking the heygen-avatar/heygen-video
  prefix pattern. Renamed to 'heygen-translate/' for consistency in ls
  output and plugin manifest paths.
- Adds a true proofreads workflow (extract SRT → user/agent edits →
  upload corrected SRT → render) — this is the missing high-stakes path
  that distinguishes the skill from API docs.

Plumbing:
- .claude-plugin/marketplace.json registers heygen:translate
- .claude-plugin/plugin.json updates description + keywords
- .codex-plugin/plugin.json updates description, keywords, longDescription,
  defaultPrompt
- .cursor-plugin/plugin.json adds heygen-translate to skills array, plus
  keywords/tags
- .github/workflows/validate-skills.yml adds heygen-translate to path
  filter and runs the same self-contained-bundle checks as the other two
  skills
- release-please-config.json adds heygen-translate/SKILL.md as a
  release-please extra-files target so the version bumps in lockstep
- README.md, INSTALL.md, INSTALL_FOR_AGENTS.md, CLAUDE.md, CONTRIBUTING.md
  all updated to reference the third skill

Out of scope (followups):
- platforms/nanoclaw/heygen-translate/ NanoClaw container variant
- Eval scenarios for heygen-translate (mirror of R17-R23 pattern from
  heygen-video)
- gh skill / agentskills.io spec compliance check (handled by the
  spec-validate-soft job already in validate-skills.yml)
- Mark PR #46 as superseded once this lands

Refs: PR #46 (predecessor), #79 (independent-skills restructure), #77
(gh skill install path)

* docs(heygen-translate): document what the proofread CLI actually performs

Per Ken's ask in #tmp-vt-skill: rewrite proofreads-workflow.md (and the
Phase 3 proofread snippet in SKILL.md) against verified live behavior of
the heygen video-translate proofreads commands, not assumed/inferred
behavior.

Verified against the live API + CLI on Apr 27 with two real proofread
sessions (b84c8e8d... silent-source failure, 8ce0fba6c... Spanish
Sintel-trailer success).

Now documented:

- Five subcommands mapped to real REST endpoints:
    create     POST /v3/video-translations/proofreads
    get        GET  /v3/video-translations/proofreads/{id}
    srt get    GET  /v3/video-translations/proofreads/{id}/srt
    srt update PUT  /v3/video-translations/proofreads/{id}/srt
    generate   POST /v3/video-translations/proofreads/{id}/generate
- What the engine actually does between create and completed (downloads
  source, runs ASR for original_srt_url, translates to srt_url, no
  render yet).
- Real response shapes for create / get / srt get / srt update / generate
  with verified JSON examples and field-by-field meanings.
- Real status enum: processing | completed | failed (NOT pending|running
  — that's the translation-render endpoint, which is a different state
  machine the resource graduates into after generate).
- Polling cadence verified empirically: 3-5 min for SRT extraction on a
  50-second source. Hard timeout 30 min for stuck sessions.
- SRT format: standard SRT (UTF-8), well-formed timecodes, editable by
  hand or sed.
- File naming: <title>_proofread.srt and <title>_proofread_original.srt.
- original_srt_url is auto-populated source-language transcription, not
  a copy of any user-provided SRT. Useful as ground truth, never
  re-uploaded as target-language SRT.

Critical correction: heygen asset create does NOT accept SRT files.

The CLI exposes both URL and asset_id shapes for srt update, but the
asset_id upload path is currently BLOCKED:

    {"error":{"code":"invalid_parameter",
              "message":"Content type not supported application/x-subrip"}}

heygen asset create only accepts png/jpeg/mp4/webm/mp3/wav/pdf.
Renaming .srt to .txt or .mp3 does not bypass it (server sniffs content,
not extension). The asset_id route is in the request schema for forward
compatibility but cannot currently be exercised through the standard
upload path.

Use the URL route. The reference now documents practical hosts that
work (gist raw URLs, GitHub raw URLs, S3 public-read, presigned
URLs >=2h, Vercel/static).

Two new failure_message strings added to troubleshooting.md from real
API responses:
- 'Failed to download video from url, please check the url is valid or
   the video is public' (instant-fail on bad/auth-walled source URL)
- 'Your video's audio is missing or corrupted, please try with another
   video' (~30s fail when source has no speech)

Other documented quirks:
- proofreads create returns proofread_ids (plural, one per language)
  plus a session-level status — per-id status comes from proofreads get.
- After generate, polling shifts from proofreads get to
  video-translate get because the resource graduates from proofread
  to translation.
- Captions on generate are independent of the proofread session's SRT —
  --captions controls whether the FINAL video burns captions in.
- Proofread session TTL ~24h.

Out of scope for this commit (still in followup queue):
- NanoClaw platform variant
- Eval scenarios for heygen-translate
- File issue/PR upstream re: SRT asset upload (worth surfacing to HeyGen
  CLI team — the asset_id route in the schema can't be reached today)

* fix(heygen-translate): auth gate, duration question, open-ended language input

Three improvements from dogfooding:

- Add auth verification step before Phase 1: runs `heygen auth status` in CLI
  mode, asks for API key and persists via `heygen auth login` if missing.
  One-time setup that survives across sessions.
- Add duration flexibility question to Phase 1 discovery: asks whether output
  must match source length, explains quality tradeoff, controls
  `enable_dynamic_duration` flag instead of hardcoding true.
- Make target language question explicitly open-ended: no picker, no
  pre-assigned choices. User types freely, validation in Phase 2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(heygen-translate): align dynamic_duration references with Phase 1 question

SKILL.md:335 and references/language-locale-guide.md:49 both said "Always
enable_dynamic_duration: true", contradicting the new Phase 1 duration
flexibility question. Updated both to reference the user's choice and warn
about quality degradation on high-compression pairs when fixed-length is chosen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: David Chou <david.chou@heygen.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-13 10:58:56 -07:00
Eve d70bfc438a feat!: eliminate root SKILL.md + root references/ — skills are now independent (#79)
Two skills, two bundles, no shared root. Each skill owns its references
and ships independently to gh skill install / ClawHub / OpenClaw plugin /
direct git clone.

Migrations into per-skill SKILL.md before deleting root:

heygen-avatar/SKILL.md: + Files & Paths, Language Awareness, UX Rules
heygen-video/SKILL.md:  + Files & Paths, UX Rules, Language Awareness,
                        First Look (first-run avatar check), v3-only
                        warning banner

Deleted (1940 lines):
- SKILL.md (the root meta-skill)
- references/ (the canonical shared references — each skill now owns its copy)
- scripts/sync-references.sh + scripts/update-check.sh (no longer needed
  at root; heygen-video/scripts/update-check.sh is the live copy)

Updated peripherals:
- INSTALL_FOR_AGENTS.md: drop root SKILL.md from canonical URLs and
  rewrite mode-detection-ladder pointers to per-skill SKILL.md
- CLAUDE.md: rewrite Architecture diagram + 300-line rule pointers,
  add explicit note that drift between skills is acceptable
- CONTRIBUTING.md: drop sync-references.sh editor checklist + section,
  replace with simpler "edit the skill that owns the file" guidance
- release-please-config.json: drop root SKILL.md from extra-files
- validate-skills.yml: drop references-in-sync job, drop root path
  triggers, add per-skill ../ check on the in-tree references/ dirs
  to catch parent-dir paths before install

Verified empirically (gh 2.91.0):
- gh skill install heygen-com/skills heygen-{avatar,video} --from-local
  produces fully self-contained bundles
- Codex plugin manifest "skills": "./" still discovers both subdirs via
  */SKILL.md convention
- update-check.sh (heygen-video/scripts/) reads version from frontmatter
  fallback when no repo-root VERSION is reachable
- No orphans, no broken references, no parent-dir paths

BREAKING CHANGE: Direct-clone consumers who cached root SKILL.md
will lose access to the meta-router skill. Contents migrated into both
heygen-avatar/SKILL.md and heygen-video/SKILL.md so the skills remain
fully functional standalone. Re-clone or git pull picks up the new layout.
2026-04-27 16:13:03 -07:00
Eve e66e7161ef feat: make heygen-avatar + heygen-video install cleanly via gh skill (#77)
* feat(skills): co-locate references for gh skill self-containment

Each skill (heygen-avatar, heygen-video) now bundles its own references/
directory with the docs it links to. This makes both skills install
cleanly via gh skill install (which only copies the skill subdirectory),
without breaking the OpenClaw plugin or direct git clone lanes that use
the repo-root references/ directory.

* docs: add gh skill install instructions + CI validation

- README + INSTALL.md: list gh skill install as Option 1, alongside
  ClawHub, OpenClaw plugin, and git clone
- Add validate-skills.yml CI: runs gh skill install --from-local for
  both skills and asserts each installed bundle is self-contained
  (no broken ../ refs, every references/ link resolves)
- Cross-skill references in references/ files now use absolute GitHub
  URLs so they remain clickable on GitHub and never produce broken
  links inside an installed bundle
- .gitignore: skip local CI fixtures (.agents/, _ghskill_test/, _install_test/)

* fix(ci): isolate install target + add references-in-sync drift gate

Address review feedback:

1. CI install path mismatch: gh skill install --scope project resolves
   to the outer repo project root (skills/.agents/), not _install_test/.
   Initialize _install_test as its own git repo so it becomes its own
   project root and the install lands inside it. Verified locally that
   the assertion now actually runs.

2. No drift-prevention CI step: add a references-in-sync job that
   diff-checks all 10 shared files (heygen-{avatar,video}/references/X
   vs root references/X) for byte-identity. Fails CI on drift with a
   helpful diff. New per-skill files (avatar-creation.md, the cleaved
   avatar-discovery.md halves) are intentionally NOT in this matrix —
   only the truly shared docs are gated.

3. Use bash 3.2-portable parallel array (pipe-delimited pairs) instead
   of associative array so the workflow can be sanity-checked locally
   on macOS without bash 5+.

* chore: purge orphaned references, wire prompt-styles, add sync script

Audit of references/*.md outcome:
- 7 files: actively linked from skills, kept as-is
- 1 file (prompt-styles.md): linked only from root SKILL.md, orphaned in
  the gh-skill subdir bundle. Wired into heygen-video/SKILL.md alongside
  the existing prompt-craft / motion-vocabulary pointers.
- 1 file (reviewer-prompt.md): zero links from any SKILL.md, dead in
  the workflow. Deleted from root references/ and heygen-video/references/.

Sync workflow (Option 2):
- Add scripts/sync-references.sh — propagates root references/ to per-skill
  copies (--check mode for CI drift detection, no args for sync).
- validate-skills.yml now invokes ./scripts/sync-references.sh --check
  instead of inlining the pair list (single source of truth).
- New CI orphan-check: every bundled references/* / scripts/* file in an
  installed bundle must be linked from SKILL.md.
- CONTRIBUTING.md documents the references layout + editor workflow.

---------

Co-authored-by: Ken Chung <kchung@heygen.com>
2026-04-27 15:52:15 -07:00
Eve 256896e3b2 fix(ci): use PAT for release-please so tag push fires publish.yml (#74)
Problem
-------

GitHub Actions intentionally does not trigger downstream workflows when
tags are pushed by GITHUB_TOKEN. This is documented behavior to prevent
recursive CI loops:

  https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow

For this repo, that means: release-please tags v\*, but publish.yml
(triggered on tag push) never fires. Result: every release requires a
manual republish to ClawHub. Concrete failure today \(v2.2.0\): tag
created at 14:49 UTC by release-please, publish.yml never ran, ClawHub
stayed on 2.1.2 until manual republish at 15:03 UTC.

Same failure mode reproduced today on v2.2.1 (the avatar canonical
install fix). Manual republish required again.

Fix
---

Read token from a separate secret \(RELEASE_PLEASE_TOKEN\) which the user
provides as a fine-grained PAT scoped to:
  - Contents: read+write
  - Pull requests: read+write
  - Workflows: write \(for editing release workflow files\)

Tag pushes from a PAT \(not GITHUB_TOKEN\) do trigger downstream workflows,
so publish.yml will fire on every release-please-created tag.

Falls back to GITHUB_TOKEN if RELEASE_PLEASE_TOKEN is unset \(non-breaking
until the secret is added\).

Setup steps for repo admin
---------------------------

1. Generate a fine-grained PAT at:
   https://github.com/settings/personal-access-tokens/new
2. Resource owner: heygen-com
3. Repository access: 'Only select repositories' -> 'heygen-com/skills'
4. Permissions:
   - Contents: read+write
   - Pull requests: read+write
   - Workflows: write
5. Expiration: 90 days \(rotate quarterly\)
6. Add as repo secret: Settings -> Secrets and variables -> Actions
   -> 'New repository secret', name 'RELEASE_PLEASE_TOKEN'

After the secret is added, the next release-please tag push will fire
publish.yml automatically.

Verification
------------

After merge + secret add, monitor next release: tag should appear, then
publish.yml run should appear in Actions tab within ~30 seconds. ClawHub
will reflect the new version automatically.
2026-04-27 14:48:16 -07:00
Ken Chung 9c809d4a4b chore: add release-please for version management (#48)
Adopt release-please to bump VERSION, SKILL.md frontmatter, and User-Agent
strings in one atomic release PR driven by conventional commits.

Problem: version was tracked in 3 places (VERSION file, SKILL.md frontmatter,
User-Agent strings) and all had drifted from each other and from the actual
git tag line (v2.0.3). Publish workflow keyed on git tag, so SKILL.md version
never mattered for publishing — but it confused contributors and LLMs reading
the skill.

Solution:
- `release-please-config.json` — declares VERSION as the version-file, plus
  three extra-files (SKILL.md + two sub-skills) with x-release-please-version
  annotations on the exact lines to bump.
- `.release-please-manifest.json` — tracks current release (2.0.3).
- `.github/workflows/release-please.yml` — opens/updates a release PR on
  every push to master. Merging that PR creates the tag, which triggers the
  existing publish.yml to ship to ClawHub.
- Normalized all version strings on master to 2.0.3 (matches latest tag).

Flow going forward:
1. PRs land on master with conventional commit messages (`feat:`, `fix:`)
2. release-please opens "chore: release X.Y.Z" PR with all version bumps
3. Merge the release PR → tag auto-created → publish.yml ships to ClawHub
4. No human ever types a version number

Co-authored-by: Ken <ken@heygen.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-16 21:28:31 -07:00
Eve 14c14e7d71 fix(ci): write clawhub config file for GHA auth (#41) 2026-04-13 18:15:14 -07:00
Eve 69927ac13f ci: add ClawHub publish workflow on tag push (#39) 2026-04-13 18:09:33 -07:00
Eve Park ea482c1876 simplify: drop GHA, publish directly from release script
One command: ./scripts/release.sh minor
Bumps version, pushes, publishes to ClawHub as heygen-stack.
2026-04-06 18:07:17 -07:00
Eve Park d06bda660a feat: GitHub Actions release pipeline + ClawHub publish
- .github/workflows/release.yml: tag-triggered release + ClawHub publish
- CHANGELOG.md: v1.0.0 and v1.1.0 release notes
- scripts/release.sh: version bump + tag helper

Flow: ./scripts/release.sh minor → git push --follow-tags → GHA creates
GitHub Release + publishes both skills to ClawHub.

Requires: CLAWHUB_TOKEN repo secret.
2026-04-06 17:35:15 -07:00