Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/cli/src/auth/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
AuthClient,
HEYGEN_CLI_SOURCE,
HEYGEN_CLI_SOURCE_HEADER,
HEYGEN_CLIENT_SOURCE,
HEYGEN_CLIENT_SOURCE_HEADER,
apiBaseUrl,
buildAuthHeaders,
} from "./client.js";
Expand Down Expand Up @@ -81,12 +83,14 @@ describe("auth/client", () => {
expect(buildAuthHeaders(cred)).toEqual({
authorization: "Bearer at_123",
[HEYGEN_CLI_SOURCE_HEADER]: HEYGEN_CLI_SOURCE,
[HEYGEN_CLIENT_SOURCE_HEADER]: HEYGEN_CLIENT_SOURCE,
});
});

it("buildAuthHeaders uses x-api-key for api_key, without the cli-source header", () => {
it("buildAuthHeaders uses x-api-key for api_key, without the cli-source header but with the tool tag", () => {
expect(buildAuthHeaders(apiKeyCred())).toEqual({
"x-api-key": "hg_x",
[HEYGEN_CLIENT_SOURCE_HEADER]: HEYGEN_CLIENT_SOURCE,
});
});

Expand Down
12 changes: 10 additions & 2 deletions packages/cli/src/auth/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ import type { OAuthTokens } from "./store.js";
const DEFAULT_BASE_URL = "https://api.heygen.com";
export const HEYGEN_CLI_SOURCE_HEADER = "X-HeyGen-Source";
export const HEYGEN_CLI_SOURCE = "cli";
// Tool-attribution header identifying this CLI as the request origin. Sent on
// every HeyGen call (both auth types) so the backend can isolate hyperframes CLI
// usage in billing meta. Distinct from HEYGEN_CLI_SOURCE_HEADER above, which is
// the OAuth-only cli-source header that gates the free allowance.
export const HEYGEN_CLIENT_SOURCE_HEADER = "X-HeyGen-Client-Source";
export const HEYGEN_CLIENT_SOURCE = "hyperframes";

export function apiBaseUrl(): string {
const override = process.env["HEYGEN_API_URL"];
Expand Down Expand Up @@ -182,12 +188,14 @@ export function buildAuthHeaders(credential: ResolvedCredential): Record<string,
return {
authorization: `Bearer ${credential.access_token}`,
[HEYGEN_CLI_SOURCE_HEADER]: HEYGEN_CLI_SOURCE,
[HEYGEN_CLIENT_SOURCE_HEADER]: HEYGEN_CLIENT_SOURCE,
};
}
// API-key traffic keeps the normal billing path; the backend ignores the
// cli-source header for it, so we don't send it (avoids a contradictory
// "cli-source claim on an API-key request").
return { "x-api-key": credential.key };
// "cli-source claim on an API-key request"). The tool-attribution header IS
// sent here — an API-key hyperframes call is still hyperframes usage.
return { "x-api-key": credential.key, [HEYGEN_CLIENT_SOURCE_HEADER]: HEYGEN_CLIENT_SOURCE };
}

async function safeText(res: Response): Promise<string> {
Expand Down
Loading