mirror of
https://github.com/hanzoai/frames.git
synced 2026-09-24 00:08:03 +00:00
The workflow skills, the CLI reference, and the guides described a vendor's services: a separate account to sign into, a credential file beside the project, a music library and asset search that are not ours, and preview media on a CDN we do not run. Auth is now one Hanzo IAM token in $HANZO_API_KEY, read from Hanzo KMS — one credential for voice, music, sound effects, images, video, the shared catalog, and cloud rendering. The credential guide, the cloud-render pages, and the CLI auth reference all say the same thing, because there is now only one thing to say. Docs previews resolve from the docs site's own /images/ path, produced by our own generator. They are not committed (docs/images/ is ignored), so a deploy must run `bun run generate:catalog-previews` first — the same gap as before, minus a CDN we cannot publish to. Element grounding calls zen-vl through api.hanzo.ai rather than a third-party vision endpoint, and the LUT library builds every look from params, so no look needs a host at all. Command examples read `npx @hanzo/frame` / `hanzo frame` throughout. Three navigation entries left dangling by the rebrand now resolve. The changelog and the weekly archive keep their entries as written and say plainly that pre-port entries describe the upstream product.
41 lines
1.5 KiB
JavaScript
41 lines
1.5 KiB
JavaScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { mapWithConcurrency } from "./concurrency.mjs";
|
|
|
|
// Regression: audio.mjs used a bare Promise.all(lines.map(synthLine)) to
|
|
// synthesize every TTS line at once, opening two requests per line
|
|
// concurrently — a long script got throttled and the whole batch failed
|
|
// together. mapWithConcurrency is the extracted cap; test it in isolation
|
|
// since audio.mjs itself is a script (CLI/exit side effects on import).
|
|
test("processes every item and preserves input order regardless of completion order", async () => {
|
|
const order = [5, 1, 3, 2, 4];
|
|
const results = await mapWithConcurrency(order, 2, async (n) => {
|
|
await new Promise((r) => setTimeout(r, n));
|
|
return n * 10;
|
|
});
|
|
assert.deepEqual(results, [50, 10, 30, 20, 40]);
|
|
});
|
|
|
|
test("never runs more than `limit` at once", async () => {
|
|
let inFlight = 0;
|
|
let maxInFlight = 0;
|
|
const items = Array.from({ length: 10 }, (_, i) => i);
|
|
await mapWithConcurrency(items, 3, async () => {
|
|
inFlight++;
|
|
maxInFlight = Math.max(maxInFlight, inFlight);
|
|
await new Promise((r) => setTimeout(r, 5));
|
|
inFlight--;
|
|
});
|
|
assert.equal(maxInFlight, 3);
|
|
});
|
|
|
|
test("limit larger than the item count runs everything without hanging", async () => {
|
|
const results = await mapWithConcurrency([1, 2], 10, async (n) => n * 2);
|
|
assert.deepEqual(results, [2, 4]);
|
|
});
|
|
|
|
test("empty input resolves to an empty array", async () => {
|
|
const results = await mapWithConcurrency([], 4, async (n) => n);
|
|
assert.deepEqual(results, []);
|
|
});
|