← 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);
  }
})();