From d6b4b900ffd76b05ea3b2884a1079a93f58e0b06 Mon Sep 17 00:00:00 2001 From: brunorezio Date: Sun, 26 Jul 2026 03:23:30 +0100 Subject: [PATCH] stop caching transcriptions and OCR Both endpoints kept a copy under cache/ and returned it on the next call, and also short-circuited when the sibling .md already existed. So a re-run never re-ran: a bad transcription stayed bad, and there was no way to ask for a fresh one. Every caller passes saveNextTo, so the cache-path return was dead code anyway. Both now always do the work and overwrite the sibling. CACHE_PREFIXES drops the two prefixes, since /save-result has nothing left to promote for them; the tts and audio caches are untouched. Also fixes the task runner output being unreadable in light mode. The panel is a fixed dark terminal, but stdout lines were classed text-foreground, which follows the app theme and renders black on the dark background. They now inherit the pre's own colour. Co-Authored-By: Claude Opus 5 --- src/servers/api/file-browser/router.ts | 60 ++----------------- .../components/TaskRunnerModal.tsx | 5 +- 2 files changed, 9 insertions(+), 56 deletions(-) diff --git a/src/servers/api/file-browser/router.ts b/src/servers/api/file-browser/router.ts index ee8472e4..1ffd6f03 100644 --- a/src/servers/api/file-browser/router.ts +++ b/src/servers/api/file-browser/router.ts @@ -602,7 +602,7 @@ router.get('/probe-folder', async (ctx) => { }); // Save a cached result (ocr/tts/transcriptions/audio) next to the original file -const CACHE_PREFIXES = ['cache/ocr/', 'cache/tts/', 'cache/transcriptions/', 'cache/audio/']; +const CACHE_PREFIXES = ['cache/tts/', 'cache/audio/']; router.post('/save-result', async (ctx) => { const user = ctx.get('user'); @@ -775,31 +775,8 @@ router.post('/ocr', async (ctx) => { const s = await stat(absPath); if (s.isDirectory()) throw errors.BAD_REQUEST('Cannot OCR a directory'); - const userDataDir = getUserDataDir(user.email); + // No caching: OCR is always run fresh and overwrites any previous result. const { dir, name } = parsePath(filePath.replace(/^\/+/, '')); - const cacheRel = dir ? `cache/ocr/${dir}/${name}.md` : `cache/ocr/${name}.md`; - const cacheAbs = resolve(userDataDir, cacheRel); - - // When saving next to file, check if the sibling .md already exists - if (saveNextTo) { - const siblingRel = dir ? `${dir}/${name}.md` : `${name}.md`; - const siblingAbs = resolveUserPath(rootDir, siblingRel); - if (existsSync(siblingAbs)) { - return ctx.json({ ocrPath: `/${siblingRel}`, ocrRoot: root ?? 'home', cached: true }); - } - } - - if (existsSync(cacheAbs)) { - if (saveNextTo) { - const text = await readFile(cacheAbs, 'utf-8'); - const siblingRel = dir ? `${dir}/${name}.md` : `${name}.md`; - const siblingAbs = resolveUserPath(rootDir, siblingRel); - await Bun.write(siblingAbs, text); - return ctx.json({ ocrPath: `/${siblingRel}`, ocrRoot: root ?? 'home', cached: true }); - } - const text = await readFile(cacheAbs, 'utf-8'); - return ctx.json({ text, ocrPath: cacheRel, ocrRoot: 'user-data', cached: true }); - } const ocrConfig = await readOcrConfig(); if (!ocrConfig) throw errors.BAD_REQUEST('OCR not configured — set it up in Settings → OCR'); @@ -851,9 +828,6 @@ router.post('/ocr', async (ctx) => { const json = (await res.json()) as { choices: { message: { content: string } }[] }; const text = json.choices[0]?.message?.content ?? ''; - await mkdir(dirname(cacheAbs), { recursive: true }); - await Bun.write(cacheAbs, text); - if (saveNextTo) { const siblingRel = dir ? `${dir}/${name}.md` : `${name}.md`; const siblingAbs = resolveUserPath(rootDir, siblingRel); @@ -861,7 +835,7 @@ router.post('/ocr', async (ctx) => { return ctx.json({ ocrPath: `/${siblingRel}`, ocrRoot: root ?? 'home', cached: false }); } - return ctx.json({ text, ocrPath: cacheRel, ocrRoot: 'user-data', cached: false }); + return ctx.json({ text, cached: false }); }); // Extract audio from video via ffmpeg with caching @@ -999,29 +973,8 @@ router.post('/transcribe', async (ctx) => { const s = await stat(absPath); if (s.isDirectory()) throw errors.BAD_REQUEST('Cannot transcribe a directory'); - const userDataDir = getUserDataDir(user.email); + // No caching: a transcription is always produced fresh and overwrites any previous one. const { dir, name } = parsePath(filePath.replace(/^\/+/, '')); - const cacheRel = dir ? `cache/transcriptions/${dir}/${name}.md` : `cache/transcriptions/${name}.md`; - const cacheAbs = resolve(userDataDir, cacheRel); - - if (saveNextTo) { - const siblingRel = dir ? `${dir}/${name}.md` : `${name}.md`; - const siblingAbs = resolveUserPath(rootDir, siblingRel); - if (existsSync(siblingAbs)) { - return ctx.json({ transcriptionPath: `/${siblingRel}`, transcriptionRoot: root ?? 'home', cached: true }); - } - } - - if (existsSync(cacheAbs)) { - if (saveNextTo) { - const text = await readFile(cacheAbs, 'utf-8'); - const siblingRel = dir ? `${dir}/${name}.md` : `${name}.md`; - const siblingAbs = resolveUserPath(rootDir, siblingRel); - await Bun.write(siblingAbs, text); - return ctx.json({ transcriptionPath: `/${siblingRel}`, transcriptionRoot: root ?? 'home', cached: true }); - } - return ctx.json({ transcriptionPath: cacheRel, transcriptionRoot: 'user-data', cached: true }); - } const sttConfig = await readSttConfig(); const whisperUrl = sttConfig?.url; @@ -1038,9 +991,6 @@ router.post('/transcribe', async (ctx) => { throw errors.BAD_REQUEST(err instanceof Error ? err.message : 'Transcription failed'); } - await mkdir(dirname(cacheAbs), { recursive: true }); - await Bun.write(cacheAbs, text); - if (saveNextTo) { const siblingRel = dir ? `${dir}/${name}.md` : `${name}.md`; const siblingAbs = resolveUserPath(rootDir, siblingRel); @@ -1048,7 +998,7 @@ router.post('/transcribe', async (ctx) => { return ctx.json({ transcriptionPath: `/${siblingRel}`, transcriptionRoot: root ?? 'home', cached: false }); } - return ctx.json({ transcriptionPath: cacheRel, transcriptionRoot: 'user-data', cached: false }); + return ctx.json({ text, cached: false }); }); // Search files by name diff --git a/src/workspaces/officerdev/src/apps/FileBrowser/FileBrowserApp/components/TaskRunnerModal.tsx b/src/workspaces/officerdev/src/apps/FileBrowser/FileBrowserApp/components/TaskRunnerModal.tsx index e9ad05fa..3dba643c 100644 --- a/src/workspaces/officerdev/src/apps/FileBrowser/FileBrowserApp/components/TaskRunnerModal.tsx +++ b/src/workspaces/officerdev/src/apps/FileBrowser/FileBrowserApp/components/TaskRunnerModal.tsx @@ -1228,12 +1228,15 @@ const ScriptRunner = ({ {runner.output.map((line, i) => ( 's light + // colour. `text-foreground` follows the app theme and rendered black-on-black in + // light mode. className={ line.stream === 'stderr' ? 'text-red-400' : line.stream === 'system' ? 'text-duck-teal/70' - : 'text-foreground' + : undefined } > {line.text}