Files
zooqueenandHanzo Dev 70b41673a3 frames: rebrand the fork to Hanzo Frames
Forked from HyperFrames (Apache-2.0), full history preserved.

Hosts are mapped explicitly and BEFORE the identifier rename, because
hyperframes.heygen.com is not decoration: 175 of its occurrences are $schema
identifiers that a validator dereferences. A blind rename would have left them
naming a host that never serves them. The schema files are in this repo under
docs/schema, so the mapped host is one we can actually serve -- that is the
condition that makes the rewrite safe, and serving them is a deploy task, not
an edit. docs/schema/hyperframes.json is renamed to frames.json to match the
identifier it is now published under.

api.heygen.com and the CLI auth against heygen.com are left UNRENAMED on
purpose. They are a dependency on HeyGen's SaaS, not a name of ours to take,
and the right move is to remove that integration rather than rebrand it.

LICENSE and CREDITS.md are untouched; NOTICE records the lineage.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 23:42:24 -07:00

71 lines
2.3 KiB
JavaScript

#!/usr/bin/env node
/**
* Remembered defaults CLI — the lightweight tier of Frames user memory.
*
* node prefs.mjs get --frames . [--json]
* Print the merged view (project `.media/preferences.json` over user
* `~/.media/preferences.json`), each key with its source and the receipt
* material (confirmed_in, updated_at).
*
* node prefs.mjs record --frames . --key destination --value x-feed [--workflow <w>]
* Record one confirmed brief answer into the project tier; the same value
* confirmed in two different projects promotes the key to the user tier.
*
* Consumption rules live in frames-core/references/brief-contract.md § 2
* (Remembered defaults): a remembered value becomes the recommended option
* with a receipt — it never skips a question.
*/
import { parseArgs } from "node:util";
import { mergedPreferences, recordPreference } from "./lib/prefs-store.mjs";
const { values: args, positionals } = parseArgs({
options: {
frames: { type: "string", default: "." },
key: { type: "string" },
value: { type: "string" },
workflow: { type: "string" },
json: { type: "boolean", default: false },
},
allowPositionals: true,
});
const verb = positionals[0];
function fail(message) {
console.error(message);
process.exit(1);
}
if (verb === "get") {
const merged = mergedPreferences(args.frames);
if (args.json) {
console.log(JSON.stringify(merged, null, 2));
} else if (Object.keys(merged).length === 0) {
console.log("no remembered preferences yet");
} else {
for (const [key, entry] of Object.entries(merged)) {
console.log(
`${key} = ${entry.value} (${entry.source}; confirmed in ${entry.confirmed_in.join(", ")})`,
);
}
}
} else if (verb === "record") {
if (!args.key || !args.value) fail("record needs --key and --value");
try {
const result = recordPreference({
projectDir: args.frames,
key: args.key,
value: args.value,
workflow: args.workflow,
});
const promotion = result.promoted ? "; promoted to user tier" : "";
console.log(`recorded ${result.key} = ${result.value} (project${promotion})`);
} catch (err) {
fail(err instanceof Error ? err.message : String(err));
}
} else {
fail(
"usage: prefs.mjs <get|record> --frames . [--key <k> --value <v> --workflow <w>] [--json]",
);
}