Snapshot: full project state

This commit is contained in:
2026-10-06 23:43:21 -07:00
commit 1551408fc5
37 changed files with 2827 additions and 0 deletions

288
db.py Normal file
View File

@@ -0,0 +1,288 @@
# Procyon — Job Hunt Workflow Engine
# Multi-step pipeline: discover -> score -> tailor -> audit -> approve -> send -> track
import sqlite3
import os
from datetime import datetime, timezone
DB_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
DB = os.path.join(DB_DIR, 'procyon.db')
def now():
return datetime.now(timezone.utc).isoformat()
def get_conn():
os.makedirs(DB_DIR, exist_ok=True)
conn = sqlite3.connect(DB, timeout=15)
conn.row_factory = sqlite3.Row
return conn
SCHEMA = """
CREATE TABLE IF NOT EXISTS jobs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
company TEXT,
location TEXT,
url TEXT UNIQUE,
source TEXT,
description TEXT,
posted_at TEXT,
discovered_at TEXT,
fit_score REAL,
opinion TEXT,
contact_email TEXT,
status TEXT DEFAULT 'new'
);
CREATE TABLE IF NOT EXISTS applications (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_id INTEGER NOT NULL,
resume_path TEXT,
tailored_pdf TEXT,
email_subject TEXT,
email_body TEXT,
audit_json TEXT,
status TEXT DEFAULT 'draft',
outcome TEXT,
sent_at TEXT,
created_at TEXT,
notes TEXT
);
CREATE TABLE IF NOT EXISTS outcomes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
application_id INTEGER NOT NULL,
stage TEXT,
happened_at TEXT,
notes TEXT
);
CREATE TABLE IF NOT EXISTS audit_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
application_id INTEGER,
job_id INTEGER,
item TEXT,
result TEXT,
detail TEXT,
checked_at TEXT
);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT
);
CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status);
CREATE INDEX IF NOT EXISTS idx_apps_job ON applications(job_id);
"""
DEFAULTS = {
'llm_base_url': 'http://10.30.20.69:11434',
'llm_model': 'qwen3.5:9b',
'llm_timeout': '120',
'smtp_host': 'smtp.mail.me.com',
'smtp_port': '587',
'smtp_user': '',
'smtp_pass': '',
'from_email': 'indianaholmes1@icloud.com',
'from_name': 'Indiana Holmes',
'resume_phone': '(425) 280-0023',
'resume_email': 'indianaholmes1@icloud.com',
'website': 'https://thetempleofdoom.com',
'proxy_url': '',
'master_resume': '',
'rss_feeds': '',
'headless_browser': '0',
'firecrawl_url': 'http://10.30.20.182:3002',
'firecrawl_enabled': '1',
'firecrawl_queries': 'remote software engineer\nremote devops engineer\nremote platform engineer\nremote linux administrator\nwork from home software engineer seattle\nremote infrastructure engineer',
'autopilot_enabled': '1',
'autopilot_interval_hours': '6',
'autopilot_max_prepare': '3',
'auto_send': '0',
}
def init_db():
conn = get_conn()
try:
conn.executescript(SCHEMA)
for k, v in DEFAULTS.items():
conn.execute('INSERT OR IGNORE INTO settings(key, value) VALUES (?, ?)', (k, v))
conn.commit()
finally:
conn.close()
def get_settings():
conn = get_conn()
try:
rows = conn.execute('SELECT key, value FROM settings').fetchall()
return {r['key']: r['value'] for r in rows}
finally:
conn.close()
def get_setting(key, default=None):
conn = get_conn()
try:
r = conn.execute('SELECT value FROM settings WHERE key = ?', (key,)).fetchone()
return r['value'] if r else default
finally:
conn.close()
def set_setting(key, value):
conn = get_conn()
try:
conn.execute(
'INSERT INTO settings(key, value) VALUES (?, ?) '
'ON CONFLICT(key) DO UPDATE SET value = excluded.value',
(key, str(value)),
)
conn.commit()
finally:
conn.close()
# ---- jobs ----
def upsert_job(title, company, location, url, source, description, posted_at=None):
conn = get_conn()
try:
if url:
existing = conn.execute('SELECT id FROM jobs WHERE url = ?', (url,)).fetchone()
if existing:
return existing['id']
cur = conn.execute(
'INSERT INTO jobs(title, company, location, url, source, description, posted_at, discovered_at) '
'VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
(title, company, location, url, source, description, posted_at, now()),
)
conn.commit()
return cur.lastrowid
finally:
conn.close()
def list_jobs(status=None, limit=100, offset=0):
conn = get_conn()
try:
q = 'SELECT * FROM jobs'
args = []
if status:
q += ' WHERE status = ?'
args.append(status)
q += ' ORDER BY COALESCE(fit_score, -1) DESC, discovered_at DESC LIMIT ? OFFSET ?'
args += [limit, offset]
return [dict(r) for r in conn.execute(q, args).fetchall()]
finally:
conn.close()
def get_job(job_id):
conn = get_conn()
try:
r = conn.execute('SELECT * FROM jobs WHERE id = ?', (job_id,)).fetchone()
return dict(r) if r else None
finally:
conn.close()
def set_job_status(job_id, status):
conn = get_conn()
try:
conn.execute('UPDATE jobs SET status = ? WHERE id = ?', (status, job_id))
conn.commit()
finally:
conn.close()
def update_job_score(job_id, score, opinion):
conn = get_conn()
try:
conn.execute('UPDATE jobs SET fit_score = ?, opinion = ?, status = ? WHERE id = ?',
(score, opinion, 'scored', job_id))
conn.commit()
finally:
conn.close()
def set_job_contact_email(job_id, email):
conn = get_conn()
try:
conn.execute('UPDATE jobs SET contact_email = ? WHERE id = ?', (email or '', job_id))
conn.commit()
finally:
conn.close()
# ---- applications ----
def create_application(job_id, subject='', body=''):
conn = get_conn()
try:
cur = conn.execute(
'INSERT INTO applications(job_id, email_subject, email_body, created_at) VALUES (?, ?, ?, ?)',
(job_id, subject, body, now()),
)
conn.commit()
return cur.lastrowid
finally:
conn.close()
def update_application(app_id, **fields):
conn = get_conn()
try:
cols = ', '.join(f'{k} = ?' for k in fields)
conn.execute(f'UPDATE applications SET {cols} WHERE id = ?', (*fields.values(), app_id))
conn.commit()
finally:
conn.close()
def get_application(app_id):
conn = get_conn()
try:
r = conn.execute('SELECT * FROM applications WHERE id = ?', (app_id,)).fetchone()
return dict(r) if r else None
finally:
conn.close()
def list_applications(limit=100):
conn = get_conn()
try:
q = ('SELECT a.*, j.title, j.company, j.url FROM applications a '
'LEFT JOIN jobs j ON j.id = a.job_id ORDER BY a.id DESC LIMIT ?')
return [dict(r) for r in conn.execute(q, (limit,)).fetchall()]
finally:
conn.close()
def add_outcome(app_id, stage, notes=''):
conn = get_conn()
try:
conn.execute('INSERT INTO outcomes(application_id, stage, happened_at, notes) VALUES (?, ?, ?, ?)',
(app_id, stage, now(), notes))
conn.execute('UPDATE applications SET outcome = ? WHERE id = ?', (stage, app_id))
conn.commit()
finally:
conn.close()
def add_audit(app_id, job_id, item, result, detail):
conn = get_conn()
try:
conn.execute('INSERT INTO audit_log(application_id, job_id, item, result, detail, checked_at) '
'VALUES (?, ?, ?, ?, ?, ?)', (app_id, job_id, item, result, detail, now()))
conn.commit()
finally:
conn.close()
def get_audit(app_id):
conn = get_conn()
try:
return [dict(r) for r in conn.execute(
'SELECT * FROM audit_log WHERE application_id = ? ORDER BY id', (app_id,)).fetchall()]
finally:
conn.close()