Files
hyperframes/skills/media-use/scripts/lib/freeze.mjs
T
Miguel ÁngelandClaude Opus 4.8 73f6d3e5be feat(media-use): core infrastructure — manifest, cache, adopt, probe (#1682)
* feat(media-use): core infrastructure — manifest, cache, adopt, probe

Foundation for media-use — the media resolution layer for HyperFrames.

- manifest.mjs: JSONL read/write/find for .media/manifest.jsonl
- index-gen.mjs: regenerate agent-readable index.md from manifest
- cache.mjs: content-addressed global cache at ~/.media/ (SHA-256, sentinel)
- freeze.mjs: download URL or copy local file to .media/
- probe.mjs: extract duration/dimensions via ffprobe
- adopt.mjs: scan assets/ directory, register existing files with metadata
- 19 passing tests (manifest round-trip, cache, promote, index generation)

* fix(media-use): oxfmt formatting + cap freeze download size

Format adopt/cache/probe/manifest.test (CI oxfmt --check gate).
Cap freezeUrl downloads at 256MB so a hostile/runaway URL can't fill
the disk (addresses CodeQL #670: network data written to file).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 20:28:38 -04:00

27 lines
1.1 KiB
JavaScript

import { writeFileSync, copyFileSync, mkdirSync } from "node:fs";
import { dirname } from "node:path";
// ponytail: bound the download so a hostile/runaway URL can't fill the disk.
// 256MB covers any real media asset; raise if 4K video sources ever exceed it.
const MAX_FREEZE_BYTES = 256 * 1024 * 1024;
export async function freezeUrl(url, destPath) {
const res = await fetch(url);
if (!res.ok) throw new Error(`freeze failed: HTTP ${res.status} for ${String(url).slice(0, 80)}`);
const bytes = Buffer.from(await res.arrayBuffer());
if (bytes.length === 0)
throw new Error(`freeze failed: empty response for ${String(url).slice(0, 80)}`);
if (bytes.length > MAX_FREEZE_BYTES)
throw new Error(
`freeze failed: ${bytes.length} bytes exceeds ${MAX_FREEZE_BYTES} cap for ${String(url).slice(0, 80)}`,
);
mkdirSync(dirname(destPath), { recursive: true });
writeFileSync(destPath, bytes);
return bytes.length;
}
export function freezeLocalFile(srcPath, destPath) {
mkdirSync(dirname(destPath), { recursive: true });
copyFileSync(srcPath, destPath);
}