Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Generate images via OpenAI, Google, OpenRouter, DashScope, Jimeng, Seedream, and Replicate APIs with batch support.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/codex-imagegen/cache.ts
1import { createHash } from "node:crypto";2import { mkdir, readFile, writeFile, copyFile, stat } from "node:fs/promises";3import { existsSync, openSync, closeSync } from "node:fs";4import path from "node:path";5import { setTimeout as delay } from "node:timers/promises";67export function cacheKey(prompt: string, aspect: string, refs: string[]): string {8const h = createHash("sha256");9h.update(prompt);10h.update("|");11h.update(aspect);12h.update("|");13for (const r of [...refs].sort()) h.update(r);14return h.digest("hex").slice(0, 16);15}1617export async function lookupCache(cacheDir: string, key: string): Promise<string | null> {18const entry = path.join(cacheDir, `${key}.png`);19try {20const s = await stat(entry);21if (s.size > 1000) return entry;22} catch {}23return null;24}2526export async function storeCache(cacheDir: string, key: string, sourcePath: string): Promise<void> {27await mkdir(cacheDir, { recursive: true });28const entry = path.join(cacheDir, `${key}.png`);29await copyFile(sourcePath, entry);30}3132export class FileLock {33private fd: number | null = null;34constructor(private lockPath: string) {}3536async acquire(timeoutMs = 30_000): Promise<void> {37const start = Date.now();38await mkdir(path.dirname(this.lockPath), { recursive: true });39while (Date.now() - start < timeoutMs) {40try {41this.fd = openSync(this.lockPath, "wx");42return;43} catch (e: any) {44if (e.code !== "EEXIST") throw e;45if (await this.isStale()) {46try {47await this.release(true);48} catch {}49continue;50}51await delay(200);52}53}54throw new Error(`Failed to acquire lock at ${this.lockPath} within ${timeoutMs}ms`);55}5657private async isStale(): Promise<boolean> {58try {59const s = await stat(this.lockPath);60return Date.now() - s.mtimeMs > 10 * 60 * 1000;61} catch {62return true;63}64}6566async release(force = false): Promise<void> {67if (this.fd != null) {68try {69closeSync(this.fd);70} catch {}71this.fd = null;72}73if (existsSync(this.lockPath) || force) {74const { unlink } = await import("node:fs/promises");75try {76await unlink(this.lockPath);77} catch {}78}79}80}81