Skill Tracer
Skills › HyperFrames › media-use › credit-limit.mjs

credit-limit.mjs

41 lines · skills/media-use/scripts/lib/credit-limit.mjs at a595755

1import { existsSync, readFileSync } from "node:fs";
2import { join } from "node:path";
3
4// A run's credit limit: the person's named total, in `.hyperframes/credit-limit.json` as {"credits": N}.
5// What is spent is read back from the job log (`.hyperframes/heygen-jobs.jsonl`): the last credits a job key logged.
6
7const read = (file) => (existsSync(file) ? readFileSync(file, "utf8") : "");
8
9/** The limit set for this project, or undefined when the person named none. Unreadable is an error, never "none". */
10export function creditLimit(projectDir) {
11 const text = read(join(projectDir, ".hyperframes", "credit-limit.json"));
12 if (!text) return undefined;
13 const credits = Number(JSON.parse(text)?.credits);
14 if (!Number.isFinite(credits) || credits < 0)
15 throw new Error(`${projectDir}/.hyperframes/credit-limit.json needs {"credits": <number>}`);
16 return credits;
19/** Credits already committed by jobs in this project, and the job keys behind them. */
20export function creditsSpent(projectDir) {
21 const charged = new Map();
22 for (const row of read(join(projectDir, ".hyperframes", "heygen-jobs.jsonl")).split("\n")) {
23 if (!row) continue;
24 const { key, credits } = JSON.parse(row);
25 if (key && typeof credits === "number") charged.set(key, credits);
26 }
27 return {
28 total: [...charged.values()].reduce((a, b) => a + b, 0),
29 keys: new Set([...charged].filter(([, c]) => c > 0).map(([k]) => k)),
30 };
33/** The engine shells out to `heygen`, which prices nothing here: under a limit those calls are refused, and
34 * `media-use generate` (priced, counted against the limit) is the way to make the same piece. */
35export function refuseUnderLimit(projectDir, what, generateType) {
36 const limit = creditLimit(projectDir);
37 if (limit === undefined) return;
38 throw new Error(
39 `media-use: ${what} cannot be priced here, so it cannot be kept under the run's credit limit of ${limit}; nothing was made. Make it with \`npx hyperframes media-use generate --type ${generateType}\`, which counts against the limit`,
40 );