focal-point: trajni predpomnilnik zarisov na /uploads, da deploy ne analizira vseh slik znova

This commit is contained in:
OpenClaw Agent
2026-08-30 09:33:27 +02:00
parent 8e29ad8e41
commit ed47a05bff
+40
View File
@@ -26,6 +26,42 @@ function loadDetected() {
const cache = new Map<string, { x: number; y: number }>();
// Trajni predpomnilnik LLM zarisov. Lezi na /opt/folxtv-uploads (bind mount),
// zato prezivi deploy in restart — brez tega je vsak deploy pomenil ponovno
// analizo vseh naslovnih slik na gpt-4o-mini.
const CACHE_PATH = path.join(process.cwd(), "client/public/uploads/focal_cache.json");
let cacheLoaded = false;
let cacheDirty = false;
function loadCache() {
if (cacheLoaded) return;
cacheLoaded = true;
try {
const raw = JSON.parse(fs.readFileSync(CACHE_PATH, "utf-8")) as Record<string, { x: number; y: number }>;
for (const [k, v] of Object.entries(raw)) {
if (v && typeof v.x === "number" && typeof v.y === "number") cache.set(k, v);
}
console.log("[focal-point] iz predpomnilnika nalozenih:", cache.size);
} catch {
console.log("[focal-point] predpomnilnika se ni, zacenjam prazen");
}
}
function saveCache() {
if (!cacheDirty) return;
try {
const obj: Record<string, { x: number; y: number }> = {};
for (const [k, v] of cache.entries()) obj[k] = v;
fs.mkdirSync(path.dirname(CACHE_PATH), { recursive: true });
fs.writeFileSync(CACHE_PATH + ".tmp", JSON.stringify(obj));
fs.renameSync(CACHE_PATH + ".tmp", CACHE_PATH);
cacheDirty = false;
console.log("[focal-point] predpomnilnik shranjen, vnosov:", cache.size);
} catch (e) {
console.log("[focal-point] predpomnilnika ni bilo mogoce shraniti:", (e as Error).message);
}
}
const manualOverrides: Record<string, { x: number; y: number }> = {
"/uploads/70-jahre-oberkrainer.webp": { x: 50, y: 55 },
};
@@ -46,6 +82,7 @@ Return ONLY a JSON object like {"x":42,"y":38} with no other text.`;
export async function analyzeFocalPoint(imagePath: string): Promise<{ x: number; y: number }> {
const originalPath = imagePath;
loadCache();
if (manualOverrides[originalPath]) {
cache.set(originalPath, manualOverrides[originalPath]);
return manualOverrides[originalPath];
@@ -104,6 +141,7 @@ export async function analyzeFocalPoint(imagePath: string): Promise<{ x: number;
y: Math.max(0, Math.min(100, Number(parsed.y) || 30)),
};
cache.set(originalPath, point);
cacheDirty = true;
return point;
}
} catch (e) {
@@ -120,10 +158,12 @@ export async function analyzeAllArticleImages(articles: Array<{ coverImage: stri
if (!article.coverImage) continue;
await analyzeFocalPoint(article.coverImage);
}
saveCache();
console.log("[focal-point] Analyzed", cache.size, "images");
}
export function getCachedFocalPoints(): Record<string, { x: number; y: number }> {
loadCache();
loadDetected();
const result: Record<string, { x: number; y: number }> = {};
for (const [key, value] of cache.entries()) {