180 lines
6.2 KiB
JavaScript
180 lines
6.2 KiB
JavaScript
const Database = require("better-sqlite3");
|
|
const sqliteVec = require("sqlite-vec");
|
|
|
|
let archiveDb = null;
|
|
let intelligenceDb = null;
|
|
|
|
function getArchiveDb(dbPath) {
|
|
if (!archiveDb) {
|
|
archiveDb = new Database(dbPath, { readonly: true });
|
|
sqliteVec.load(archiveDb);
|
|
archiveDb.pragma("journal_mode = WAL");
|
|
}
|
|
return archiveDb;
|
|
}
|
|
|
|
function getIntelligenceDb(dbPath) {
|
|
if (!intelligenceDb) {
|
|
intelligenceDb = new Database(dbPath);
|
|
intelligenceDb.pragma("journal_mode = WAL");
|
|
}
|
|
return intelligenceDb;
|
|
}
|
|
|
|
function runMigrations(db) {
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS cursors (
|
|
key TEXT PRIMARY KEY,
|
|
value INTEGER
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS tracked_companies (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT,
|
|
ticker TEXT,
|
|
aliases TEXT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS article_queue (
|
|
id INTEGER PRIMARY KEY,
|
|
article_id INTEGER UNIQUE,
|
|
status TEXT DEFAULT 'pending',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS event_knowledge (
|
|
id INTEGER PRIMARY KEY,
|
|
event_id INTEGER,
|
|
company_id INTEGER,
|
|
type TEXT,
|
|
data TEXT,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS company_embeddings (
|
|
company_id INTEGER PRIMARY KEY,
|
|
embedding BLOB NOT NULL,
|
|
model TEXT NOT NULL,
|
|
generated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS event_predictions (
|
|
id INTEGER PRIMARY KEY,
|
|
event_id INTEGER,
|
|
company_id INTEGER,
|
|
type TEXT,
|
|
direction TEXT,
|
|
magnitude TEXT,
|
|
timeframe TEXT,
|
|
rationale TEXT,
|
|
event_date TEXT,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS company_facts (
|
|
id INTEGER PRIMARY KEY,
|
|
company_id INTEGER,
|
|
type TEXT,
|
|
claim TEXT,
|
|
confidence TEXT,
|
|
confirmation_count INTEGER DEFAULT 1,
|
|
first_seen_at DATETIME,
|
|
last_seen_at DATETIME,
|
|
last_event_id INTEGER,
|
|
supporting_event_ids TEXT
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_company_facts_unique ON company_facts (company_id, claim);
|
|
|
|
CREATE TABLE IF NOT EXISTS company_relationships (
|
|
id INTEGER PRIMARY KEY,
|
|
from_company_id INTEGER,
|
|
relationship_type TEXT,
|
|
to_entity TEXT,
|
|
to_company_id INTEGER,
|
|
confidence TEXT,
|
|
confirmation_count INTEGER DEFAULT 1,
|
|
first_seen_at DATETIME,
|
|
last_seen_at DATETIME,
|
|
supporting_event_ids TEXT
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_company_relationships_unique
|
|
ON company_relationships (from_company_id, relationship_type, to_entity);
|
|
|
|
`);
|
|
}
|
|
|
|
function runColumnMigrations(db) {
|
|
try { db.exec("ALTER TABLE event_predictions ADD COLUMN event_date TEXT"); } catch (_) {}
|
|
try { db.exec("ALTER TABLE event_knowledge ADD COLUMN event_date TEXT"); } catch (_) {}
|
|
|
|
}
|
|
|
|
function seedCompanies(db) {
|
|
const count = db.prepare("SELECT COUNT(*) as c FROM tracked_companies").get().c;
|
|
if (count > 0) return;
|
|
|
|
const insert = db.prepare(
|
|
"INSERT INTO tracked_companies (name, ticker, aliases) VALUES (?, ?, ?)"
|
|
);
|
|
|
|
const companies = [
|
|
// semiconductors
|
|
{ name: "NVIDIA", ticker: "NVDA", aliases: ["Nvidia Corporation"] },
|
|
{ name: "TSMC", ticker: "TSM", aliases: ["Taiwan Semiconductor", "Taiwan Semiconductor Manufacturing Company"] },
|
|
{ name: "ASML", ticker: "ASML", aliases: ["ASML Holding"] },
|
|
{ name: "Intel", ticker: "INTC", aliases: ["Intel Corporation"] },
|
|
{ name: "AMD", ticker: "AMD", aliases: ["Advanced Micro Devices"] },
|
|
{ name: "Qualcomm", ticker: "QCOM", aliases: ["Qualcomm Incorporated"] },
|
|
{ name: "Broadcom", ticker: "AVGO", aliases: ["Broadcom Inc"] },
|
|
{ name: "Micron", ticker: "MU", aliases: ["Micron Technology"] },
|
|
{ name: "Texas Instruments", ticker: "TXN", aliases: ["TI"] },
|
|
{ name: "Applied Materials", ticker: "AMAT", aliases: ["Applied Materials Inc"] },
|
|
{ name: "Lam Research", ticker: "LRCX", aliases: ["Lam Research Corporation"] },
|
|
{ name: "KLA Corporation", ticker: "KLAC", aliases: ["KLA"] },
|
|
{ name: "Samsung", ticker: "005930.KS", aliases: ["Samsung Electronics", "Samsung Group"] },
|
|
{ name: "SK Hynix", ticker: "000660.KS", aliases: ["Hynix"] },
|
|
|
|
// big tech / cloud
|
|
{ name: "Microsoft", ticker: "MSFT", aliases: ["Microsoft Corporation"] },
|
|
{ name: "Apple", ticker: "AAPL", aliases: ["Apple Inc"] },
|
|
{ name: "Alphabet", ticker: "GOOGL", aliases: ["Google", "Google LLC", "DeepMind"] },
|
|
{ name: "Amazon", ticker: "AMZN", aliases: ["Amazon Web Services", "AWS"] },
|
|
{ name: "Meta", ticker: "META", aliases: ["Meta Platforms", "Facebook"] },
|
|
{ name: "Tesla", ticker: "TSLA", aliases: ["Tesla Inc", "Tesla Motors"] },
|
|
|
|
// AI / infrastructure
|
|
{ name: "OpenAI", ticker: "OPENAI", aliases: ["Open AI"] },
|
|
{ name: "Anthropic", ticker: "ANTHROPIC", aliases: [] },
|
|
{ name: "xAI", ticker: "XAI", aliases: ["x.AI"] },
|
|
{ name: "Palantir", ticker: "PLTR", aliases: ["Palantir Technologies"] },
|
|
{ name: "Super Micro Computer", ticker: "SMCI", aliases: ["Supermicro", "SMCI"] },
|
|
{ name: "Arista Networks", ticker: "ANET", aliases: ["Arista"] },
|
|
|
|
// networking / hardware
|
|
{ name: "Cisco", ticker: "CSCO", aliases: ["Cisco Systems"] },
|
|
{ name: "Marvell Technology", ticker: "MRVL", aliases: ["Marvell"] },
|
|
{ name: "Arm Holdings", ticker: "ARM", aliases: ["Arm", "ARM Ltd"] },
|
|
|
|
// enterprise software
|
|
{ name: "Oracle", ticker: "ORCL", aliases: ["Oracle Corporation"] },
|
|
{ name: "Salesforce", ticker: "CRM", aliases: ["Salesforce Inc"] },
|
|
{ name: "SAP", ticker: "SAP", aliases: ["SAP SE"] },
|
|
{ name: "ServiceNow", ticker: "NOW", aliases: [] },
|
|
|
|
// storage / infra
|
|
{ name: "Western Digital", ticker: "WDC", aliases: ["WD", "Western Digital Corporation"] },
|
|
{ name: "Seagate", ticker: "STX", aliases: ["Seagate Technology"] },
|
|
{ name: "Pure Storage", ticker: "PSTG", aliases: [] },
|
|
];
|
|
|
|
for (const c of companies) {
|
|
insert.run(c.name, c.ticker, JSON.stringify(c.aliases));
|
|
}
|
|
|
|
console.log(`[db] seeded ${companies.length} tracked companies`);
|
|
}
|
|
|
|
module.exports = { getArchiveDb, getIntelligenceDb, runMigrations, runColumnMigrations, seedCompanies };
|