← back to Ventura Corridor
src/jobs/regen_thin.ts
46 lines
/**
* Identify magazine_features with thin editorial (<MIN_LEN chars) and
* call /api/magazine/:id/regen to refresh them via Mac1 Ollama.
*
* $ npx tsx src/jobs/regen_thin.ts # rescue all thin features
* $ npx tsx src/jobs/regen_thin.ts 20 # max 20
*/
import 'dotenv/config';
import { pool, query } from '../../db/pool.ts';
const N_MAX = parseInt(process.argv.find(a => /^\d+$/.test(a)) || '50', 10);
const MIN_LEN = parseInt(process.env.MIN_LEN || '200', 10);
const SERVER = process.env.VC_URL || 'http://127.0.0.1:9780';
const AUTH = 'Basic ' + Buffer.from('admin:DWSecure2024!').toString('base64');
async function main() {
const r = await query(
`SELECT id, length(editorial) AS len, headline FROM magazine_features
WHERE editorial IS NULL OR length(editorial) < $1
ORDER BY generated_at ASC
LIMIT $2`,
[MIN_LEN, N_MAX]
);
console.log(`[regen_thin] ${r.rowCount} features below ${MIN_LEN} chars to refresh`);
let ok = 0, fail = 0;
for (const row of r.rows) {
try {
const t0 = Date.now();
const resp = await fetch(`${SERVER}/api/magazine/${row.id}/regen`, {
method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: AUTH }
});
if (!resp.ok) throw new Error(`${resp.status}: ${(await resp.text()).slice(0, 100)}`);
const j = await resp.json();
console.log(` ✓ ${row.id} (${row.len || 0}ch → fresh, ${Date.now() - t0}ms) "${(j.headline || '').slice(0, 50)}"`);
ok++;
} catch (e: any) {
console.log(` ✕ ${row.id} (${row.len || 0}ch) — ${e.message.slice(0, 80)}`);
fail++;
}
}
console.log(`[regen_thin] ok=${ok} fail=${fail}`);
await pool.end();
}
main().catch(e => { console.error(e); process.exit(1); });