feat(media-use): tag HeyGen API calls with X-HeyGen-Client-Source#2365
Conversation
somanshreddy
left a comment
There was a problem hiding this comment.
Reviewed as the sender half of the X-HeyGen-Client-Source pair (EF #41968 is the receiver). LGTM — clean, and the wire seam lines up.
- The value emitted here —
X-HeyGen-Client-Source: media-use— is exactly what EF #41968's persist allowlist accepts (_KNOWN_CLIENT_SOURCES = {"media-use", "hyperframes"}), so the tag actually lands in billing meta rather than silently dropping. That cross-PR value match is the make-or-break check for this feature, and it holds. - Sent on both auth types. The comment correctly distinguishes this unconditional tool-attribution header from the OAuth-only
X-HeyGen-Source: cliheader that gates the free allowance — a paying (API-key) media-use call is still media-use, so tagging it too is right, and it matches the receiver readingclient_sourceon both auth paths. - Tests updated for both branches (API-key + OAuth) asserting the tag is present. ✅
skills-manifest.jsonhash bump is the expected artifact of the skill-file change; CI (incl. manifest checks) is green.
Non-blocking nit: in heygenJSON, { ...HEYGEN_CLIENT_SOURCE_HEADERS, ...headers } lets a caller-supplied header override the tag. Harmless here (auth headers carry the same value, and an explicit override is a reasonable escape hatch) — just flagging that the precedence is intentional.
— Somu
james-russo-rames-d-jusso
left a comment
There was a problem hiding this comment.
Reviewed as the client half of the X-HeyGen-Client-Source pair with EF#41968 open in the other tab. Layering on Somu's review (which nailed the wire-seam value-match + dual-auth coverage) — adding one call-site coverage check and cross-linking one downstream gotcha that lives on the EF side but is worth surfacing here for the Hex-slice goal.
Call-site coverage (comprehensive, not narrow — verified). Traced every credit-consuming HeyGen API call path in media-use and all of them go through a tagged transport at head cc1b7eb:
heygen-tts.mjs:69→heygenAuthHeaders()→ tagged atheygen.mjs:96-98(both OAuth and API-key branches).heygen-tts.mjs:76(/voices?engine=starfish...) →heygenJSON(...)→ tagged atheygen.mjs:111.audio/scripts/lib/tts.mjs:306-309synthesizeHeygen→heygenJSON('/voices/speech', ...)withauthHeaders()→ double-tagged (auth-headers already carry the tag;heygenJSONmerges its own default) — same value both places, safe.scripts/lib/heygen-search.mjs:11(pre-existing) already emits the same header/value via theheygen --headersflag; this PR is the missing-half extension to the audio engine (right pattern).
No un-tagged HeyGen API call path in media-use/ at HEAD. So the Hex-slice denominator ("all media-use HeyGen consumption") shouldn't have blind spots on the emit side.
One downstream drop worth checking with the receiver PR (EF#41968). MovioBill.meta picks up client_source fine via get_api_origin_meta_extras() — that's the direct write path this PR targets. But EF's filter_api_origin_meta() (used by heygen/jobs/video_repurpose/process_clip_activity.py and heygen/services/heygen_server/video_metadata_store.py to copy origin attribution onto derived resources) reads a fixed tuple API_ORIGIN_META_KEYS that does not include client_source at EF HEAD 58f8ee6. If the Hex-slice dashboard queries only the direct bill row, no issue. If it also expects the tool dimension to survive video_repurpose → clip meta or master_video_metadata propagation, client_source needs to land in that tuple too. Flagged on the EF PR — non-blocking here, cross-linked so the pair discussion sees it.
Small note, non-blocking. The header is user-declared and there is no server-side auth boundary tied to it (EF's _KNOWN_CLIENT_SOURCES allowlist gates persistence, and genesis-code-reviewer confirmed client_source feeds no OAuthBillingDecision / get_feature / quota routing). So spoofing risk is analytics-inflation only — worth carrying as a known property of the tag, not a fix here.
LGTM from my side — leaving as a comment; approval routes to Vai / OG on Miguel's stamp convention.
— Review by Rames D Jusso
cc1b7eb to
3e1a56e
Compare
Send `X-HeyGen-Client-Source: media-use` on every media-use HeyGen API request (both auth types, via heygenAuthHeaders + the heygenJSON transport), so backend billing meta can isolate media-use consumption from other free TTS and avatar-video usage. Unconditional of auth type — a paying user's media-use call is still media-use — unlike the OAuth-only cli-source header that gates the free allowance.
3e1a56e to
344ed75
Compare
…Source (#2391) The agent-driven video recipes (heygen video create) went out untagged, so media-use avatar / image-to-video usage landed as generic cli traffic and wasn't attributable to media-use. Add --headers "X-HeyGen-Client-Source: media-use" to the generating recipes (persistent flag, allowlisted by the CLI) so those videos carry client_source in master_video_table meta and show up in the API dashboards alongside the TTS path (#2365) and CLI (#2368).
What
media-use now sends an
X-HeyGen-Client-Source: media-useheader on every HeyGen API request it makes (both OAuth and API-key auth), viaheygenAuthHeaders()and theheygenJSONtransport in the audio engine.Why
media-use resolves voice / TTS / sound assets through the HeyGen API. Today those requests are indistinguishable from other first-party CLI traffic, so HeyGen API usage can't be attributed back to media-use. A stable, self-declared tool-attribution header lets the backend tag media-use usage as its own source. The header name already exists in the sound-search path (
heygen-search.mjs); this extends it to the credit-consuming audio calls and makes it consistent across the engine.How
HEYGEN_CLIENT_SOURCE_HEADERSconstant.heygenAuthHeaders()(covers the TTS request path) and into theheygenJSONtransport's default headers (covers other REST calls).X-HeyGen-Source: cliheader, which also gates the free allowance and is deliberately left untouched.Test plan
heygen.test.mjs: both auth branches (api-key and OAuth) now assertX-HeyGen-Client-Source: media-useis present.node --test heygen.test.mjs→ 5/5 pass.oxlint+oxfmtclean on changed files.Not covered