Files
WaterrrForever 8089f0049c feat(skills): soft-launch reverse-any-video, and fix what Wanbi's Pro test found (#7006)
* feat(skills): publish reverse-any-video, render it at high quality, and stop on a stuck shot

From Wanbi's Pro test of reverse-any-video (11-01, checked against 0.9.2):

- A standard install never found the skill: it was internal, and /hyperframes did not route to
  it. It is now an on-demand skill on every catalog surface, and the routing line names it.
- The cloud render in SKILL.md had no --quality high, so the final rendered at standard.
- A re-shoot that stayed pending had no rule; the run waited four hours. people.md now runs the
  command once more after generate's 30-minute stop, then treats the shot as failed.

* feat(cli): generate takes a language for --voice, so a Pro sign-in gets a HeyGen voice

Wanbi's Pro run fell back to Kokoro: --voice needed an id, and the only way to list ids was the
separate heygen CLI and its own login. /v3/voices answers on the HyperFrames sign-in, so:

- --voice <language> picks HeyGen's first public voice in it and names it in the output.
- A missing --voice lists six English voices to pick from instead of a bare error.
- A voice id still goes straight through, with no extra call.

* fix(cli): a voice picked by language stays with its request across re-runs

Rames: `--voice Chinese` re-picked HeyGen's first voice on every run, and the voice is part of the
body and the idempotency key. If the catalog reordered while a job was pending, the same command
could start a second paid job instead of resuming the first.

The pick is now bound to the request (every field, plus the account scope a job bills) in the
project's heygen-jobs.jsonl, or the CLI config dir outside a project, and a re-run reuses it.
Regression: a pending timeout, a reordered catalog, the same command, for voice and avatar; the
second POST keeps the voice, body and key.

* fix(cli): a voice pick waits for a known account instead of binding to none

Rames: when /v3/users/me failed, senderScope() was null and the pick was bound to an empty
scope; once the account came back, the same command missed that binding and could pick another
voice and paid key. pickVoice now stops before picking or posting while the account is unknown,
and never reads or writes a blank-account binding.

Regressions, both directions: unknown then known refuses with no POST, then picks once; known
then unknown refuses the re-run with no second POST, then resumes with the same body and key.
Also README: a non-interactive install gets all 8 skills, not 7.
2026-11-02 11:48:55 +00:00
..