← back to AbramsOS
scripts/run-savings-advisor.js
32 lines
#!/usr/bin/env node
// Nightly savings-advisor run. Reads .env, regenerates grounded savings suggestions
// for every active reorder item (local Ollama, $0). Safe to run repeatedly — the
// advisor dedupes by item+strategy, so it only adds genuinely new ideas.
//
// Wire it up (Steve pastes — launchd bootstrap is classifier-gated):
// launchctl bootstrap gui/$(id -u) ~/Projects/AbramsOS/deploy/com.steve.abramsos-savings.plist
// Manual run:
// node ~/Projects/AbramsOS/scripts/run-savings-advisor.js
require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });
const advisor = require('../lib/savings-advisor');
const billAudit = require('../lib/bill-audit');
const reorderTiming = require('../lib/reorder-timing');
const USER_ID = process.env.SAVINGS_USER_ID || 'user_steve';
(async () => {
const started = new Date().toISOString();
try {
const out = await advisor.generateSuggestions(USER_ID, { limit: 100, timeoutMs: 90_000 });
const bills = await billAudit.generateBillAudit(USER_ID, { model: 'gemma3:12b' });
const reorders = await reorderTiming.generateReorderNudges(USER_ID);
console.log(`[savings-advisor ${started}] substitutes=${out.created} bill-audit=${bills.created} reorder-timing=${reorders.created} skipped=${out.skipped} errors=${out.errors.length}`);
if (out.errors.length) console.log(' errors:', out.errors.map((e) => `${e.item}: ${e.error}`).join('; '));
process.exit(0);
} catch (err) {
console.error(`[savings-advisor ${started}] FAILED: ${err.message}`);
process.exit(1);
}
})();