Repository navigation
fix(cli): media-use voices says whose clones it lists, and --voice takes language codes - #7261
Conversation
4011865 to
545caba
Compare
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Reviewed at 545caba2984445f760f9f5c965204fedfd060d40. Request changes on the remaining teammate-voice consent bypass in the changed style-sampling instruction. skills/style-sampling/references/remix.md now correctly says the media-use voices list includes teammates’ clones and a named clone should be theirs, but its first two branches still say a person-supplied full voice ID is used “and ask nothing,” and a unique 8-character prefix is resolved and used without an ownership/permission condition. If a person supplies a teammate's ID or unique prefix without saying it is theirs or that its owner agreed, the agent is still expressly instructed to voice with it. The CLI accepts a full 32-hex ID without an owner lookup; the workspace voice list does not return owner identity, so presence/uniqueness cannot stand in for consent. Please qualify both full-ID and prefix paths: proceed only when the person identifies the clone as theirs or confirms its owner's permission; otherwise ask or use an explicitly chosen public/stock voice. This is a narrow wording fix, not a request to suppress the list or alter the accepted public-voice path.
The other changes look sound: voices labels workspace scope, pickVoice normalizes en, en-US, zh-CN and cmn to English/Chinese catalog queries and refuses an unrequested Multilingual fallback. Existing cached picks retain their previous selection by design. I inspected the seven-file patch and the exact-ref instruction/caller; I did not run a live voice generation or query owners/consent from the API. Hosted checks are independent of this missing permission condition. No merge or enqueue by me. — Jerrai
|
@jerrai-bot-heygen fixed in a53e5ff: |
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Re-reviewed successor a53e5fffda865bde48b84da23615b0fda2531c0d. The original full-ID/prefix loophole is narrowed: the guide and media-use voices output now explicitly require the person to say a clone is theirs or that its owner agreed. One remaining consent bypass blocks approval: the new sentence “An id that is not a clone there is a stock voice: use it” treats absence from a bounded list as proof of public/stock status. media-use voices defaults to ownVoices(20) (voices.ts:20–25), which calls GET /v3/voices?type=private&limit=20 (v3.ts:340–369). A workspace with >20 clones can supply a teammate's private clone ID beyond the first page. It will not appear in this result, so the guide calls it stock and instructs the agent to use it without owner consent; pickVoice accepts a full 32-hex ID directly with no catalog or ownership check (generate.ts:589–596). A failed or unavailable private-list read also cannot establish that an ID is public.
Please require a positive public-voice identification (e.g. matching the ID in a public catalog) before treating an unmatched ID as stock, or ask for the person's own/owner-permitted clone claim when provenance cannot be proven. Do not infer public status from a missing match in a 20-item private page. Add a wording/contract regression that captures an absent-from-first-page private ID; the current voices.test.ts checks the output sentence, not this inference. The language-code routing and explicit clone-permission wording otherwise remain sound. New-head CI is still running, an independent merge gate. No merge or enqueue by me. — Jerrai
There was a problem hiding this comment.
Reviewed at a53e5fffda865bde48b84da23615b0fda2531c0d (including the delta from 545caba2984445f760f9f5c965204fedfd060d40).
Need: yes · Size: ok · Reuse: existing publicVoices/persisted picks and Intl.DisplayNames · Simpler: keep unknown provenance unknown rather than infer it · Structure: fine
Risk: medium — agent instructions govern use of workspace clones.
Language normalization and fresh Multilingual-fallback refusal read clean. The new whose notice is in the command's JSON output via runMeasure, with or without --json. The new head also explicitly applies permission to named clones and clone IDs.
Important (blocks merge) — absence from this list does not establish a stock voice. As Jerrai also noted, skills/style-sampling/references/remix.md:26 now says “An id that is not a clone there is a stock voice: use it.” voices.ts:25 defaults to 20 entries; heygen/v3.ts:340–361 reads one page and discards has_more/next_token, although the generated list API exposes them. A teammate's clone on page 2 is absent, so this new instruction classifies it as stock and skips the permission question. pickVoice accepts a full hexadecimal ID unchanged, so no downstream guard corrects the classification.
I independently reproduced the list boundary using the exact transpiled listVoices and new voices command: a mocked valid first-page response from a 21-clone workspace produced one {type:"private",limit:20} request, 20 output voices, no pagination metadata, and omitted the known-private 21st ID. This is a fixture/probe, not a live API claim.
Fix: remove the absence→stock inference. Use an ID as stock only with positive public-voice evidence; otherwise ask once for the person's ownership/owner-permission confirmation. A larger private-list limit alone does not prove that an absent ID is public. Pin the unknown/unlisted-ID instruction in a regression alongside the consent wording.
Other verification: fresh exact-source function probes cover alias/case variants (including EN_us, eng, chi, cmn), matching-language acceptance, unknown-code Multilingual refusal, explicit Multilingual, and persisted-pick reuse. Selection code is unchanged at this re-pin. The dependency-backed generate/v3/voices suite could not collect with borrowed dependencies (stale workspace exports, then missing dependencies with source aliases). No live catalog or paid generation was exercised. Nit: docs/packages/cli.mdx:679 should also describe the workspace list and permission rule.
Verdict: REQUEST CHANGES
Reasoning: The new fallback instruction can still route an unlisted workspace clone around the permission requirement. Treating an unverified ID as unknown closes this without adding a new selection mechanism.
— Rames (hf-review)
|
@jerrai-bot-heygen @jrusso1020 fixed in 2e22cab. |
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Re-reviewed at 2e22cabf85adc820de525f37a2d7e3223401654f. The second consent blocker is closed: the style-sampling guide no longer infers “stock voice” from an ID absent in the private voice list. It explicitly says the list is one page, and the media-use voices output warns that an unlisted ID may still be a teammate’s clone. Full IDs and resolved prefixes now require the person to state the voice is theirs, its owner agreed to this film, or it is a HeyGen stock voice; otherwise the agent asks in its one question round. A prefix lookup uses --limit 100 but still treats absence/ambiguity as unknown, not as stock. The added output test asserts the missing-ID warning. Previously reviewed language normalization and Multilingual refusal are unchanged in this four-file successor commit.
This is instruction-level consent, not an API-enforced owner check: /v3/voices lacks an owner field, and the CLI accepts explicit full IDs without verifying the claim. A person could falsely describe a private clone as stock or theirs; enforcing provenance requires API support or a verifiable public catalog. That residual limitation is disclosed, not silently treated as proof. At click time the PR head was pinned, but mergeStateStatus=DIRTY and the new head's hosted checks had not populated; conflict resolution and green required checks remain independent merge gates. Code approval only; no merge, queue, paid voice call or permission to use any third-party voice. — Jerrai
jrusso1020
left a comment
There was a problem hiding this comment.
Reviewed at 2e22cabf85adc820de525f37a2d7e3223401654f (four-file delta from my a53e5fff review).
Need: yes · Size: ok · Reuse: existing voice-list output and permission question · Simpler: unknown provenance stays unknown · Structure: fine
Risk: medium — agent instructions govern use of workspace clones.
The previous Important finding is resolved: the guide no longer infers stock status from an ID missing from a private page. Full IDs and prefixes require the person's ownership, owner-permission, or explicit stock-voice statement; without one, the agent asks. Prefix lookup asks again for zero or multiple matches. The command's whose output explicitly warns that an absent ID may still be a teammate's clone, and voices.test.ts positively pins that warning. Accepting full IDs in the CLI is unchanged; this fix establishes an instruction-level confirmation, not API-enforced ownership verification.
Verification: API compare shows one commit, only the guide, output notice, wording test and generated manifest hash changed. An exact-source transpilation probe of packages/cli/src/commands/media-use/voices.ts (bun review-artifacts/hf7261-r3/notice-probe.ts) with injected list/output dependencies passed for default, JSON and limit-100 arguments; guide assertions pin the required confirmation and reject the old absence-to-stock sentence. These are focused probes, not a run of the dependency-backed 61-test suite. No live voice request or generation, and no fresh manifest-generator run. The earlier language-selection audit remains applicable because that code is unchanged.
GitHub currently reports mergeable: CONFLICTING, mergeStateStatus: DIRTY. I found no remaining wording blocker in this delta, but I am not approving this conflicting head. Resolve the merge conflict, regenerate the manifest as needed, and re-pin the resulting head for approval.
Verdict: COMMENT
Reasoning: The consent-inference blocker is fixed at this head. Approval awaits review of the conflict-resolved tree.
— Rames (hf-review)
…kes language codes
`media-use voices` lists every clone the account's workspace can use, a teammate's
included, and HeyGen does not say who made each one. The command's description and
output (`whose`) now say so, and the style-sampling remix rule no longer reads
"One clone: use it": a clone is used only when the person names it as their own.
`--voice en`, `en-US`, `zh`, `zh-CN` and `cmn` were sent to HeyGen as language names
it does not list, so it answered with a multilingual voice ("Gail in car") and the CLI
used it. Codes now map to the English language name HeyGen lists, and a multilingual
voice offered for a language the request did not name is refused with the fix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HebQXPiLcYKQfvPWB3Fgxy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HebQXPiLcYKQfvPWB3Fgxy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HebQXPiLcYKQfvPWB3Fgxy
…n says it is theirs The remix guide used a voice id the person gave, or a unique prefix of one, without asking whose clone it was. The workspace list includes teammates' clones, so either path could voice a film with someone else's clone. Both paths, and the `whose` line of `media-use voices`, now use a clone only when the person says it is theirs or that its owner agreed. An id that is not a clone in the list is a stock voice and is used as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HebQXPiLcYKQfvPWB3Fgxy
`media-use voices` returns one page of private voices (20 by default), so a teammate's clone can be absent from it. The remix guide treated an absent id as stock and used it without asking. Now a given id or prefix is used only when the person says it is theirs, that its owner agreed, or that it is a HeyGen stock voice; otherwise the agent asks in its one round of questions. The `whose` line says the list is one page and absence proves nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HebQXPiLcYKQfvPWB3Fgxy
2e22cab to
8fcbf2a
Compare
jrusso1020
left a comment
There was a problem hiding this comment.
Reviewed at 8fcbf2a0a8844c46a039dce6e44b5441bcca434c against main 41b7aeeafb99dba664f32b7ac0a8b0af5b7b75f1.
Need: yes · Size: ok · Reuse: existing voice picker and agent permission question · Simpler: already minimal · Structure: fine
Risk: medium — agent instructions govern workspace-clone use.
The earlier consent-inference blocker is fixed, and the merge conflict is resolved. Full IDs/prefixes require the person's ownership, owner-permission, or explicit stock-voice statement; missing IDs are unknown rather than inferred stock. This is instruction-level confirmation, not API-enforced owner verification.
Rebase verification: comparing the old and new base-relative patches shows identical changes in all five source/test files and the remix guide. All five source/test blobs are also identical to 2e22cabf. The guide's only blob difference is #7262's already-reviewed §7 render guidance. The generated manifest is the only changed patch: independently recomputing the sorted relative-path/content SHA-256 over both style-sampling files gives 5d26c6211fdfc062, matching the committed hash and file count. Other manifest entries have no base-relative changes.
Focused verification at this head: bun review-artifacts/hf7261-r4/notice-probe.ts passes for default, JSON and limit-100 output, and asserts the guide's confirmation/unknown-ID rules. The prior language-selection audit and consent-fix audit carry forward through the verified parity. I did not independently rerun the full 61-test suite or full manifest generator, and made no live voice request or paid generation. GitHub reports MERGEABLE at this head.
Verdict: APPROVE
Reasoning: The instruction-level consent-inference bypass is closed and the rebase preserves the reviewed behavior while correctly regenerating the conflicting manifest.
— Rames (hf-review)
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Re-reviewed #7261 at rebased 8fcbf2a0a8844c46a039dce6e44b5441bcca434c, base 41b7aeeafb99dba664f32b7ac0a8b0af5b7b75f1 after #7262 merged. The six non-manifest changed-file patches have identical added/removed lines to the previously approved 2e22cabf85adc820de525f37a2d7e3223401654f against its old base (normalized diff digest matched). The integrated style-sampling guide retains both the voice-consent/unknown-ID rule at §3 and the cloud elapsed-time wording from #7262 at §7. skills-manifest.json was regenerated for this integrated guide; its check remains a hosted gate. The bounded private-list absence is still treated as unknown, not proof of stock. My earlier instruction-level-versus-API ownership caveat remains.
This is a code re-approval only. The former conflict is gone, but new-head CI and Rames’s superseding review are independent merge gates; I did not merge, enqueue or exercise a paid voice call. — Jerrai
…view Adopts heygen-com#7299 (accented Latin letters draw in a bundled family at its bundled weight), heygen-com#7301 (installing Chrome on a busy Windows PC), heygen-com#7262 (cloud render logs a line a minute while a job holds its status), heygen-com#7265 (video starts a second early and catches up hidden) and heygen-com#7305 (check_report names the finding that stopped the check). Player packed budget takes upstream's +1655 from heygen-com#7265 since the player bundles core's media-steer. Defers heygen-com#7302; heygen-com#7261 and heygen-com#7263 do not apply. Watermark advances to 9e2510b. Co-authored-by: Miguel Ángel <miguel.sierra@heygen.com> Co-authored-by: WaterrrForever <miao.yang@heygen.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
media-use voicessays whose clones it lists.--voiceaccepts language codes and no longer uses a multilingual fallback voice without saying so.Why
These are two findings from the v0.9.16 style-sampling run: five 4-minute films, one per template, on a shared workspace account.
1.
media-use voiceshands an agent other people's voices (P0).GET /v3/voices?type=private. That returns every clone the workspace's ACL lets this user run. On the test account it returned 20 clones, all made by teammates. One of them,vclab-…-hv1, is named after the Finance template's reference creator.AudioVoiceItemcarries onlyvoice_id,name,language,gender,preview_audio_url,support_pause,support_localeandtype, so the CLI cannot filter to the person's own clones.style-sampling/references/remix.mdsays "One clone: use it. Several: ask which". With that list, an agent filtering to the episode's language gets exactly one clone and would use a creator-like voice.2.
--voice <language code>silently picks the wrong voice (P1).--voice en,en-US,zh,zh-CNandcmnall came back as "Gail in car", languageMultilingual. For a Chinese script, that is a wrong-language voice.remix.mdsays--voice <the script's language>without saying which spelling. The catalog filters by English language name, soEnglishandChinesework and the codes fall through to the multilingual default.How
media-use voiceswhoseline that tells the agent to use a clone only when the person names it, or gives its id, as their own, and never to pick one by count, language or name.remix.mddrops "One clone: use it".pickVoiceIntl.DisplayNames. Examples:en-US→ English,zh-CN→ Chinese,cmn→ Chinese.English,ChineseandHindistill work.Multilingualvoice for a request that didn't name Multilingual, the CLI refuses with a fix instead of using it. "Mandarin" now fails clearly instead of returning Gail..hyperframes/heygen-jobs.jsonlis still returned first, so a re-run of an existing project keeps its voice and its idempotency key.The template kits carry the same rule in their REMIX and README files. Those changes ship in the template bundles and are re-pinned in a separate PR.
Related work
Follow-up to the v0.9.16 release check. A real owner filter needs the API to expose who created a voice. That is a separate experiment-framework change.
Test plan
mainand pass here.voices: the output says the list includes teammates' clones.pickVoicewithen,en-US,zh-CNandcmnasks for English or Chinese.generate.test.ts,v3.test.tsandvoices.test.ts: 95 passed.tsc --noEmit: no errors in the touched files.lint-skills,check-core-skillsandcheck-skill-mirrorpass.check-attr --source. CI runs it. No comments were added.--voice Englishgave Leanne,--voice Chinesegave Shuxian, and every code gave Gail.🤖 Generated with Claude Code
https://claude.ai/code/session_01HebQXPiLcYKQfvPWB3Fgxy